вторник, 13 января 2015 г.

Что такое предусловия (постусловия), зачем они нужны и как реализованы

Предистория.

Спустя некоторые время после реализации автоматизированного тестирования стали видны проблемы, связанные с процессом обработки результатов автопрогона тестов. Основной из них оказалось влияние непрошедних тестов на начальную (умолчательную) настройку системы. И хотя у нас существует постулат, что программно тесты не влияют друг на друга (например, результат работы функции "А" в тесте 1 не доступен тесту 2) оказалось не учтенной ситуация, когда после теста "залипают" неудалившиеся комментарии, фильтры, вкладки, окна и т.д.. Из-за этого в конце прогона тестов накапливается большое количество однотипных ложных срабатываний, когда имеет место быть не ошибка, а неверные начальные настройки.
Начальными умолчательными настройками в Немезисе принято считать следующие:
  • Главное окно развернуто на весь экран;
  • Главное окно активно (находится поверх всех окон);
  • Окно "Совет дня" скрыто;
  • Состояние настроек конфигурации равно умолчательному;
  • Оболочка запущена в режиме без вкладок;
  • В оболочке, на момент запуска теста, не должно быть пользовательских комментариев, фильтров и сохраненных объектов.
Помимо прочего перед каждым тестом выполняется следующая подготовка (словарь Common\TestProlog.script):
TRY
 "Закрыть все окна кроме текущего" 
EXCEPT
END 
StyleTable:Restore 
ОсновноеМеню 
"Сбрасываем вкладку БП в умолчательное состояние" 
"Выключаем машину времени" 
clipboard:clear
При написании и ручной отладки тестов подготовка оболочки полностью лежит на плечах тестировщика. Но, из-за большого количества однотипных ошибок в авторежиме, пришлось ввести проверку предусловий и постусловий. Предусловия - автоматичеки готовят систему к проведению теста (задают те умолчательные настройки, которые автор теста посчитал правильными). Постусловия - автоматически по окончанию теста проверяют, чтобы умолчательные настройки не изменились.
Пример предусловия: перед выполнением теста происходит проверка на наличие во вкладке "Мои документы" пользовательских объектов. Если они присутствуют, то происходит их удаление, если же удаление не сработало, результатом работы теста сразу становится ASSERT (до выполнения сценария теста дело не доходит).
Пример постусловия: в текущей реализации, постусловия проверяют, чтобы после теста главное окно не изменилось. Если же это произошло, тест тоже считается непрошедшим (с получением ASSERT). Следующий выполняющийся тест считает новое окно - своим главным окном, и значит, исключения не получаем, тест проходит успешно. Таким образом, удалось решить проблему с поиском тестов с "внезапно" меняющимся главным окном (ложные срабатывания из-за смены индекса главного окна, конечно, остались, но это вопрос к минимизации информации в эталонах). Другими, словами, не приходится искать 1 проблемный тест среди всех полутора тысяч, он сам сообщает о проблеме.

Реализация.

Для реализации системы проверки пред и постусловий были созданы словари:
  • Common\TestWithParameters.script (здесь находится описание всех возможных параметров, сгруппированных по видам использования).
  • Common\TestParamsDefine.script (объявление костант/переменных для поддержки параметров в скриптах).
  • Common\TestExecuteCommand.script (поддержка слова "Выполнить" и другие вспомогательные слова).
  • MainBasic.script (содержание всех слов, используемых в TestExecuteCommand.script, кроме нескольких подключенных словарей). По сути, MainBasic.script заменил HLTCLike.script.
Добавление новых параметров в словари, может создаваться как от описания названия параметра до добавления кода, который выполняет этот параметр, так и наоборот. Главное, о чем стоит помнить, это не пропускать ни одного словаря, чтобы не пропустить неприсвоенных и используемых переменных. Также следует хорошо продумать, как этот параметр впишется в уже имеющуюся картину проверок.
Для проверки любого параметра в тесте нужно использовать конструкцию вида:
Параметры: ( Описание_ параметра )
Выполнить (
 Сценарий_теста
)
Следует знать, что у параметров есть свои умолчательные значения:
PROCEDURE "Первоначальные параметры"
 "Проверить предусловия"
 "Не открывать документ"
 "Без проверок"
 "Импорт консультации не нужен"
 "Выполнить тест в основной конфигурации"
 "Не очищать строку Базового Поиска" 
 "Без изменения базы"
 "Проблем с фокусом после переключения баз не возникло"
 "Без установки размеров"
 "Не запоминать позицию мыши"
 "Не восстанавливать настройки до теста"
 "Используем умолчательные настройки" 
 "Не восстанавливать настройки после теста"
 "Не закрывать никакую вкладку"
 "Не проверять отсутствие комментариев"
 "Не проверять отсутствие пользовательских фильтров"
 "Не должно измениться основное окно"
 1 >>> g_WasInit
;
Они будут запущены в любом случае, при использовании слова Выполнить ( ... ).
Состояние любого параметра можно изменить, просто вписав противоположное значение в конструкцию Параметры: ( ... ).

Вывод.

Введенная система пред и постусловий позволила автоматически настраивать оболочку под определенные условия, и в автоматическом же режиме отслеживать их корректную настройку.
Упростился разбор результатов прохождения автотестов. Сократилось количество ложный срабатываний.

Планы и немного истории.

В планах расширить список постусловий (например, отслеживать СНР после теста).
В планах есть расширение количества доступных параметров.
В планах нет развития группы параметров, которые осуществляют проверку результаты работы теста. Такой параметр был введен, но признан неудачным опытом. Такая запись портит читаемость теста в целом (пропадает самодокументируемость кода).
В связи с вводом такой системы подготовки к тесту становится неактуальным большая часть кода словарей, ответственная за "восстановление" настроек до умолчательных. В планах обширный рефакторинг словарей и тестов, с целью исключить дублирование "настроек".
Можно рассмотреть ситуацию на примере восстановления позиции мыши:
Первоначально было:
VAR x_coord
VAR y_coord
"Запомнить позицию мыши" >>> y_coord >>> x_coord
TRY
 Код_теста
FINALLY
 x_coord y_coord mouse:SetCursorPosition 
END
Выделено в отдельную процедуру:
PROCEDURE "Запомнить позицию мыши и выполнить" IN aProc
 VAR x_coord
 VAR y_coord
 "Запомнить позицию мыши" >>> y_coord >>> x_coord
 TRY
  aProc DO
 FINALLY
  x_coord y_coord mouse:SetCursorPosition 
 END
;
Выделено в WORDWORKER (создаем самодокументируемый код):
VOID WORDWORKER "##Запомнить позицию мыши и выполнить"
 "Запомнить позицию мыши и выполнить {(@ ( WordToWork DO ) )}"
;
Этот же код реализован в виде условия, чтобы позиция мыши после теста восстановилась. Для его вызова достаточно выполнить:
Параметры: ( "Восстанавливать позицию мыши" )
Выполнить (
 Сценарий_теста
)
Т.е. становится неактуальным код "Запомнить позицию мыши и выполнить", "##Запомнить позицию мыши и выполнить". Рефакторинг подразумевает собой удаление дублирующегося кода, т.к. сейчас восстановление позиции мыши происходит дважды. Будем оптимизировать.

1 комментарий: