вторник, 13 апреля 2010 г.

Лекция 1 автоматизированное тестирование


Предисловие.
Данный кус составлен по материалам сайтов http://software-testing.ruforum.script-coding.info
1.    Вводный курс – 4ч.
·         Actions, Iterations
·         Использования объекта DataTable и параметризация
·         Распознавание объектов в QTP
·         Работа с Object Repository
·         Методы Test Object
·         Свойства Объектов
·         Работа без репозитория
Цель: Научить работать с определять объекты и работать с таблицей.
Actions, Iterations
Вопрос: Что такое Action?
Ответ:
Action — это независимый скрипт в составе теста. Он имеет свой контекст имен переменных, свой локальный Object Repository (хранилище описаний объектов пользовательского интерфейса тестируемого приложения), свой Action Sheet (называемый, также Local Sheet — таблица для хранения значений параметров; его можно вызывать из других тестов. Кроме того, начиная с QTP 8.0 у Actions есть свои параметры (не путать с Data Table parameters: в данном случае имеются в виду значения переменных, передающихся в action извне, либо выходные параметры, аналогично параметрам функций).
В свойствах Action можно указать, сколько раз подряд его надо запустить (количество итераций) — это имеет смысл делать при активном использовании параметризации. При использовании параметризации, при каждой следующей итерации Action, все локальные параметры принимают новое значение — значение из ряда Action Sheet, совпадающего с номером итерации. Следует иметь в виду, что кроме Action Sheet, существует Global Sheet (один на весь тест) — значения параметров, описанные в нём, изменяются при переходе к следующей итерации теста, а не Action.
В Mercury считают, что один Action должен примерно соответствовать одной бизнес операции, или одному Use Case. То есть, использование Actions (по Mercury) — основной способ функциональной декомпозиции. В реальности, вместо Actions для этих целей часто бывает удобнее использовать функции. Впрочем, это зависит от стиля Ваших тестов, в частности, от того, используете ли Вы параметризацию.
Вопрос: Что такое Reusable Action?
Ответ:
Для вызова Action из другого теста (либо из другого Action) необходимо, чтобы в свойствах action (Action Properties) была выставлена галочка "Reusable action".
Вопрос: Какие есть способы передачи значений переменных между разными Actions?
Ответ:
Каждый Action имеет свой контекст имён, поэтому переменные одного Action не видны из другого. Универсальный способ передачи переменных, начиная с версии QTP 6.0 — использование объекта Environment. Кроме того, начиная с версии 8.0 у Actions появились параметры (см. Help: Action properties, Action call properties, Action parameters). То есть, Action, — это в некотором смысле аналог функции с входными и выходными параметрами.
Использование объекта DataTable и параметризация
Вопрос: Что такое Data-driven тестирование? Как параметризировать тест?
Ответ:
Для того, чтобы вместо фиксированных значений параметров функций (например, текста, вводимого в поле ввода) использовать (в цикле) значения из таблицы, используется подход, называемый Data-Driven тестирование. При параметризации, исполнение теста происходит в форме исполнения двух вложенных циклов — по всему тесту целиком и по отдельным Actions. Соответственно, есть 2 типа параметров: глобальные — для всего теста, и локальные — для отдельных Actions. В начале каждой итерации все параметры приобретают значения, хранящиеся в строчке соответствующей таблицы (Global Sheet/Action Sheet), номер которой равен номеру итерации (теста или Action соответственно).
Вопрос: Что такое Run-time data sheet?
Ответ:
Кроме использования Data Table для хранения входных тестовых данных (параметры), QTP позволяет использовать его для хранения выходных данных (Output Values). Во время выполнения теста, значения в Data Table можно менять, однако они не будут сохранены в тесте. Зато их можно будет увидеть в отчёте об исполнении теста (логе).
Вопрос: Как приступить к параметризации, с чего начать?
Ответ:
Два самых удобных способа:
Из Keyword View (кликнуть на параметр функции, который хотите параметризировать) — появится кнопочка. Кликнуть — откроется диалог.
Tools>Data driver
Оба способа годятся только при параметризации методов тестовых объектов в тесте. В библиотеках параметризация по понятной причине не доступна.
Вручную это делается так:
1. В соответствующей таблице (Local Sheet или Global Sheet):
          a. DoubleClick на заголовке неиспользуемого столбца — вводим имя параметра
          b. Вручную заполняем ряды
2. Для использования параметра в скрипте, в качестве параметра функции или метода используем (MyParam — имя параметра):
DataTable("myParam",dtGlobalSheet) — для глобальных параметров (параметров теста)
DataTable("myParam",dtLocalSheet) — для локальных параметров (параметров Action)
Удобней использовать – DataTable.Value(1,1) и DataTable.Value(1,2)

http://software-testing.ru/images/stories/library/mercury-qtp-faq/1.gif
Вопрос: Какие существуют ограничения на использование DataTable?
Ответ:
Во время исполнения нельзя добавлять дополнительные ряды в таблицу. Кроме того, использование большого количество параметров и/или рядов заметно влияет на производительность. Поэтому DataTable рекомендуется использовать только по прямому назначению — для параметризации и хранения Output Values (Хотя существует развитый API для работы с таблицами — cм. Help по объектам: DataTable, Sheet, Parameter).
Логгинг
Вопрос: Что записывается в лог QTP, и можно ли это настроить?
Ответ:
Записываются все действия над тестовыми объектами (то есть, все statements, полученные во время записи теста) и сообщения об ошибках. Flow Controls statements, вызовы пользовательских функций и т.п. не записываются. Это — то, что QTP пишет в лог, если запись в лог не контролировать программно. Для работы с логом служит встроенный объект Reporter. У него есть всего один метод — ReportEvent() и одно свойство — Filter. Для записи в лог своего собственного сообщения (например, комментария или сообщения об ошибке), используется метод ReportEvent(). Метод хорошо описан в Help. При просмотре лога можно отфильтровать события по статусу (Done — информационные сообщения, Passed — успешно пройденные шаги; Warning, Failed — ошибки выполнения теста). Кроме того, записываемыми в лог сообщениями можно управлять из теста с помощью свойства Filter. При значении 0 (по умолчанию), записываются все сообщения; при 1 — Warning и Failed, 2 — failed, 3 — ничего. Причём, не записанные в лог сообщения НЕ влияют на статус теста и статистику.
Существует один хитрый трюк, позволяющий использовать в тексте сообщений лога HTML — см."Undocumented features".
Вопрос: Можно ли использовать HTML в логах?
Ответ:
Штатными средствами — нельзя. Но если в тексте параметра Description использовать подстроку "&", то описание события показывается в виде HTML. То есть, можно использовать форматирование, вставлять ссылки, делать таблицы, и т.п.
Пример:
Reporter.ReportEvent micDone, "Test HTML reporting", "
&
Test HTML Reporting"

Распознавание объектов в QTP
Вопрос : При воспроизведении записанного теста, QTP не распознаёт объекты. Почему? Что делать?
Ответ:
При записи теста QTP записывает описания объектов интерфейса тестируемого приложения (Application Under Test, AUT), с которыми тест взаимодействует, в Object Repository. Если QTP что-то не распознаёт, с 99.9% вероятности это означает, что свойства распознавания в Object Repоsitory указаны неверно. Это происходит потому, что при записи QTP записывает в Object Repository совершенно определённый набор свойств объекта, одинаковый для каждого отдельного типа объектов. Какие именно свойства QTP записывает для каждого типа объектов определяется настройками Object Idenfication (Tools>Object Identification...).
Следует:
Спомощью Object Spy выяснить, какие именно свойства, из тех что записываются в Object Repository для объекта, меняются от сессии к сессии;
Выяснить, какие свойства не меняются - их можно использовать для распознавания;
Пойти в Object Identification Settings (Tools>Object Identification) и для соответствующего типа объектов правильно настроить свойства распознавания (которые будут прописываться в Object Repository при записи).
Уже записанные скрипты использовать после такой процедуры не рекомендую. Можно, конечно, вручную поменять свойства распознавания для каждого объекта в Object Repository, но это может привести к неприятным последствиям — см. Раздел "Работа с Object Repository"
Вопрос: Как правильно настроить распознавание объектов в QTP с помощью настроек Object Identification?
Ответ:
В настройках Object Identification от обилия опций глаза разбегаются. Однако, всё довольно просто:
http://software-testing.ru/images/stories/library/mercury-qtp-faq/11.gif
Рис.1. Окно Object Identification
Mandatory Properties — свойства, которые QTP прописывает для этого типа объектов в Object Repository ВСЕГДА.
Assistive Properties — свойства, которые QTP прописывает в Object Repository ТОЛЬКО если во время записи объекта в OR в приложении наличествуют более одного объекта, удовлетворяющих Mandatory Properties
Ordinal Identifier — QTP использует, если даже при использовании и Mandatory и Assistive Propertires им удовлетворяет более одного объекта. Ordinal Identifier определённым образом "нумерует" похожие объекты. Делает он это так:
Index — по порядку создания в приложении
Location — слева направо, сверху вниз
Creation Time — только для Browser — по времени создания
Соответственно, в качестве Mandatory свойств надо прописывать такие свойства, которые чаще всего остаются неизменными от версии к версии, но при этом позволяют отличить один объект от другого.
Assistive свойства выбирают так: это свойства которые наверняка позволят отличить объекты один от другого, но есть небольшая вероятность их изменения от одной версии приложения к другой.
Настройка Objеct Identification зависит от манеры программирования разработчиков, специфики используемых технологий и т.д.
Настройки QTP по умолчанию не слишком удачны для работы с Win32 GUI приложениями, написанными НЕ на MFC и для динамических страниц Web. Наибольшие проблемы возникают от следующих настроек:
— Standard Windows:
Практически для всех типов объектов в качестве Assistive свойства указано window id. Для приложений, написанных без использования Microsoft Fundation Classes это приводит к тому, что объекты не распознаются при воспроизведении, так как window id меняется от сессии к сессии.
— Web:
Browser — не выставлены Mandatory и Assistive свойства. В качестве Ordinal Identifier используется Creation time. В результате, надёжность воспроизведения зависит от числа открытых браузеров и порядка их создания. Я использую в качестве Mandatory свойства — title.
Настройка Object Identification очень сильно зависит от специфики тестируемого Web-приложения, и какие-то общие рекомендации дать сложно. Рекомендуется с помощью Object Spy выяснить, по каким свойствам легче всего идентифицировать тот или иной тип элемента интерфейса (см. ответ на предыдущий вопрос).
Вопрос: Что такое Smart Identification?
Ответ:
Это такая опция, которую лучше не использовать :) Если серьёзно, то Smart Identification это опция, которая призвана сгладить неумелую настройку пользователем свойств распознавания объектов — с её помощью находятся объекты, которые не удовлетворяют их описанию в Object Repository. Проблема же заключается в том, что эту опцию правильно настроить заметно сложнее чем Object Identification - в результате, её использование у начинающих тестировщиков приводит к тому, что QTP пытается работать не с теми объектами (замечу, что это заметно хуже того случая, когда QTP просто не находит объекта). Опытные же пользователи QTP этой опцией предпочитают не пользоваться — так как умеют настраивать Identification так, что если QTP не находит объекта — значит его нет :)
Интересующихся отсылаю к Help — статья "Smart Identification, configuring"
Вопрос: Можно ли распознавать объекты интерфейса без использования Object Repository?
Ответ:
Можно. Причём, двумя разными способами:
1. C использованием объекта Description:
Пример из Help ("Using Description Objects for Programmatic Descriptions") :
set EditDesc = Description.Create()
         EditDesc("Name").Value = "userName"
         EditDesc("Index").Value = "0"
 Browser("Welcome: Mercury").Page("Welcome: Mercury").WebEdit(EditDesc).Set "MyName"
