Проблемы автоматизации приемочного тестирования программного обеспечения при использовании подхода "разработка, управляемая описанием поведения"

В дальнейшем предполагается исследова- женных методов и проведение его детального ние построения нового языка программиро- сравнения с существующими промышленными вания на основе тесной интеграции предло- языками.

СПИСОК ЛИТЕРАТУРЫ

1. Pierce, B. Types and Programming Languages [Text] / B. Pierce. -MIT Press, 2002.

2. Mitchell, J.C. Concepts in programming languages [Text] / J.C. Mitchell. -Cambridge University Press, 2003. -278 p.

3. Biancuzzi, F. Masterminds of Programming [Text] / F. Biancuzzi, S. Warden. -O'Reilly Media, 2009.

4. Odersky, M. An overview of the Scala programming language [Text] / M. Odersky // ACM SIGPLAN. -2006.

5. Scharli, N. Traits: Composable Units of Behavior [Text] / N. Scharli, S. Ducasse, O. Nierstrasz [et al.]. -Springer - Science, 2003. -P. 327-339.

6. Musser, D. Generic Programming [Text] / D. Musser, A. Stepanov // Symbolic and Algebraic Computation: International symp. -1988. -P. 13-25.

7. Cardelli, L. On Binary Methods [Text] / L. Cardelli // Theory and Practice of Object Systems. -1995. -P. 221-242.

УДК 004.413:004.414.3:004.415.53

Е.В. Пышкин

ПРОБЛЕМЫ АВТОМАТИЗАцИИ ПРИЕМОЧНОГО ТЕСТИРОВАНИЯ ПРОГРАММНОГО ОБЕСПЕЧЕНИЯ ПРИ ИСПОЛЬЗОВАНИИ ПОДХОДА «РАЗРАБОТКА, УПРАВЛЯЕМАЯ ОПИСАНИЕМ ПОВЕДЕНИЯ»

Подход «разработка, управляемая описанием поведения» (behavior driven development, BDD [1]) развивается в рамках гибких (agile) подходов к разработке программного обеспечения давно, тем не менее в отечественных источниках эта тема освещена недостаточно. Метод BDD возник и развивается и как технология, нацеленная на автоматизацию тестирования готового программного продукта заказчиком, и как проектная практика сродни практике «тесты вначале» и основанной на ней методологии разработки через тестирование (test-driven design). Действительно, использование модульных тестов как центрального элемента подхода «тесты вначале» не эквивалентно тестированию в строгом смысле этого понятия: речь идет здесь не столько о тестировании как динамическом методе обеспечения качества, сколько о применении определенных практик тестирования в процессе реализации функциональных требований [2]. Тесты в данном случае, фактически, выступают в качестве альтернативной формы записи этих функциональных требований.

Приемочные тесты относятся к категории тестов, труднее других поддающихся формализации. Одна из задач, решаемых в рамках подхода

«разработка, управляемая описанием поведения», собственно, и состоит в создании определенной инфраструктуры, которая позволила бы осуществить переход от описания тестовых сценариев, сформулированных заказчиком, к тестовым классам и методам для модульного тестирования. При этом предполагается использование существующих библиотек и фреймворков модульного тестирования (unit-тестирования), например библиотеки JUnit для языка Java.

Разработка через описание поведения: конструктивная идея

Согласно известной V-модели организации разработки, приемочные тесты - это своего рода элемент верхнего слоя абстрактной модели процесса разработки (рис. 1).

Приемочные тесты в наибольшей степени сфокусированы на пользовательских требованиях (нередко неясных и плохо сформулированных) и нацелены на процесс верификации, вообще говоря, уже протестированной системы, с участием представителей заказчика. Ошибки, выявляемые в ходе приемочных испытаний, как правило, означают, что либо существует неадек-

Рис. 1. Приемочные тесты в У-модели разработки ) процесс; (--) результат процесса; (<}----) верификация

