10. Возможности языка 4Test

Назад Содержание Дальше

Так как язык 4Test очень похож на язык с++, то мы не будем останавливаться на рассмотрении всех возможностей этого языка, а лишь укажем на некоторые особенности, которые могут быть полезны в работе.

10.1 Циклы for

В SilkTest-е существует 3 вида цикла for:

  • стиль языка С
  • стиль языка Basic
  • цикл for…each

 

Каждый из них рекомендуется применять в разных ситуациях.

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

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

Примеры:

Code

[-] for i = 1 to ListCount (li)
	[-] if (li[i] < 5)
		[ ] ListDelete (li, i)
[ ] Print (li)

При выполнении данного кода возникнет исключение:

Code

*** Error: Index value of 8 exceeds list size of 7

Для того чтобы этого не случилось, необходимо переписать его следующим образом:

Code

[-] for (i = 1; i <= ListCount (li); i++)
	[-] if (li[i] < 5)
		[ ] ListDelete (li, i)
		[ ] i--
[ ] Print (li)

Пример использования цикла for…each можно посмотреть в главе 2

10.2 Конкатенация строк

Кроме привычного способа конкатенации (сложения строк) с помощью оператора “+” SilkTest предлагает еще один способ: внутри строковой константы можно указать имя переменной, обрамленной символами { и }.
Преимущество такого способа в том, что кроме строковых переменных можно использовать переменные любых других типов, их приведение к строке произведется вручную. Кроме того, этот способ более простой и проще читается.

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

Code

[ ] STRING s = "Sample string"
[ ] INTEGER i = 138
[ ] REAL r = 34.786
[ ] BOOLEAN b = TRUE
[ ] 
[ ] STRING sResult = s + " " + Str (i) + " " + Str (r) + " " + [STRING]b
[ ] Print (sResult)

с вариантом, который доступен в SilkTest-е (здесь показан уже лишь процесс объединения всех переменных, объявления переменных такие же, как в предыдущем примере):

Code

[ ] STRING sResult = "{s} {i} {r} {b}"

Очевидно, что второй вариант гораздо проще писать, читать и редактировать.

10.3 Динамическое изменение настроек Агента

Во время работы скрипта иногда необходимо на время изменить параметры агента. Например, мы это делали в главе 7. Обработка результатов (Results) для при создании скриншота. Теперь рассмотрим эту возможность подробнее.

С помощью изменений настроек Агента можно изменить многие параметры, которые заданы в opt-файле. Также эти параметры задаются в окне Agent Options (Options – Agent). Например, с помощью опций Агента можно изменить время ожидания окна SilkTest-ом, время задержки при вводе данных с клавиатуры или с помощью мыши, проверку на активность объекта при работе с ним, либо проверку на то, что объект доступен для работы (enabled) и многое другое. Все параметры Агента, доступные для изменения, перечислены в справке по SilkTest-у. Кроме того, они отображаются внизу окна Agent Options при их изменении. Для работы с настройками Агента существует класс Agent. Методы этого класса, предназначенные для работы с настройками, перечислены ниже.

  • Agent.GetOption (Option) – возвращает значение определенной опции. Тип возвращаемого значения зависит от опции
  • Agent.SetOption (Option, aValue) – устанавливает значение опции. Возвращает предыдущее значение этой же опции
  • Agent.IsOptionValid (aoOptionName) – проверяет, является ли опция допустимой

Метод Agent.SetOption устанавливает значение опции на все время работы скрипта. То есть при изменении какой-либо настройки во время работы одного тесткейса, эти же настройки будут сохранены и для всех остальных тесткейсов до тех пор, пока не будут изменены явно.

 

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

Приведем пример. В SilkTest-е по умолчанию включена опция “Verify that windows are active”. Это значит, что вы не сможете работать с объектами неактивного окна и следующий пример вызовет ошибку.

Code

[-] testcase Test_Agent_Options () appstate apsTestApp
	[ ] 
	[ ] wTestApp.SetActive ()
	[ ] wTestApp.Control.ListBox.Pick ()
	[-] if (!dListBox.Exists ())
		[ ] LogError ("ListBox dialog not opened")
	[ ] dListBox.btnPopup.Click ()
	[ ] Sleep (0.5)
	[-] if (!dMsg.Exists ())
		[ ] LogError ("Message Box not opened")
	[ ] Print (dListBox.lstItemType.sValue)

Результат работы:

Code

	[ ] *** Error: Window '[PopupList]Item type:' is not active
	[ ] Occurred in dListBox.lstItemType.sValue.Get

Как видно из примера, SilkTest не смог взять значение свойства sValue из списка, который находится в неактивном окне. Переделаем этот пример, чтобы сделать его рабочим, независимо от того, активно окно или нет (мы приведе здесь лишь ту часть скрипта, которая была изменена):

Code

	[-] withoptions
		[ ] BindAgentOption (OPT_VERIFY_ACTIVE, FALSE)
		[ ] BindAgentOption (OPT_VERIFY_ENABLED, FALSE)
		[ ] Print (dListBox.lstItemType.sValue)

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

10.4 Обработка исключительных ситуаций

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