2. Явно указывая свойства распознавания:
Синтаксис:
TestObject("PropertyName1:=ProperyValue1", "..." , "PropertyNameX:=ProperyValueX")
Пример из Help ("Entering Programmatic Description Directly into Test Statements"):
Set MyWin = Window("Text:=Myfile.txt - Notepad")
         MyWin.Move 50, 50
         MyWin.WinEdit("AttachedText:=Find what:").Set "hello"
 MyWin.WinButton("Caption:=Find next").Click
Вопрос: Что делать, если элемент интерфейса тестируемого приложения распознаётся как "WinObject", несмотря на то, что является более специализированным элементом (таким как кнопка, drop-down list, edit box, и т.п.)?
Ответ:
Необходимо настроить распознавание для этого объекта (точнее, для всех объектов с тем же значением свойства native class). Для этого
Вызываем диалог Object Identification: Tools->Object Identification:
http://software-testing.ru/images/stories/library/mercury-qtp-faq/21.gif
Рис.2а: Настройка распознавания объектов нестандартных классов — последовательность действий.
Выбираем Environment->Standard Windows
Жмём на кнопку User Defined...
Вручную заполняем значение поля Class name…
… либо нажав на кнопку с изображением руки указываем нужный нам элемент интерфейса (тогда поле Class name заполнится автоматически)
Выбираем желаемый тип элемента интерфейса
Жмём Add
Жмём OK

