AT.info ПОСИДЕЛКИ  vKontakte   facebook группа  
Mapping

TestComplete ( JScript ): Описание оконных деклараций через классы-обертки

Автоматизированное тестирование на уровне GUI содержит в себе много сюрпризов, связанных с работой с оконными объектами. Причем сюрприз заключается в том, что наиболее изящное решение проблемы с поддержкой описаний оконных объектов в актуальном состоянии для каждого отдельно взятого средства может быть свое. Но это наиболее удачное решение. Тем не менее, есть ряд механизмов, имеющих аналоги в различных средствах. Одним из примеров является Mapping оконных деклараций, позволяющий некоторым оконным объектам ставить в соответствие некоторый псевдоним. Подобное решение в TestComplete обладает одним ключевым недостатком: при изменении иерархии оконного объекта приходится переделывать маппинг всех дочерних объектов. Альтернативой этому стало введение с 6-й версии TestComplete такой функциональности как Alias, которая позволяла регулировать иерархию псевдонимов. Но у такого решения есть другой недостаток: низкая скорость. Соответственно, нужны механизмы, позволяющие оперативно реагировать на изменение GUI, при этом корректировки желательно минимизировать. Давайте рассмотрим конкретный пример.

У нас есть некоторое диалоговое окно, к которому в коде можно обратиться так:

Sys.Process( PRODUCT_NAME ).Window("TForm", "New Text Style", 1);

Здесь PRODUCT_NAME - это некоторая константа, содержащая в себе имя процесса. В вышеуказанном диалоге есть текстовое поле Name , к которому обратиться можно так:

Sys.Process( PRODUCT_NAME ).Window("TForm", "New Text Style", 1).Window( "TEdit" , "*" , 1 );

а также 2 кнопки: OK, Cancel, у которых описания имеют вид соответственно:

Sys.Process( PRODUCT_NAME ).Window("TForm", "New Text Style", 1).Window( "TButton", "*", 1 )
Sys.Process( PRODUCT_NAME ).Window("TForm", "New Text Style", 1).Window( "TButton", "*", 2 )

Как видно из описаний, объекты не очень компактно описаны, более того, достаточно нестабильно, поскольку используются индексы. Часто может возникнуть ситуация, когда имена объектов в разной среде разные. Самый простой пример: системные окна сообщений для разных локализаций операционной системы имеют кнопки с текстом на локальном языке. Если заказчик из англоязычной страны, то проблем не возникнет. Но если же автотесты создаются для продукта, который идет и для неанглоязычных потребителей, то тут надо уменьшить привязку к тексту объектов, что было сделано для объектов выше. Теперь, давайте рассмотрим некоторый типичный тестовый сценарий, использующий эти объекты. Допустим нам надо подождать появления диалога в течение 5 секунд. Если он появился, то вводим текст ( неважно какой ) в текстовое поле Name и жмем кнопку OK. В чистом виде это выглядит так:

if( Sys.Process("Inventory").WaitWindow("TForm", "New Text Style", 1 , 5000 ).Exists ) {
        Log.Error( "No Text Style dialog available" );
}
else {
      Sys.Process( PRODUCT_NAME ).Window("TForm", "New Text Style", 1).Window( "TEdit" , "*" , 1 ).wText = "Some Text";
      Sys.Process( PRODUCT_NAME ).Window("TForm", "New Text Style", 1).Window( "TButton", "*", 1 ).Click();
}

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

function NewTextStyleDlg()
{
  this.Get = function ()
  {
    return Sys.Process( PRODUCT_NAME ).Window("TForm", "New Text Style", 1);
  }  
}

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

var dNewTextStyle = new NewTextStyleDlg();

if( Sys.Process( PRODUCT_NAME ).WaitWindow("TForm", "New Text Style", 1 , 5000 ).Exists ) {
        Log.Error( "No Text Style dialog available" );
}
else {
      dNewTextStyle.Get().Window( "TEdit" , "*" , 1 ).wText = "Some Text";
      dNewTextStyle.Get().Window( "TButton", "*", 1 ).Click();
}

RSS-материал