4.8. Автоматическое тестирование

4.8.1. Global как COM-Сервер

Клиентское приложение Global является COM-сервером, с которым возожно взаимодействовать из любого языка программирования, поддерживающего вызовы методов COM-объектов. Для регистрации приложения Global как COM-сервера необходимо через командную строку запустить приложение Global с ключом /regserver: Global.exe /regserver

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

4.8.2. Основные понятия

  • Сервер/OLE-сервер - клиент Global.exe запущенный в режиме OLE-Сервера, созданный при помощи методов CreateObject/CreateOleObject(в зависимости от конкретного языка) - запускается самой ОС, где он и должен быть прописан - возвращает интерфейс-наследник от IDispatch. Большинство исполнителей способны возвращаемое значение принимать как тип данных Variant. Обращение к методам реализованным в интерфейсе сервера происходит просто через точку:

    fooVariantVariable := CreateOleObject('btkRuntime.GlobalApplication');
    fooVariantVariable.FooServerMethod(some_params);
    
  • Клиент - тот кто запустил OLE-сервер. Приложения Global также способны быть клиентом, с той лишь разницей, что им нет необходимости выполнять CreateObject/CreateOleObject и обращаться к методам непосредственно: для этого в Scripter-е определён специальный объект “TestApp” у которого описаны все необходимые методы для взаимодействия с Сервером - укрупнённые относительно методов непосредственно OLE интерфейса.

  • Исключительная ситуация - это все “ошибки” выплывающие на поверхность приложения: как системные, так и пользовательские- от ошибки “деление на ноль” до сообщений в духе “Требуется значение атрибута “Код” для класса “Читатели”.

  • Параметры командной строки

4.8.2.1. Синхронизация выполнения методов

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

  • Возникает необходимость в методах позволяющих дождаться управляемого объекта на стороне сервера, в методах синхронизации выполнения скрипта, например, дождаться непосредственного открытия выборки после команды её открытия: WaitSelection, и прочие методы вида TestApp.Wait*
  • Исключительные ситуации возникающие на сервере при асинхронном выполнении метода не смогут автоматически попасть на клиент, в связи с чем невозможно их обработать и учесть в логике эксплуатирующей сервер программы (в скрипте Автоматического Тестировщика).

Ситуацию отчасти спасает возможность оставаясь в асинхронном режиме выполнения дождаться окончания выполнения метода: в подсистему Автоматического Тестирования внедрён объект ожидания Event, при запуске очередного метода он сбрасывается, а когда метод завершился (штатно или с ошибкой) - выставляется, что позволяет клиенту вслед за запуском асинхронного метода встать в ожидание его завершения и при этом не при каких условиях не оказаться заблокированным навсегда, т.к. ожидание выполняется по таймауту (если сервер не сигнализировал об окончании выполнения метода своевременно- ожидание будет прекращено). Объект ожидания создаётся по запросу клиента: параметр метода Run указывает на необходимость его создания/”Синхронизации выполнения методов”.

Примечания:

  • Если заведомо известно, что метод (например, Выполнение Операции) вызывает блокировку исполняющего потока - можно просто принудительно задать ему время ожидания “0”, чтобы скрипт зря не тормозил.

    Пример: операция открытия выборки в карточном представлении - карточка открывается как модальное окно и, соответственно, фактический метод завершит свою работу только после её закрытия.

4.8.2.2. Проброс исключительных ситуаций сервера

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

Примечания:

  • Если ожидание какого-либо метода было прекращено по истечении заданного времени, но после того он вызвал ошибку - эта ошибка будет извлечена следующим методом поддерживающим проброс/”обработку ошибок сервера”.
  • В некоторых ситуациях выполняемый метод может инициировать асинхронное выполнение другого кода (например, выполнение асинхронных SQL-Операций), тогда исключительная ситуация сгенерированная этим кодом не попадёт в результат выполнения данного метода, вместо того она будет извлечена другим методом, на чьё время исполнения придётся её(исключительной ситуации) возникновение.

4.8.2.3. Методы поддерживающие обработку ошибок/”исключительных ситуаций” Сервера

  • методы Объекта TestApp(TbtkScriptTesterObject), в конце своего выполнения проверяют состояние очереди и если она не пуста
  • возвращают ошибку с соответствующим извлечённым текстом . Эти методы имеют три параметра позволяющих управлять возникновением/перенаправлением ошибки, параметры всегда идут последними и в указанном порядке. Параметры не перечислены в методов описании, т.к. одинаковы для всех методов этой группы.
  • Timeout: Integer - Время отведённое на ожидание выполнения метода, по его истечении может быть сгенерирована исключительная ситуация. Если задать значение “-1”, то значение будет проигнорированно - подставлено значени по-умолчанию; значене “0” - метод не будет ничего ждать, и, соответственно, ругаться.
  • DoRise: Boolean - генерировать исключительную ситуацию, если в очереди возврата результатов всё-таки было обнаружено упоминание об ошибке.
  • RaiseOnTimeout: Boolean - генерировать исключительную ситацию, если метод завершил ожидание по истечении времени.

Если исключительная ситуация/ошибка будет выброшена(raise) из метода - она должна быть обработана в блоке try..except..endtry..finally..end , в противном случае выполнение кода/скрипта будет завершено с соответствующим сообщением, с текстом исключительной ситуации. Если метод сгенерировал исключительную ситуацию, но значение параметра DoRise или RaiseOnTimeout (или, если не указаны - их значение по-умолчанию) равно False - текст исключения будет направлен в операцию выборки скрипта чьё имя задаётся методом SetRaiseOperationName, однако, если имя операции не задано, то вне зависимости от значения соответствующих параметров исключения будут выброшены.

4.8.3. Прикладная разработка

4.8.3.1. Доступные команды

4.8.3.1.1. Инициализация и завершение работы

4.8.3.1.1.1. Инициализация

TbtkScriptTesterObject.Run - Метод запускает экземпляр тестируемого приложения.

4.8.3.1.1.2. Завершение работы OLE-сервера
Хорошим тоном обязательного завершения будет:
  try
    TestApp.Quit;
  except
    TestApp.Terminate;
  end;
4.8.3.1.1.3. Runned

TbtkScriptTesterObject.Runned - проверяет, активен ли в данный момент OLE-Сервер

4.8.3.1.1.4. Прочие
  • TbtkScriptTesterObject.RunAsCurrent - запускает экземпляр тестируемого приложения, используя имя пользователя и пароль текущего пользователя. В качестве параметра может быть передано системное имя главной выборки приложения.
  • TbtkScriptTesterObject.CmdLine
  • TbtkScriptTesterObject.EnableScriptRecording - включает в рестируемом приложении режим записи тестового скрипта.
  • TbtkScriptTesterObject.DisableScriptRecording - выключает в тестируемом приложении режим записи тестового скрипта.
  • TbtkScriptTesterObject.ScriptRecording - свойство указывает, что тестируемое приложение работает в режиме записи тестового скрипта.

4.8.3.1.2. Настройка обработки ошибок Сервера

Любая ошибка/”Исключительная ситуация” Сервера попадает в скрипт тестирования исключительно с исполнением метода этого Сервера, т.е. метода объекта TbtkScriptTesterObject, за исключением методов реализованных локально. Сами эти методы можно разделить на две большие и принципиально разные категории: синхронные и асинхронные. Любая ошибка проявившаяся в синхронном методе просто всплывает на стороне исполнителя(скрипта) и может быть отловлена и обработана штатными средствами- блоком try except. Если же ошибка проявляется в методе асинхронном, то ничего такого не происходит - её необходимо специально пробрасывать с Сервера на Клиент, для чего на стороне Сервера реализована очередь ошибок. В эту очередь складываются текстовые сообщения исключений- как непосредственно выполняемого метода(если говорить о TestApp)/команды(если говорить о TbtkAutoTestRobot), так и приложения в целом. Интерфейс Сервера реализует метод умеющий забирать порцию сообщений/проверять очередь - PopExecResults (ACount : Integer): WideString; Методы TestApp общающиеся непосредственно с интерфейсом Сервера вызывают PopExecResults сами внутри себя, никаких дополнительных действий не требуется. Если была возвращена несуптая строка - за время прошедшее с прошлого извлечения ошибок что-то произошло - на клиенте необходимо об этом рапортовать, варианты:

  • Вызвать операцию и передать ей текст исключения. Настраивается свойством TbtkScriptTesterObject.RaiseOperationName.
  • Выбросить исключительную ситуацию непосредственно из самого метода, что можно обработать тем же способом как и исключения синхронных методов. В противном случае выполнение скрипта будет прервано с соответствующим исключением. Поведение управляется параметром DoRaise методов TestApp поддерживающих обработку ошибок сервера. Параметр не обязательно задавать для каждого отдельного вызова - он имеет значение по-умолчанию, задаваемое свойством TbtkScriptTesterObject.DefaultDoRaise,- использовать следует только в тех случаях, когда необходимо изменить общую логику обработки ошибок для конкретного вызова.

