Создание инфраструктуры автоматизации тестирования с использованием Rational Functional Tester

Источник: IBM

В данной статье Шиной Захариас (архитектор ПО, IBM Rational Functional Tester, IBM) описывает создание инфраструктуры автоматизации тестирования с использованием Rational Functional Tester. Он продемонстрирует весь процесс создания инфраструктуры автоматизации, начиная с введения в Rational Functional Tester и программного интерфейса (API) find. В статье рассматриваются примеры и сценарии.

Введение в IBM Rational Functional Tester

IBM® Rational® Functional Tester является инструментом автоматизированного функционального и регрессионного тестирования. Этот продукт предоставляет тестировщикам средства автоматизированного тестирования, позволяющие выполнять функциональное тестирование, регрессионное тестирование, тестирование пользовательского интерфейса и тестирование, управляемое данными. Rational Functional Tester включает встроенную поддержку Web-, .Net-, Java-, Siebel-, SAP-приложений и приложений эмуляции терминалов. Можно тестировать приложения PowerBuilder, AJAX, Adobe Flex, Dojo Toolkit, GEF, документы Adobe PDF, а также приложения для zSeries, iSeries и pSeries.

Преимущества использования Rational Functional Tester

Преимущества Rational Functional Tester:

  • Автоматизированное тестирование с использованием технологии ScriptAssure позволяет тестировщикам создавать автоматизированные тесты, устойчивые к частым изменениям пользовательского интерфейса приложений.
  • Storyboard Testing упрощает визуализацию и редактирование тестов благодаря использованию естественного языка и снимков экрана.
  • Управляемое данными тестирование позволяет многократно выполнять отдельные тесты с различными наборами тестовых данных.
  • Сценарии тестирования позволяют комбинировать записанные действия пользователя с помощью настраиваемых параметров и возможностей интеллектуального управления сценариями.
  • Интеграция с IBM Rational Team Concert и IBM Rational Quality Manager предоставляет доступ к элементам потока операций, а также поддержку логических или составных SCM-активов тестов.
  • Создание инфраструктур автоматизации тестирования с помощью богатого набора программных интерфейсов.

Предварительные условия

Для выполнения примеров данной статьи необходимо иметь базовые знания IBM Rational Functional Tester и установить Rational Functional Tester версии 8.2.

Необходимость инфраструктуры автоматизации

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

Rational Functional Tester и инфраструктура автоматизации

Инфраструктура автоматизации дает много преимуществ, таких как:

  • Мощные возможности создания сценариев. Возможность использования языков программирования Java и Visual Basic.
  • Объектно-ориентированный подход к автоматизации тестирования.
  • Алгоритм распознавания объектов и карты объектов.
  • Возможность динамического поиска объектов тестирования с помощью свойств объектов.
  • Богатый набор программных интерфейсов для создания сценариев без записи объекта.
  • Автоматизация создания сценариев, даже если приложение недоступно.
  • Механизм расширения пользовательских элементов управления, использующий прокси-объект SDK.

Создание инфраструктуры автоматизации в Rational Functional Tester с использованием find API

Использование API (программного интерфейса поиска) find при создании инфраструктуры автоматизации дает следующие преимущества:

  • Простой в использовании программный интерфейс поиска (find API) элемента управления в тестируемом приложении (Application Under Test - AUT) во время исполнения.
  • Не требуется карта объектов.
  • Устойчивая работа сценария даже при изменении приложения.
  • Возможность использования API find с любыми объектами test в Rational Functional Tester (например, GuiTestObject, BrowserTestObject и т.д.).
  • Возможность использования API find с объектом RootTestObject в Rational Functional Tester.

В Rational Functional Tester есть два вида API find:

  • find(Subitem Properties).
  • find(Subitem Properties, Boolean mappableOnly).

Подэлементы API find

Подэлементами могут быть atChild(), atDescendant() и atList().

atChild
Одно или несколько свойств, которые должны сравниваться с прямым потомком исходного TestObject.
 
atDescendant
Одно или несколько свойств, которые могут сравниваться с любым потомком исходного TestObject.
 
atList
Последовательный список свойств для сравнения. Подэлементами atList являются atChild, atDescendant и atProperty. Сначала сравнивается первый элемент списка, чтобы получить список кандидатов. Потомки первого списка сравниваются со следующим элементом списка и т.д.
 
mappableOnly
Аргументы, ограничивающие поиск. Если значение установлено в true, поиск будет ограничен отображаемыми объектами тестирования; в противном случае также будет выполнен поиск неотображаемых объектов тестирования.
 

sind() с подэлементом atChild

Если find() используется в TestObject с подэлементом atChild, find() сравнивает одно или несколько свойств с прямым (непосредственным) потомком TestObject.

Есть три вида find() с подэлементом atChild:

  • find(atChild(Property[] properties))
  • find(atChild(String propName, Object propValue))
  • find(atChild(String propName1, Object propValue1, String , propName2, Object propValue2 ))