http://software-testing.ru/images/stories/library/mercury-qtp-faq/22.gif

Рис.2б: Настройка распознавания объектов нестандартных классов — результат.
В диалоге Object Identification выбираем добавленный класс и изменяем свойства его распознавания (если нужно)
Жмём OK
Работа с Object Repository
Вопрос: Объекты типа Page/Frame дублируются в Object Repository при записи скрипта. Почему?
Ответ:
Действительно, по умолчанию QTP создаёт новые объект после каждого запроса "POST" на сервер. Чтобы этого не происходило в 6.5:
Tools>Options>Закладка "Web" >Кнопка "Advanced":
http://software-testing.ru/images/stories/library/mercury-qtp-faq/31.gif
Рис.3а: Настройка свойств записи Page/Frame в версии QTP 6.5
Create New Page object for: Установите "Pages with different test object description".
Optimize Page/Frame test object creation - снимите флажок.

В QTP 8.2 и 9 эти опции вынесены в отдельный диалог:
http://software-testing.ru/images/stories/library/mercury-qtp-faq/32.gif
Рис.3б: Настройка свойств записи Page/Frame начиная с версии 8.2
Вопрос: В каких случаях QTP создаёт новые объекты в Object Repository (настройка Web settings?)
Ответ:
QTP будет создавать новые объекты в Object Repository если :
Значения свойств объекта не совпадают со свойствами объектов в Object Repository
(ВНИМАНИЕ!) Список свойств объекта, находящегося в Object Repository не совпадает со списком свойств в Object Identification Settings для этого типа объекта. То есть, если Вы изменили описание объекта либо поправили Object Identification Settings, при последующей записи скрипта QTP создаст новый объект.
Поэтому, СНАЧАЛА выставляем Object Identification Settings, потом записываем скрипт. При изменении Object Identification Settings, с большой долей вероятности в репозитории будут создаваться новые объекты.
Вопрос: Чем отличается тип репозитория Shared от per Action?
Ответ:
Начиная с версии 9, в QTP каждый тест может иметь одновременно локальные (для каждого Action'a) и разделяемые (для нескольких тестов) репозитории. Причём, каждый отдельный action может ссылаться одновременно более чем на один shared репозиторий (для каждого action’a репозитории могут быть разные). Как это выглядит? Для того, чтобы проассоциировать каждый action со своим репозиторием надо открыть диалог "Associate Repositories" (Resources>Associate Repositories..):
http://software-testing.ru/images/stories/library/mercury-qtp-faq/5.gif
Рис.5: Окно Associated Repositories в QTP 9.0
Теперь при открытии диалога Object Repository показывается не отдельный репозиторий, а "сумма" проассоциированных с текущим action shared репозториев и локального репозитория Action'a. Конфликты репозиториев разрешаются автоматически — учитывается порядок следования shared репозиториев в списке в диалоге "Action Properties", закладка "Associated Repositories". В окне Object Repository редактировать можно ТОЛЬКО объекты, лежащие в локальном репозитории. Чтобы редактировать shared репозиторий, его необходимо открыть в окне "Object Repositories Manager" (Resources>Object Repository Manager). Причём, не забудьте при открытии убрать опцию "Open as read-only". Object Repository Manager позволяет сливать локальные и shared репозитории, сливать разные shared репозитории с помощью Object Repository Merge Tool, перемещать объекты между репозиториями, и т.п.
Возникает закономерный вопрос: как использовать все эти новые возможности (и зачем они вообще нужны)? Ответ довольно прост — для обеспечения комфортной совместной работы над тестами, использующими один и тот же Shared Object Repository. То есть, пока мы пишем/редактируем наш отдельно взятый тест, мы не меняем объектов в Shared Object Repository. Когда все тесты готовы и отлажены, их Object Respositories сливаются с shared. Вот, собственно и всё (до следующего релиза ;-) ). Ну а новые возможности, такие как использование нескольких репозиториев одновременно, использование различных репозиториев для разных action'ов, экспорт и импорт в XML, я думаю, лишними не будут.
Вопрос: Каким образом свойства распознавания объектов в OR могут поменяться?
Ответ:
Не забывайте при запуске теста в режиме Update Mode снимать галочку "Update test object properties" — иначе все описание всех объектов, с которыми работает тест будут обновлены, причём свойства, отсутствующие в Object Identification Settings для данного типа объектов будут удалены.
Вопрос: Можно ли отказаться от использования Object Repository? Как?
Ответ:
Да, многие тестировщики, работающие с QTP стремятся отказаться от работы с Object Repository. Причин много (правда, многие из них устранены с выходом QTP 9.0). Среди причин отказа от использования Object Repository можно перечислить:
проблемы с использованием библиотек совместно с Object Repository. Действительно, в идеале библиотеки функций должны работать вне зависимости от используемого тестом репозитория. Впрочем, проблема скорее идеологическая. В принципе, ничто не мешает разрабатывать библиотеки, имея в виду их работу с определённым репозиторием. Особенно в QTP 9.
проблемы правильной настройки Object Identification. Хотя Object Identification настраивается достаточно гибко, тестировщику зачастую хочется самому контролировать, по каким свойствам распознаётся объект.
(для версий QTP 6.0-8.0) невозможность совместного использования нескольких Object Repository. В результате приходится использовать один гигантский репозиторий для всех тестов, либо руками создавать объекты (и переименовывать их) в каждом репозитории. А уж если представить себе ситуацию когда с этим репозиторием что-то случится (некоторые версии QTP не слишком дружат с большими репозиториями)... Обратите внимание, что начиная с QTP 9.0 появилась возможность использовать несколько object repositories для одного action'a.
(для версий QTP 6.0-8.2) QTP не предоставляет штатных средств для копирования объектов как в пределах одного репозитория, так и между несколькими репозиториями (QTP Plus я в расчёт не беру — он работает не со всеми версиями, и вообще является "кустарным" решением). Внимание, начиная с версии 9.0 появились штатные средства редактирования нескольких репозиторием — Object Repository Manager и Object Repository Merge Tool.
Основной плюс репозитория, в том что это способ повторного использования данных, который позволяет один раз в одном месте изменить описание объекта, который многократно используется тестом. Кроме того, отказавшись от использования репозитория мы автоматически отказываемся от использования записи скриптов. Встаёт вопрос — как отказаться от OR и при этом не лишится этих преимуществ? К сожалению, ни одно решение не позволяет научить QTP записывать тест без использования Object Repository. Другая проблема — повторное использование определений объектов решается с переменным успехом.
Многие пытаются создавать свои альтернативные OR — на XML, в Excel и т.п. Однако, я не вижу больших преимуществ такого решения по сравнению со стандартным Object Repository. Точнее, преимущества есть, но они скрадываются неудобством использования (главным образом — громоздкостью синтаксиса вызова объектов при их использовании либо (при простоте синтаксиса) — отсутствие решения проблем пересечения пространств имён (действительно, неприятно если для всех объектов придется придумывать разные имена вне зависимости от того, к какому объекту верхнего уровня они относятся)).
Мне больше по душе подход, комбинирующий использование объектов Description (для дочерних объектов) с "Helper Functions", возвращающими объекты верхнего уровня, такие как Page, Frame, Window и т.п.:
'== Функция для библиотеки - переводит строку в объект Description
public function TODescriptionFromString(aString)
   Dim aProp,aValue
   Dim PairsArr,i
   Dim aDescription
 set aDescription = description.create
   PairsArr = Split(aString,";")
   for i = 0 to UBound(PairsArr)
   on error resume next
   aprop = Split(PairsArr(i),"=")(0)
   aValue = Split(PairsArr(i),"=")(1)
   on error goto 0
   if aprop<>"" then
   aDescription.Item(aprop).value = aValue
   end if
   next
 set TODescriptionFromString = aDescription
       end function