(

ватность в представлении требований заказчика в технической спецификации, либо обнаруживается разрыв в понимании задачи заказчиками и разработчиками. И то, и другое относится к критическим рискам, возникающим при разработке программного обеспечения, а следовательно, является серьезной проблемой управления разработкой. Поэтому развитие и совершенствование средств, предназначенных для снижения рисков возникновения подобных проблем, представляется актуальным направлением работы инженеров и системных аналитиков.

Основополагающая идея подхода BDD состоит в создании инфраструктуры, позволяющей представителям коллектива разработчиков и заказчикам двигаться навстречу друг другу: первые получают возможность реализовать приемочные тесты максимально близко к стандартной модели модульных тестов (обеспечивающих такие важные свойства agile-практик, как повторяемость, воспроизводимость, инкрементность разработки и т. д.), а вторые могут лучше видеть, каким образом представленные на естественном языке пользовательские сценарии отображаются в элементы тестового программного кода, т. е. в классы и методы на соответствующем языке программирования. Отметим, что BDD относится к развивающимся подходам, основополагающие концепции

которых являются предметом обсуждений, при этом не все ключевые определения вполне ясны и сформированы [3-5].

В чем же состоят основные трудности, с которыми сталкиваются и разработчики, и потребители?

Для того чтобы исполнить тесты, необходимо исполнить соответствующий тестовому сценарию фрагмент кода. Это означает, что нужно понимать данный код, а также уметь сформировать контекст, в котором он выполняется, определить пред- и постусловия, инварианты и т. д. Нормально, что у заказчиков и тем более пользователей обо всем этом имеются в лучшем случае весьма смутные представления. Тем не менее им важно убедиться в выполнении требований технической спецификации и должном функционировании системы.

Свою долю проблем в почти линейный процесс от требований к реализующему их коду (рис. 2) вносят неизбежные изменения, происходящие как на стороне заказчика (и ведущие к изменению требований - ведь понимание заказчиком своих интересов и потребностей тоже развивается вместе с процессом создания системы), так и на стороне разработчика. При этом очевидно, что изменения в разрабатываемом коде (например, в процессе рефакторинга) вовсе не обязательно связаны с изменениями в требованиях.

Рис. 2. От требований к модульным тестам

Разработка через описание поведения: от приемочных тестов к тестовым классам

Что же предложено «методологами» BDD? Рассмотрим небольшой пример, иллюстрирующий применение BDD в ходе разработки и тестирования небольшого приложения.

Предположим, что разрабатывается компонент информационной системы, обеспечивающий символьные и численные математические

Given a derivative function test When the input function is xA2+3 Then the derivative function is 2*x Then the derivative value for x=1 is 2

Листинг 1. Пример текстового сценария

Очевидно, что могут существовать фрагменты текста сценария, которые неизменны от теста к тесту, в то время как отдельные элементы могут изменять свои значения, например When the input function is 1/x Then the derivative function is -1/xA2

Соответственно, изменяющиеся элементы тестового сценария разумно сделать параметрами теста: структура теста повторяется, параметры изменяются. Методология BDD предполагает, что на основе подобных пользовательских сценариев (narrative-сценариев) создаются соответствующие модульные тесты. Получаемые тесты обеспечивают возможность автоматического запуска, модификации, получения отчетов и интеграции со средой разработки. Иными словами, BDD создает пространство для лучшей совместной работы и лучшего взаимопонимания двух «конкурирующих» сторон (здесь термин «конкуренция» используется в том исконном смысле, в котором оно вошло в информатику: «сонаправ-ленная работа нескольких участников»).

вычисления.

Тесты правильного функционирования компонента могут быть сформулированы в виде текстовых сценариев на «упрощенном английском языке». Ниже мы рассматриваем последовательность преобразований в том виде, в каком она реализована в модели JBehave [6], хотя аналогичные этапы свойственны и другим реализациям методологии BDD (Листинг 1).

where accuracy is 1e-6

Основные шаги процесса BDD-разработки состоят в следующем.

1. Написание тестовых сценариев, или историй.

2. Отображение этих сценариев в unit-тесты.

3. Описание конфигурации тестовой сборки и запуска.

4. Запуск тестов (например, с использованием возможностей соответствующей среды разработки).

5. Анализ результатов, подготовка отчетов по результатам тестирования, формулирование требований по внесению изменений в программное обеспечение или по формированию новых тестовых сценариев.

Отображение представленного выше сценария проверки вычисления производной функции и значения этой функции в заданной точке в соответствующие модульные тесты (которые в рамках JBehave называются candidate steps), может выглядеть так, как представлено в листинге 2 (мы выделяем здесь наиболее существенный фрагмент кода тестового класса, определяемого в соответствии с правилами JBehave).

@Given

public void givenADerivativeFunctionTest () { // Объект-вычислитель calc = factory.createCalculator ();

// Объект для сравнения функций, заданных символически comparator = factory.createSymbolicFunctionComparator();

}

@When(«the input function is $input») public void theInputFunction(String input) { // Вычисляем производную для функции input calc.derivative(input);

}

@Then(«the derivative function is $result») public void theDerivativeFunction( String derivative ) { // Контролируем результат символьных вычислений

assertTrue(comparator.equal(calc.getDerivative(),result);

}

@Then(«the derivative value for x=$x is $y where accuracy is $acr») public void theDerivativeValue(double x,double y,double acr) { // Контролируем корректность значения производной // в заданной точке с заданной точностью double derivativeVal = calc.getDerivativeValue(x); assertEquals(derivativeVal, y, acr );

}

Листинг 2. Методы тестового класса JBehave

Полученные в результате такого преобразования тесты могут быть исполнены с подстановкой в качестве аргументов значений, извлекаемых из тестовых сценариев.

Отметим, что в текущей реализации JBehave (равно, как и многих других средств) преобразование из текстового сценария в методы тестового класса, а также формирование значений соответ-

ствующих атрибутов, происходит большей частью вручную. Несмотря на то что переходы от элементов пап^^е-сценария к методам тестового класса происходят на основе регулярных правил, осуществление такого перехода требует участия разработчика. Актуальной представляется задача автоматизации формирования каркаса тестового класса (листинг 3).

@Given

public void aDerivativeFunctionTest() { // TODO: Write the initial condition throw new UnsupportedOperationException();

}

@When

public void theInputFunction( String input ) { // TODO: Write the unit test action throw new UnsupportedOperationException();

}

@Then

public void theDerivativeFunction( String result ) { // TODO: Write the assertion code throw new UnsupportedOperationException();

}

//...

Листинг 3. Каркас тестового класса

Рис. 3. Процесс разметки narrative-сценария

При постановке и решении задачи автоматизации следует иметь в виду ряд вопросов, ответы на которые неоднозначны, в частности:

• каким образом и из какой части пользовательского сценария формируется имя соответствующего метода тестового класса;

• какие элементы сценария должны быть параметрами методов;

• каковы типы этих параметров.

Таким образом, несмотря на то, что создаваемый тестовый класс для модульного тестирования напоминает тестовый сценарий с точностью до структуры кода на языке программирования, решение задачи автоматической генерации та-

A derivative function test

The input function is xA2+3

The derivative function is 2*x

The derivative value for x=1 is 2 where

Листинг 4. Сценарий до разметки

Далее возникает задача, которую мы называем задачей разметки тестового сценария (рис. 3).

Фактически, данная разметка (для которой предлагается разработать соответствующие инструментальные средства) призвана, с одной стороны, осуществить переход от плохо структурированного сценария к структурированному описанию, ориентированному на последующую

кого каркаса не лишено трудностей (в т. ч. из-за сформулированных выше неоднозначностей). Сам сценарий может основываться на шаблоне (так, например, делается в SpecFlow - реализации BDD для Visual Studio [7]). Отметим, однако, что правила конструирования подобных шаблонов необязательно очевидны представителю заказчика.

Постановка задачи разметки тестовых сценариев

Если рассмотреть форму сценария, в большей степени «приближенную к неспециалисту по тестированию», то для нашего примера она могла бы выглядеть, например, как в листинге 4.

accuracy is 1e-6

автоматическую генерацию тестового каркаса, с другой стороны, упростить работу по «доведению» приемочных сценариев до формализованных модульных тестов.

Основные решения, которые должны быть приняты специалистом по тестированию в ходе работы с инструментарием разметки тестовых сценариев, состоят в следующем:

1) формализовать структуру приемочного теста, на которой основывается инструментарий разметки тестовых историй, в рамках предложенной модели определить назначение отдельных элементов (строк) сценария, приписав им соответствующие атрибуты, например, @Given - для определения контекста, @When - для определения выполняемого действия, @^еп - для определения проверяемого условия выполнения теста, @Alias - для определения синонимов и т. д.;

2) определить названия соответствующих методов тестового класса или правила их конструирования;