В листинге 1 показано использование различных вариантов find() с atChild.

Листинг 1. Различные варианты find() с atChild
publicvoid testMain(Object[] args)
{	
    TestObject[] tobs1 = find(atChild(".class", "JButton"));
    TestObject[] tobs2 = find(atChild(".class", "JButton", "text", "OK"));
	
    Property prop1 = new Property(".class", "JButton");
    Property prop2 = new Property(".name", "ok");
    Property prop3 = new Property("text", "OK");
    Property[] props = {prop1, prop1, prop3};
    TestObject[] tobs3 = find(atChild(props));
}

find() с подэлементом atDescendant

Если find() используется в TestObject с atDescendant, find() будет пытаться сравнить одно или несколько свойств с любым потомком (не обязательно с прямым/непосредственным потомком) TestObject.

Есть три вида find() с подэлементом atDescendant:

  • find(atDescendant(Property[] properties))
  • find(atDescendant(String propName, Object propValue))
  • find(atDescendant(String propName1, Object propValue1, String propName2, Object propValue2 ))

В листинге 2 показано использование различных вариантов find() с atDescendant.

Листинг 2. Варианты find() с atDescendant
publicvoid testMain(Object[] args)
{
    TestObject[] tobs1 = find(atDescendant(".class", "JButton"));
    TestObject[] tobs2 = find(atDescendant(".class","JButton","text", "OK"));
		
    Property prop1 = new Property(".class", "JButton");
    Property prop2 = new Property(".name", "ok");
    Property prop3 = new Property("text", "OK");
    Property[] props = {prop1, prop1, prop3};
    TestObject[] tobs3 = find(atDescendant(props));	
}

find() с подэлементом atList

find() с atList предоставляет последовательный список свойств для сравнения. Подэлементами atList являются atChild, atDescendant и atProperty. Сначала сравнивается первый элемент списка, чтобы получить список кандидатов. Их потомки сравниваются со следующим элементом списка. Затем процесс продолжается.

Есть пять типов find() с подэлементом atList:

  • find(atList(subitems))
  • find(atList(subitems[]))
  • find(atList(subitems, subitems))
  • find(atList(subitems, subitems, subitems))
  • find(atList(subitems, subitems, subitems, subitems))

В листинге 3 показано использование find() с atList.

Листинг 3. find() с atList
publicvoid testMain(Object[] args)
{	
    TestObject[] tobs = find(atList(atDescendant
    (".class", "JFrame"), atChild(".class", "JButton", ".value", "OK"))) ;
}

find() с RootTestObject

RootTestObject представляет собой глобальный взгляд на тестируемую систему. Он обеспечивает доступ к общесистемным функциям, таким как поиск произвольного объекта тестирования на основании свойств и местоположения, а также поиск объекта DomainTest.

Существуют специальные свойства, применимые к find() с RootTestObject. К ним относятся:

.processName
Динамически разрешает процесс для тестирования. Ограничивает поиск процессами с указанным именем.
 
.processId
Динамически разрешает процесс для тестирования. Ограничивает поиск процессами с указанным идентификатором процесса (pid).
 
.domain
Выполняет поиск в доменах верхнего уровня, удовлетворяющих свойству .domain.
 
.hWnd
Используется в сочетании с .domain; если свойство .domain задано как Win, соответствующие окно будет активировано для тестирования.
 
Handle
Используется в сочетании с .domain; если свойство .domain задано как Net, соответствующие окно будет активировано для тестирования.
 

В листинге 4 RootTestObject используется для ввода текста в приложение notepad. Приложение notepad настраивается с помощью мастера Application Configuration Wizard.

Листинг 4. Пример использования RootTestObject в сценарии
publicvoid testMain(Object[] args)
{
		
    ProcessTestObject pto = startApp("notepad") ;
    Integer pid = new Integer((int)pto.getProcessId());
    RootTestObject rto = RootTestObject.getRootTestObject();
    TestObject[] textObjects = rto.find (atList(
        atProperty(".processId", pid), 
        atDescendant(".class", "Edit"))) ;
    ((TextGuiTestObject)textObjects[0]).setText("Hello RFT");
}

Создание инфраструктуры автоматизации с использованием API find в Rational Functional Tester

Теперь, познакомившись с API find и его вариантами, вы можете приступить к созданию инфраструктуры автоматизации с помощью этого интерфейса. Инженеры по автоматизации используют интерфейс API find для создания библиотек, с помощью которых тестировщики, не имеющие технической подготовки, разрабатывают сценарии тестирования. Библиотеки скрывают сложность идентификации объектов с помощью программных интерфейсов Rational Functional Tester. Начинающий пользователь может использовать удобные высокоуровневые функции для быстрого создания тестов.

Например, не имеющий технической подготовки тестировщик может написать тест с помощью простых функциональных вызовов, таких как:

  • ClickButton
  • EnterText
  • ClickLink
  • ClickImage
  • SelectComobboxItem
  • SelectRadio
  • CheckCheckbox

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