Именно для таких целей в SilkTest-e существует возможность работать с исключениями.

Для того, чтобы перехватить исключение и не дать SilkTest-у остановить работу скрипта, необходимо поместить ту часть кода, где мы ожидаем появление ошибки, в блок do…except.

Возьмем самый просто пример деления на ноль:

Code

	[ ] Print (1/0)
	[ ] Print ("something")

При выполнении данной строки сгенерируется исключение:

Code

*** Error: Divide by zero

и строка “something” выведена в результатах не будет

Теперь поместим эту строку в блок do…except и в случае возникновения исключительной ситуации будем об этом сообщать в результатах:

Code

	[-] do
		[ ] Print (1/0)
	[-] except
		[ ] LogError ("Exception occured")
	[ ] Print ("something")

Результат теперь примет такой вид:

Code

[ ] Exception occured
[ ] something

Теперь рассмотрим некоторые операции для работы с исключениями:

  • ExceptPrint () – функция выводит на печать информацию об ошибке
  • ExceptData ( ) – возвращает информацию об исключении
  • ExceptNum ( ) – возвращает номер исключения
  • ExceptLog ( ) – выводит на печать информацию об исключении. Отличие от первой функции в том, что информация выводится, как ошибка, а не как обычный комментарий
  • ExceptClear () – очищает информацию о текущем исключении
  • ExceptCalls () – возвращает список вызовов всех функций от тесткейса до функции, в которой произошла ошибка
  • raise [integer-expr [, expr [, cmd-line]]] – генерирует исключение с заданным номером (integer-expr)
  • reraise – генерирует исключение повторно

Например, если необходимо перехватить какое-либо конкретное исключение, но при этом другие исключения должны возникать, как и прежде, будет уместно написать следующее:

 

Code

[-] do
	[ ] Print (1/0)
[-] except
	[-] if ExceptNum () == E_DIVIDE_BY_ZERO
		[ ] Print ("Division by zero as expected")
	[-] else
		[ ] Print ("Unexpected exception: {ExceptNum ()}, {ExceptData ()}")
		[ ] reraise

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

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

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

Code

[-] void First ()
	[ ] Second ()
[-] void Second ()
	[ ] raise E_DIVIDE_BY_ZERO, "Divide by zero generated"
[ ] 
[-] main ()
	[ ] LIST OF CALL lcCalls
	[ ] CALL cCall
	[ ] 
	[-] do
		[ ] First ()
	[-] except
		[ ] lcCalls = ExceptCalls ()
		[-] for each cCall in lcCalls
			[ ] Print ("Error occured in module '{cCall.sModule}', function '{cCall.sFunction}', line {cCall.iLine}")
		[ ] LogError ("{ExceptNum ()}, {ExceptData ()}")

Результат будет иметь такой примерно вид:

Code

[ ] Error occured in module 'TestApp.t', function 'Second', line 1516
[ ] Error occured in module 'TestApp.t', function 'First', line 1514
[ ] Error occured in module 'TestApp.t', function 'main', line 1523
[ ] -11500, Divide by zero generated

 

10.5 Преобразование типов

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

В SilkTest-e существуют два типа преобразования данных: явный и неявный.

При явном преобразовании необходимо использовать оператор [] для указания типа, в который преобразуются данные. Например:

Code

STRING s = [STRING]55

Здесь производится явное преобразование из INTEGER в STRING.

Неявное преобразование осуществляется автоматически и не требует указания оператора []. Например:

Code

	[ ] LIST OF STRING ls = {"one", "two", "three"}
	[ ] ARRAY OF STRING as = ls

Ниже дана таблица явных и неявных преобразований, возможных в SilkTest-e с примечаниями к некоторым из них.

Таблица 10.1 Явные и неявные преобразования типов в SilkTest-e

Явные преобразования Неявные преобразования
BOOLEAN –> INTEGER INTEGER –> REAL
INTEGER –> enum INTEGER –> BOOLEAN
BOOLEAN –> enum **** REAL –> INTEGER
любой_не_строковый –> STRING enum –> INTEGER
record –> LIST LIST –> record
STRING –> INTEGER LIST –> ARRAY
STRING –> GUITYPE ARRAY –> LIST
** DATETIME –> DATE * LIST OF type-1 –> LIST OF type-2
** DATETIME –> TIME * ARRAY of type-1 –> ARRAY OF type-2
** DATE –> DATETIME GUITYPE –> INTEGER
** TIME –> DATETIME enum –> BOOLEAN
SET –> LIST *** STRING –> DATETIME
SET –> INTEGER STRING –> HMACHINE
INTEGER –> SET LIST –> SET
INTEGER –> SEMAPHORE  

 

Примечания:
* Для элементов массива или списка используются правила преобразования встроенных типов
** Подробнее смотри описание типа DATETIME
*** Если строка в формате ISO: YYYY-MM-DD HH.MM.SS.MSMSMS
**** Преобразование REAL в INTEGER осуществляется с помощью отбрасывания дробной части (не округление!)

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

Code

	[ ] INTEGER i = Val ("654")
	[ ] REAL r = Val ("654.554")

 


Назад Содержание Дальше