3) определить, какие элементы сценария будут выступать в роли параметров тестовых методов;

4) определить типы параметров тестовых методов;

5) определить возможности расширения множества допустимых элементов разметки тестового сценарии в соответствии с особенностями конкретной предметной области;

6) определить образцы (шаблоны тестовых сценариев), на основе которых автоматически генерируются или размечаются сценарии с другими значениями исходных данных.

Выполнить все эти шаги автоматически в общем случае невозможно, однако можно сформулировать постановку задачи частичной автоматизации разметки тестовых сценариев с участием специалиста по тестированию. Детальная формулировка требований к разработке инструментария разметки и правил, на которых будут основаны соответствующие преобразования тестового сценария, являются предметом дальнейшей работы.

Реализации и открытые проблемы

В статье [8] на основе обзора существующих реализаций BDD и анализа их основных возможностей, особенно в части интеграции со средами разработки, мы сформулировали список общих требований, которые необходимо учитывать при разработке средств, поддерживающих BDD. Проведенное исследование показывает, что даже те средства, которые рекламируются как поддерживающие написание приемочных тестов в виде простого текста, в действительности устанавливают существенные ограничения на тестовые истории. При этом одним из критических аспектов является обеспечение автоматизируемости отображения тестовых сценариев в модульные тесты.

В связи с этим следует выделить несколько важных моментов, определяющих основные трудности применения подхода BDD.

Несмотря на то что сами модульные тесты легко автоматизируются, задача преобразования пользовательских историй к связанным с реализацией тестовым классам остается актуальной.

Приемочные тесты суть требования. Так как в требованиях (равно как и в самом программном обеспечении) неизбежны изменения, вопрос преобразований приемочных тестов очень важен. В процессе написания «тестовой истории» мы можем обнаружить, что какие-то требования упущены. С другой стороны, изменения могут затрагивать интерфейсный уровень приложения - в этом случае сами приемочные тесты, возможно, и не изменятся, но изменится процесс отображения. Для представленного выше примера с вычислением производной функции подобное изменение может заключаться в определении, скажем, интерфейса RealValuedFunction со следующими методами:

public interface RealValuedFunction { void set( String symbolic ) ; double getValue( double x ) ;

}

Это изменение не затрагивает уровень представления приемочных тестов, но реализация тестовых методов, очевидно, изменится (листинг 5).

Еще одним моментом, требующим внимания исследователей, является то, что в существующих реализациях BDD обеспечивается формулирование сценариев ожидаемого (желательного) поведения системы. При этом учет сценариев нежелательного поведения системы также может рассматриваться как возможное расширение модели BDD, важное для практики разработки программного обеспечения.

Автоматизация перехода от плохо структурированного текста на естественном языке к упрощенному структурированному языку тестовых сценариев остается существенной проблемой (см. также [9]). Полезным может оказаться применения опыта и подходов из области NLP-технологий. Заметим, что даже более простая задача поддержания процесса разметки тестовой истории для обеспечения возможности дальнейшей автоматической генерации модульных, далека от окончательного решения.

@Given(«a derivative function test «) public void aDerivativeFunctionTest() { calc = factory.createCalculator();

comparator =factory.createSymbolicFunctionComparator();

}

@When(«the input function is $input») public void theInputFunction(String input) {

// Создаем объект класса, реализующего интерфейс // RealValuedFunction

RealValuedFunction rvf = new RealValuedFunction() { @Override

public set( String input ) { // Реализация функции...

}

@Override

double getValue( double x ) {

// Реализация вычисления значения в точке.

}

@Override

String toString() {

// Преобразование к символьному представлению.

}

};

rvf.set( input );

// Вычислитель теперь работает с функциями, // реализующими интерфейс RealValuedFunction calc.set( rvf );

}

@Then(«the derivative function is $result») public void theDerivativeFunction( String result ) { RealValuedFunction derivative = calc.derivative(); assertTrue(comparator.equal(derivative.toString(),result);

}

@Then(«the derivative value for x=$x is $y where accuracy is $acr») public void theDerivativeValue(double x,double y,double acr) { RealValuedFunction deriviative = calc.derivative(); assertEquals(derivative.getValue(x), y, acr );

}

Листинг 5. Модификация тестового класса

Средства BDD все еще в сильной степени ориентированы на разработчиков. В то же время технологическая поддержка BDD все еще ограничена. В большинстве публикуемых примеров (включая и данную статью) тестовые сценарии и ипк-тесты написаны одними и теми же специалистами. Это означает, что внедрение обсуждаемых технологий в проектную практику, фактически, означает необходимость дополнительной рабо-

ты, которая опять же ложится на плечи разработчиков. Поэтому даже небольшие улучшения существующих технологических средств могут оказать заметное влияние на востребованность BDD-инструментария как у самих разработчиков, так и у инженеров по контролю качества, которые, вероятно, и есть целевая аудитория, ответственная за формирование правильных отношений между заказчиками и разработчиками.

СПИСОК ЛИТЕРАТУРЫ

1. North, D. Behavior modification: the evolution of behavior-driven development [Текст] / D. North. -Better Software. -March 2006.

2. Beck, K. Aim, Fire [Текст] / K. Beck // IEEE Software. -2001. -Vol. 18. -№ 5. -P. 87-89.

3. Solis, C. A study of the characteristics of behaviour driven development [Текст] / C. Solis, X. Wang // In Proc. of 37th EUROMICRO Conf. on Software Engineering and Advanced Applications (SEAA). -Oulu, Aug 30-Sep 2. 2011.

4. Janzen, D. Test-driven development: concepts, taxonomy, and future directions [Text] / D. Janzen, D.H. Saiedi-an // Computer. -2005. -Vol. 38. -№ 9. -P. 43-50.

5. Janzen, D. Does test-driven development really improve software design quality? [Текст] / D. Janzen, D.H. Saiedian // IEEE Software. - March/Apr., 2008. -Vol. 25. -№ 2. -P. 77-84.

6. What is JBehave? [Электронный ресурс]. -Режим

доступа: http://jbehave.org

7. Sanderson, S. Behavior driven development

8. Pyshkin, E. On requirements for acceptance testing automation tools in behavior driven software development [Электронный ресурс] / E. Pyshkin, M. Mozgovoy, M. Glukhikh // In Proc. of the Central & Eastern European Software Engineering Conf. Russia

9. Borg, R. Automated acceptance test refactoring [Электронный ресурс] / R. Borg, M. Kropp // In Proc. of WRT'11. -Waikiki, Honolulu, HI, USA. -May 22, 2011.

УДК 004.415

Л.Ю. Лабошин, А.А. Лукашин, В.Б. Семеновский

ПОДДЕРЖКА ВЫЧИСЛЕНИЙ НА ГРАФИЧЕСКИХ УСКОРИТЕЛЯХ В ВИРТУАЛЬНОЙ СРЕДЕ XEN ДЛЯ ОБРАБОТКИ ПОТОКОВ ДАННЫХ

РОБОТОТЕХНИЧЕСКИХ СИСТЕМ

Перспективы применения графических ускорителей

Современные робототехнические системы испытывают необходимость обработки массивов потоковых данных в режиме реального времени. Актуальны задачи обработки видеопотоков, решения систем алгебраических уравнений и расчета поведения динамических систем. Перспективным направлением решения этих задач является передача потоков данных по телематическим каналам в центры обработки данных (ЦОД). Современные ЦОД базируются на технологиях виртуализации и облачных вычислений.

Для эффективной обработки потоков данных, поступающих с робототехнических систем, могут использоваться графические процессорные устройства (GPU), изначально предназначенные для обработки видеоинформации, но на данное время активно применяемые для проведения научных и инженерных расчетов. Параллельные

участки кода могут быть перенесены на GPU, где будут выполняться множеством нитей (threads). В целом работа нитей на GPU соответствует архитектуре SIMD (Single Instructions - Multiple Data), однако имеется существенное различие. Только нити в пределах одной группы выполняются физически одновременно. Нити различных групп могут находиться на разных стадиях выполнения программы. Такой метод обработки данных обозначается термином SIMT (Single Instructions -Multiple Threads) [1]. Управление работой групп производится на аппаратном уровне.

Вычислительные системы, в которых часть вычислительной нагрузки принимают на себя графические процессорные устройства, потенциально сравнимы с суперкомпьютерами в решении некоторых классов вычислительно емких задач, таких, как, например, численные методы, молекулярная динамика, квантовая химия [2]. Для решения задач на графических процессорах существу-