Также методы, реализующие асинхронные команды, могут генерировать исключение по истечении времени ожидания, за что отвечает, как и в случае c DoRaise, дефолтный параметр RaiseOnTime.

4.8.3.1.2.1. Соответствующие свойства объекта TestApp
  • свойство TbtkScriptTesterObject.RaiseOperationName - задаёт системное имя Pascal-операции, обрабатывающей невыброшенные скриптовыми методам исключительные ситуации
  • свойство TbtkScriptTesterObject.DefaultWaitExecTimeout - задаёт значение подставляемое по-умочанию в дефолтный параметр Timeout ф-й поддерживающих обработку ошибок сервера
  • свойство TbtkScriptTesterObject.DefaultDoRaise - задаёт значение подставляемое по-умочанию в дефолтный параметр DoRaise ф-й поддерживающих обработку ошибок сервера
  • свойство TbtkScriptTesterObject.DefualtRaiseOnTimeout - задаёт значение подставляемое по-умочанию в дефолтный параметр RaiseOnTimeout ф-й поддерживающих обработку ошибок сервера

4.8.3.1.3. Методы управления тестируемым приложением.

4.8.3.1.3.1. Методы поддерживающие обработку ошибок Сервера
  • TbtkScriptTesterObject.ExecuteOperation - выполняет операцию, принадлежащую выборке с указанным именем и отображением.

  • TbtkScriptTesterObject.ExecuteOperationEx - выполняет операцию, принадлежащую выборке с указанным именем и отображением. В метод возможно передать параметры, управляющие режимом выполнения операции.

  • TbtkScriptTesterObject.SelectionLocate - выполняет позиционирование на запись в указанной выборке по ключевому полю.

    Пример
    TestApp.SelectionLocate('FooSelection', 'ROLIST', 'FooID_Attr', 'ID_Value');
    
    TestApp.SelectionLocate('FooSelection', 'ROLIST', ['FooID_Attr1', 'FooID_Attr2'], ['ID1_Value', 'ID1_Value']);
    
  • TbtkScriptTesterObject.IsSelectionActive - проверяет существование и активность выборки с указанным именем и отображением на текущей форме тестируемого приложения

  • TbtkScriptTesterObject.WaitSelection - ожидает создания и открытия выборки с указанным именем. Если выборка не будет создана и открыта в течении указанного интервала времени, будет сгенерирована ошибка.

  • TbtkScriptTesterObject.SelectionSetVar - устанавливает значение параметру в указанной выборке

  • TbtkScriptTesterObject.SelectionGetVar - возвращает значение атрибута (параметра) указанной выборки

  • TbtkScriptTesterObject.CloseActiveModalForm - закрывает текущую активную модальную форму тестового приложения установкой форме соответствующего значения ModalResult.

  • TbtkScriptTesterObject.CloseActiveForm - закрывает текущую активную форму тестового приложения

  • TbtkScriptTesterObject.WaitDialog - ожидает отображения диалога в тестируемом приложении

  • TbtkScriptTesterObject.CloseActiveModalWindow устаревший - Закрывает модальное окно

  • TbtkScriptTesterObject.CloseActiveWindow - закрвыает окно

  • TbtkScriptTesterObject.FocusOnFirstControl

  • TbtkScriptTesterObject.FocusOnFieldByName - перемещает фокус ввода на контрол, являющийся редактором для указанного атрибута выборки