В листинге 5 приведен пример реализации одной из этих функций с помощью API find. Инженеры по автоматизации пишут библиотеки и функции, а тестировщики используют эти библиотеки для создания теста. Для операции "нажать кнопку" инженер-тестировщик указывает имя (name) или значение (value) кнопки (элемент управления button). При вводе текста в текстовое поле используется имя элемента управления text и значение текста. В листинге 5 приведен пример для Web-приложений.

Листинг 5. Пример функции, использующей API find
publicstaticvoid ClickButton(String name)
{
    GuiTestObject buttonObj = findButton(name);
    if (buttonObj != null) {
        buttonObj.click();
    }
    elsethrownew ObjectNotFoundException();
}
            
privatestatic GuiTestObject findButton(String value)
{
    TestObject[] tobs = find(atDescendant
    (".class", "Html.INPUT.submit", ".value", value), true);
    if(tobs.length == 0) 
        returnnull;
    return (GuiTestObject)tobs[0];
}

Метод ClickButton() использует аргумент, в данном случае - свойство value кнопки. В методе findButton() интерфейс API find используется для получения элемента управления, соответствующего свойству, переданному в API find. Метод можно настроить на поиск элемента управления на основе свойств, например, .text или .name. Эту логику можно также включить в подпрограмму findButton(). Можно, также, написать различные виды методов ClickButton, такие как ClickButtonByValue(), ClickButtonByName() или ClickButtonByLabel(), для поиска кнопки по значению, по имени или по метке.

В листинге 5 метод ClickButton принимает аргумент, а затем инженер-тестировщик передает свойство .value элемента управления. Если значение свойства .value или любых других свойств, используемых в find(), не доступно, для получения всех свойств и значений можно использовать инструмент Test Object Inspector, предоставляемый Rational Functional Tester (см. рисунок 1). В предыдущем примере показан первый элемент, возвращаемый find(). В результате можно получить более одного кандидата. Если это произойдет, измените подпрограмму так, чтобы она создавала больше свойств и можно было найти уникальный элемент.

Рисунок 1. Инструмент Test Object Inspector
Рисунок 1. Инструмент Test Object Inspector

Кроме того, инженеры по автоматизации могут писать модули для других функций, таких как clickText, EnterText и т.д. (см. листинг 6).

Листинг 6. Примеры библиотечных функций, основанных на API find
publicstaticvoid ClickText(String name)
{
    TextGuiTestObject textObj = findTextObject(name);
    if (textObj != null) {
        textObj.click();
    } else {
        throw new ObjectNotFoundException();
    }
}

public static void EnterText(String controlName, String value)
{
    TextGuiTestObject textObj = findTextObject(controlName);
    if (textObj != null) {
        textObj.setText(value);
    } else {
        thrownew ObjectNotFoundException();
    }
}

public static void ClickPassword(String name)
{
    TextGuiTestObject textObj = findPasswordObject(name);
    if (textObj != null) {
        textObj.click();
    } else {
        thrownew ObjectNotFoundException();
    }
}
	
 private static TextGuiTestObject findTextObject(String name)
{
    TestObject[] tobs = find(atDescendant(".class", 
    "Html.INPUT.text", ".name", name), true);
    if(tobs.length == 0)
        returnnull;
    return (TextGuiTestObject)tobs[0];
}
	
private static TextGuiTestObject findPasswordObject(String name)
{
    TestObject[] tobs = find(atDescendant(".class", 
    "Html.INPUT.password", ".name", name), true);
    if(tobs.length == 0)
        returnnull;
    return (TextGuiTestObject)tobs[0];
}

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

RegularExpression buttonRE = new RegularExpression("*button", 
false) ;
TestObject[] tobs = find(atDescendant(".class", buttonRE, 
"name", "OK"));

Теперь инженеры по автоматизации могут создать библиотеку классов инфраструктуры, а инженеры-тестировщики могут использовать эти классы для создания сценариев. В приведенном ниже примере инженеры-тестировщики используют функции инфраструктуры для загрузки amazon.com, поиска iPhone и входа в систему для покупки телефона.

public void testMain(Object[] args)
{
    startApp("www.amazon.com");
    sleep(5); //задержка на 5 секунд для загрузки страницы amazon
    EnterText("field-keywords", "iphone");
    ClickButton("Go");
    sleep(3); //задержка на 3 секунды для загрузки следующей страницы
    ClickLink("Hello. Sign in Your Account");
    sleep(3); //задержка на 3 секунды для загрузки следующей страницы
    EnterText("email", "name@gmail");
    ClickPassword("password");
    EnterPassword("password", "password");
    ClickImage("Continue");
}

Заключение

В статье описано использование программного интерфейса find API в Rational Functional Tester при создании инфраструктуры автоматизации тестирования HTML-приложения. Такой же подход можно использовать при написании инфраструктур для других приложений, поддерживаемых Rational Functional Tester.


Страница сайта http://www.interface.ru
Оригинал находится по адресу http://www.interface.ru/home.asp?artId=35957