'Oпределяем Description для кнопки

   set MyFrame_SearchBtn = TODescriptionFromString("innertext=Search;index=0")
'Helper для Frame'a
       public Function GetMyFrame()
       set GetMyFrame=Browser("title=My Page").Page("index:=0").Frame("name:=MyFrame")
   end function
'Вполне компактная запись получается:
       GetMyFrame().WebButton(MyFrame_SearchBtn).Click
Методы Test Object
Вопрос: Как получить доступ к дочерним объектам (если мы не знаем их свойств)?
Ответ:
Для этого есть замечательный метод — ChildObjects. Использовать ChildObject легко, и этот метод достаточно хорошо описан в Help.
Set oDesc = Description.Create() 

         oDesc("micclass").Value = "WebList" 

         Set Lists = Browser("Mercury Interactive").Page("Mercury Interactive").ChildObjects(oDesc) 

         NumberOfLists = Lists.Count() 

         For i = 0 To NumberOfLists-1 

         Lists(i).Select i+1 

         Next 
В Web, метод ChildObjects применим к объектам типа Page и Frame.
Другой способ — использовать Ordinal Identifier в качестве единственного свойства в описании. Тогда пример из Help будет выглядеть примерно так (не слишком изящно, скажем прямо, и, к тому же, заметно медленнее):
Dim listsArr()

       Redim listsArr(1000)

       i=0

       notfound = false

       do

       if Browser("Mercury Interactive").Page("Mercury Interactive").WebList("index:="&Cstr(i)).Exist(0) then

       Set listsArr(i) = Browser("Mercury Interactive").Page("Mercury Interactive").WebList("index:="&Cstr(i))

   i=i+1

   else

   notfound = true

   end if

   loop until notfound
Redim Preserve listsArr(i-1)
for i = 0 to UBound(listsArr)

   listsArr(i).Select i+1

   end if
При работе с объектом WebTable используется другой метод — ChildItem (см. Help). К сожалению, как этот, так и другие методы WebTable для работы с ячейками (например, GetCellData) работают чрезвычайно медленно с большими таблицами. В этом случае единственным решением является использование свойства .object таблицы.
Вопрос: Что такое свойство object?
Ответ:
Свойство object есть почти у всех объектов Web (исключением является Browser), объектов VisualBasic, .NET , Java, ActiveX (при установке соответствующих Add-ins). С его помощью можно получить доступ к "родным" (native) свойствам и методам объекта соответствующей среды разработки. Так, свойство object Web-объектов предоставляет доступ к COM-объектам библиотеки MSHTML 4. Те кто знакомы с программированием DHTML страниц, поймут о чём я говорю — получив доступ к объекту элемента DOM мы с ним работаем так же, как если бы мы программировали DHTML cкрипт для Internet Explorer.
Ниже приведён пример работы c полем .object WebTable:
'Эта функция позволяет получить текст ячеек таблицы в виде массива
Public Function tableSaveToArray2D (table,Byref arr)

       Dim i,j,rowcount,oTable,colcount,curcc,oRow 

       Dim fakeArr(0,0)

       TableSaveToArray2D = false
If Not isObject(Table) Then

   Reporter.ReportEvent micWarning,"tableSaveAsArray2D","Invalid parameter (table)!"

   Exit Function

   End If
If Not table.exist(10) Then

   Reporter.ReportEvent micWarning,"tableSaveToArray2D","Table not found!"

   Exit Function

   arr = fakeArr

   tableSaveToArray2D=false

   End If
set oTable = table.Object

       rowcount = oTable.Rows.Length

       

       For i = 0 To rowcount -1

   set oRow = oTable.Rows(i)

   curcc = oRow.cells.length

   colcount = Max(curcc,colcount)

   Next
Redim Arr(rowcount-1,colcount-1)

         

         For i = 0 to rowcount-1

   For j = 0 To colcount-1 

   On Error Resume Next

   Arr(i,j) = Replace(cstr(oTable.rows(i).cells(j).innertext),vbCrLf,"\n")

   If Err.description <> "" Then

   Arr(i,j) = ""

   Err.Clear

   end if

   On Error goto 0

   Next 

   Next
TableSaveToArray2D = true

       End Function
Синхронизация
Вопрос: Тест не дожидается появления/отрисовки объекта, сообщает об ошибке и переходит к выполнению следующих операторов (также с ошибками). Как сделать так, чтобы QTP дожидался появления объектов либо их определённого состояния (например, enabled)?
Ответ:
Этот вопрос хорошо освещён в Help. Cм. "Adding Exist and Wait Statements"," Solving Synchronization Problems", " Modifying Timeout Values".
Вкратце же:
1. Необходимо настраивать установки таймаутов:
Для всех сред:
Object Synchronization Timeout (Test > Settings > Run tab)
Для Web:
Browser Navigation Timeout (Test > Settings > Web tab).
2. Если надо дождаться появления объекта, надо использовать метод .Exist
Синтаксис такой:
.Exist без параметров — ждём Object Syncronization Timeout до появления объекта. Не рекомендуется.
.Exist(timeout) — ждать появления объекта timeout секунд. Возвращает true если удалось дождаться появления объекта, false — если нет. Используем так:
var = TestObject.Exist(timeout)
либо
if not TestObject(timeout) then

end if
К сожалению, запись
TestObject.Exist timeout
не работает, видимо из-за нюансов определения этого метода.
3. Чтобы дождаться нахождения объекта в нужном нам состоянии, используем метод .WaitProperty:
Пример #1
If Browser("index").Page("index").WebEdit("Account").WaitProperty("disabled", 0) 

         then 

   Browser("index").Page("index").WebEdit("Account").Set ("123") 

   End If 
Пример№2
If Browser("index").Page("index").Link("All kind of").WaitProperty("attribute/readyState", "complete", 4000) then 
   Browser("index").Page("index").Link("All kind of").Click 
   End If

Свойства Объектов
К сожалению, терминология свойств объектов QTP не слишком прозрачна. Поэтому часто возникает путаница.
Вопрос: Чем отличаются TO Property, RO Property и Run-time object property?
Ответ:
TO Properties — свойства объекта, используемые при его идентификации. Метод GetTOProperty возвращает то значение свойства, которое использовалось при его (объекта) идентификации. Если оно не использовалось, то ничего хорошего не возвращается. Список свойств объекта, которые можно использовать при идентификации указан в Help для каждого класса объектов. TO свойства показываются в Object Spy при выборе опции "Test Object Properties/Methods". Следует обратить внимание на то, что показываются ТОЛЬКО те свойства, которые прописаны в Object Identification, что весьма неудобно.
RO Properties — свойства объектов, в данный момент отображаемых в тестируемом приложении. Их список — тот же, что и у TO Properties. Соответственно, метод GetROProperty возвращает свойства объекта в тестируемом приложении, только если объект этот в данный момент существует (не обязательно отображается).
Run-Time Object properties — поля объекта .object. При тестировании Web есть трюк, позволяющий получить доступ к этим полям при использовании метода GetROProperty и при идентификации. Для этого используется конструкция attrubute/… Например, вот так:
readyState = Browser("index").Page("index").GetROProperty("attribute/readyState")/
Но проще всё же записать так:
readyState = Browser("index").Page("index").object.readyState
Оригинальная статья на http://software-testing.ru/library/testing/functional-testing/139#uf
Результат: Работающий тест.
Задание: Залогиниться на gmail, логин и пароль должны хранится в таблице