4.8.3.1.3.2. Локальные методы TestApp

Методы не использующие Сервер как таковой. Манипулируют непосредственно состоянием ОС.

4.8.3.1.3.3. Методы и свойства записи скрипта

Свойство TbtkScriptTesterObject.RecordingOperationName - Имя операции куда будут отправляться новые сгенерированные строки скрипта и результаты выполнения операций отправленных методом TbtkScriptTesterObject.AddRecorderManualOperation

Метод TbtkScriptTesterObject.AddRecorderManualOperation

Пример:
  TestApp.AddManCtrlOperation('ScriptIfVarNotEqual', 'Проверка значения', 144,
        '<PASCAL>'#13+
        '  ShowMessage(''Будет отправлен текст скрипта.'')'#13+
        '  Result := '''';'#13+
        '  Selection.First;'#13+
        '  while not Selection.Eof do'#13+
        '  begin'#13+
        '    if GetVar(''Checked'') then'#13+
        '    begin'#13+
        '      Result := Result + ''  if TestApp.SelectionGetVar('' +'#13+
        '        QuotedStr(Selection.Master.EntityName) + '', ''+'#13+
        '        QuotedStr(Selection.Master.Representation) + '', ''+'#13+
        '        QuotedStr(GetVar(''Name'')) + '') <> ''+'#13+
        '        QuotedStr(GetVar(''Value'')) + '' then ''#10+'#13+
        '        ''    Raise(''''Значение атрибута '' +GetVar(''Name'')+ '' не соответствует'''');''#10;'#13+
        '    end;'#13+
        '    Selection.Next;'#13+
        '  end;'#13+
        '</PASCAL>');

4.8.3.2. Запись макроса/скрипта

4.8.3.2.1. Автоматическая

4.8.3.2.2. Ручное управление

../../_images/ATRecirdingManualControl.png

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

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

Также кроме ручного проставления, имеется возможность просто “прокликать” интересующие поля в отображении - галочки выставляются в панели автоматически. Чтобы в Клиент не уходили не нужные строки, такие как TbtkScriptTesterObject.SelectionLocate и TbtkScriptTesterObject.FocusOnFieldByName, которые бы возникали как побочный эффект “прокликивания”,- включается “режим сбора данных” - первая кнопка на тулбаре, она существует всегда и не зависит от добавления операций из клиента тестирования.

В приложении “Автоматический Тестировщик” на базе BTKDEV реализованы пользовательские операции записи скриптов:

  • проверка группы значений на соответствие ожидаемым

    if TestApp.SelectionGetVar('SEL_LB4_PERSON', 'ROLIST', 'SBIRTHDATE') <> '11.07.1985' then
      Raise('Значение не соответствует!');
    
    if TestApp.SelectionGetVar('SEL_LB4_PERSON', 'ROLIST', 'IDCLASS') <> '' then
      Raise('Значение не соответствует!');
    
  • позиционирование курсора по значениям произвольного набора атрибутов выборки

    TestApp.SelectionLocate('SEL_LB4_PERSON', 'ROLIST', ['SSECONDNAME', 'SFIRSTNME', 'SMIDDLENAME'], ['Трактор', 'Филипов', 'иванович']);
    

4.8.4. Системная разработка

4.8.4.1. UML классов подсистемы

4.8.4.1.1. Схема классов воспроизведения скрипта Автоматического Тестирования

../../_images/BtkAutoTester_ClassDiagramm.gif

Диаграмма классов Автоматического Тестировщика.svd

4.8.4.1.2. Схема классов записи скрипта автомачического тестирования

../../_images/AutoTestRecorderUML.png

Диаграмма классов системы записи скрипта

4.8.4.2. Типы методов

../../_images/TestAppMethodsClassification.gif

Основание классификации методов.vsd

4.8.4.2.1. Методы интерфейса

4.8.4.2.1.1. Команды робота(TbtkAutoTestRobot)
../../_images/RobotsCommandExecute.gif

Выполнение Команды роботом.vsd