Показаны сообщения с ярлыком автоматизация. Показать все сообщения
Показаны сообщения с ярлыком автоматизация. Показать все сообщения

понедельник, 29 июня 2009 г.

QTP: DP в 60-ти простых слайдах




Автор: Yaron Assa
Перевод: Сергей Талалаев (SQAdotBY)
Оригинальная публикация: DP in 60 slides




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

В рамках данной небольшой презентации автор умудрился разложить по полочкам ключевые моменты Дескрипторного Программирования (DP) применяемого в QTP. Причем сделал это с драйвом и без лишней воды.

Сейчас для меня эти принципы кажутся настолько же очевидными и понятными насколько они были туманны и запутанны в момент начала изучения QTP :) Именно для того, чтобы сократить путь от тумана к полной ясности я перевел эту презентацию и уверен, что она вас не разочарует.

Read more...

четверг, 11 июня 2009 г.

10 Причин провала автоматизации




Автор: Shrini Kulkarni
Перевод: Сергей Талалаев (SQAdotBY)
Оригинальная статья: 10 ways to make automation difficult or ineffective


Нашему коллеге, сформулировавашему эту десятку причин можно ставить памятник при жизни (согласен со всем на 100%). А глядя в его мудрые грустные глаза понимаешь, что расхлебывал все это он сам лично "Вот этими вот руками..." :)

Однозначно можно распечатывать и вешать на стенку.


10. Безумное желание о 100% автоматизации

9. Попытка автоматизировать существующие тест кейсы без тщательного анализа на предмет их пригодности к автоматизации

8. Линейное сопоставление тест кейсов и скриптов 1:1 – становясь жертвой обманчивого удобства в контроле над изменениями и отчетности.

7. Создания проекта автоматизации игнорируя модель “снизу-вверх”, нечеткое разбиение проекта на функциональные части.

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

5. Фокусировка только на задачах, связанных с выполнением тестов

4. Использование автоматизации как скриптования – игнорируя общепринятые практики разработки ПО.

3. Отказ от привлечения разработчиков на начальной стадии – не стремясь к улучшению тестируемости или автоматизируемости приложения

2. Погружение в атоматизацию ради ускорения тестирования или сокращения издержек до решения существующих проблем – неоднозначности, неэффективности и отсутствия целостности.

1. Отказ от поиска правильной пропорции между ручным и автоматизированным тестированием.

0. Использование автоматизации в качестве средства выявления ошибок


Read more...

вторник, 12 мая 2009 г.

QTP: Реализация GUI слоя при помощи классов



Автор: Meir Bar-Tal
Перевод: Сергей Талалаев (SQAdotBY)
Оригинальная статья: Implementing a GUI Layer with Classes


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

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


Аннотация

Эта статья описывает действенную технику, которая используя ООП шаблоны проектирования, дескрипторное программирование (DP) и объект Dictionary позволяет объединить GUI объекты вместе с их бизнес функциями. Статья также включает ценное дополнение: эффективный прием, позволяющий избежать зависания QTP при попытке обращения к несуществующим GUI объектам во время выполнения.


Введение

Основная проблема в автоматизированном тестировании – это как уменьшить издержки по поддержке скриптов. Вопросы вида: “Должны ли мы использовать объектный репозиторий (Object Repository OR) или дескрипторное программирование (Descriptive Programming DP)? Если выбран OR, то должны ли мы использовать общий OR или локальный для каждого Action? Если выбран DP, тогда какой оптимальный вариант его реализации?” достаточно повсеместны и ответы на них могут зависеть как от конкретных особенностей проекта так, во многих случаях, и от людей, вовлеченных в процесс.

В этой статье я проанализирую концепцию Тестовых Объектов (Test Objects) в рамках принципов OO (Object Oriented). Я попытаюсь показать, что реализация объектного репозитория в QTP не соответствует этим принципам, и каково влияние этого факта на разработку автоматизированных тестов с точки зрения эффективности затрат и трудоемкости поддержки. Затем я опишу расширение OR-концепции, которое соответствует принципам OO – GUI слой (GUI Layer). Эта концепция была адаптирована экспертами компании SOLMAR, основываясь на том факте, что возможно максимизировать повторное использование кода (и таким образом улучшить поддерживаемость кода) используя OO подход, согласно которому автоматизируемый проект разбивается на несколько уровней абстракции.


Тестовые Объекты и Run-Time Объекты

Тестовый объект содержит в себе ссылку на run-time объект – объект реального мира, который инициирован в тестовом приложении. Тестовый объект содержит описание объекта, на который он ссылается, в виде набора атрибутов и значений служащих критерием для поиска нужного объекта в ходе тестового прогона. Это описание больше всего похоже на то, что вы себе представляете, идя на встречу с незнакомкой (“Я брюнетка, стройная и высокая, и буду одета в красное платье и туфли”)

Аналогично QTP использует описание для запроса к OS, загружен ли в настоящий момент объект в оперативную память. Если ответ положительный, то OS вернет адрес объекта (ссылку или указатель) и, следовательно, QTP получит доступ к публичным методам и свойствам объекта, в то время как частные методы и свойства остаются скрытыми от просмотра по определению (таким образом QTP никогда не вмешивается в частную область, чего вы бы хотели в отношении брюнетки, если повезет!)

Хотя это описание может быть слишком упрощено, но по существу это такой процесс, который позволяет нам взаимодействовать с GUI (и другими) объектами используя QTP или другое средство автоматизации (Test Partner, Test Complete, Rational Robot, AutoIt и т.д.) Более детальное объяснение различия между Тестовыми Объектами и Run-Time Объектами доступно в статье Yaron Assa "Differences and Connections between Runtime Objects and Test Objects" (2009).


Тестовые Объекты и Объектный Репозиторий

Рассказанное выше естественно заставляет нас думать о тестовых объектах как о данных. Что я имею в виду? Основываясь на описании, построенном из свойств и значений, QTP имеет возможность распознать GUI объект среди всех объектов, загруженных в данный момент в машинную память. Этот процесс подобен тому, как мы получаем необходимую запись из БД согласно условию WHERE в SQL запросе. Разница лишь в том, что в данном случае OS (Windows), а не БД возвращает запись. Кроме того, запись содержит только одно поле – ссылку на реальный run-time объект. Следуя данной мысли, это кажется вполне естественным хранить эти записи - тестовые объекты (Test Objects) – в базе данных, которой собственно Объектный Pепозиторий (Object Repository) и является (если вы обратили внимание на файлы с расширением bdb в QTP тестах, то знайте, что bdb в действительности означает Berkeley Data Base – продукт компании Oracle).

В чем же собственно проблема с подходом, использующим OR? Тестовые объекты в действительности являются данными, но мы до текущего момента вынуждены выполнять действия с Run-time объектами, что, учитывая вышесказанное, предоставляет нам искаженную картину. Ниже я объясню почему.

Это действительно, правда, что OR, при правильном использовании, предоставляет наилучшую технику, в соответствии с которой нам необходимо сохранить описание каждого GUI объекта всего лишь раз для уменьшения стоимости изменений. Тем не менее, чтобы достичь этого должны быть потрачены большие усилия на правильное управление тестовым проектом, потому что непродуманные запросы и недостаток ресурсов могут привести нарушению целостности этого ценного ресурса (OR). Например, предположим, что два инженера автоматизации работают одновременно с общим репозиторием, но один из них модифицирует скрипт для прошлой версии приложения, а другой – для новой. При условии, что GUI изменения выполняются регулярно от одной версии приложения к другой, не придется долго ждать, пока репозиторий окажется заполненным новыми лишними объектами необходимыми для работы с новой версией приложения. И это еще относительно неплохой результат. Гораздо более худший результат вы получите в случае, если каждый инженер изменяет набор свойств существующих объектов для отражения своих требований, безвозвратно разрушая ROI (возврат инвестиций) проекта автоматизации в целом. Конечно имеются решения и для таких ситуаций, такие как хранение отдельных версий репозитория для соответствующей версии приложения и использование специального ПО по управлению конфигурациями в рамках проекта автоматизации. Но, как говорилось ранее, это требует хорошего управления проектом, что не всегда доступно.

Кроме того поддержка версионности объектного репозитория оставляет открытой одну проблему. По причине того, что автоматические тесты являются регрессионными по своей сути, их модификация затрагивает не только OR, но также и код, который реализует непосредственные манипуляции с GUI объектами и проверки, также как и работу с входными данными и ожидаемым результатом. В общем случае, когда при переходе от одной версии приложения к другой меняются только описания объектов, использование объектного репозитория действительно будет оправданным. Тем не менее, чаще ситуация обратная, изменения в GUI отражают изменения в функциональности приложения, которые в свою очередь гораздо чаще сопровождаются более глубокими изменениями – на уровне БД, например. Таким образом, изменения в GUI требуют изменений как на уровне объектного репозитория, так и на уровне скрипта, который ссылается на тестовые объекты и плюс к этому на уровне входных данных для самого скрипта. Учитывая то факт, что скрипты чаще всего подвергаются модификации, а не разработке, вышеупомянутый анализ приводит меня к мысли, что нечто в концепции OR неправильно по отношении к управлению крупномасштабными проектами автоматизации.


Объектно-ориентированный взгляд

Концепция ООП базируется на трех основных принципах – инкапсуляции, наследовании и полиморфизме. Инкапсуляция означает упаковку вместе функциональности и данных, которые сосуществуют вместе и данная упаковка, через которую осуществляются обращения, называется классом. Фактически классы – это представление данных (например, Customer, Product и т.д.) Различие между полнофункциональным классом и обычной структурой данных в том, что класс содержит в себе функции по работе со своими данными - полями. Эти функции обычно называются методами класса. Например, типичный класс для Customer-а включал бы себя следующие поля, которые однозначно определяют покупателя (customerId, firstName, lastName, phoneNo и т.д.) вместе с методами setCustomerId, getCustomerId, которые присваивают и возвращают значения соответствующим полям, также как и getCustomerAge and getCustomerBalance выполняющими расчеты на основе текущих значений полей и возвращающие результат.

Наследование тесно связано с одной из важнейших целей ОО подхода – повторного использование кода. В объектно-ориентированных языках, таких как C++ и Java, повторное использование кода вступает в игру посредством возможности создавать новый класс, который “наследует” поля и методы уже созданного класса (называемого базовым классом) и расширяет их согласно специфическим требованиям, поставленным для нового класса.

Полиморфизм – это еще один мощный принцип, который делает возможным определять несколько версий одной функции (с одним именем, но с различным набором аргументов) для того чтобы прозрачно реагировать на различные ситуации в рамках контекста приложения. Например, у нас есть необходимость производить одну и ту же операцию с различным набором аргументов (float, int) и тогда вместо того, чтобы в одной функции реализовывать набор условных операторов для проверки типов переданных параметров, мы определим несколько функций с одинаковым именем, но с разной сигнатурой (различным набором аргументов). Следовательно, в нашем коде, использующем эти функции, нам не придется использовать приведение типов; мы будем использовать одинаковый интерфейс в обоих случаях, полагаясь на то, что корректный вызов будет осуществлен самой средой выполнения. Тем не менее, в QTP две последние концепции (наследование и полиморфизм) не могут быть реализованы в рамках VB скрипта, который обеспечивает только ограниченную поддержку работы с классами. Тем не менее, позже мы увидим, что это не причина отказываться от использования классов в автоматизации тестирования.

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

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


Автоматизация Тестирования и Разработка ПО

Я был свидетелем одной вещи на протяжении всей моей карьеры – это то, что QA профессионалы всех уровней рассматривают автоматизацию тестирования лишь как особый вид тестовой деятельности. Не удивительно, что не так уж редко можно встретить профессионалов в автоматизации, думающих также о роли автоматизации. Иногда это даже отражается в названии должностей для персонала автоматизации: “авто-тестер” - это одно из абсурдных названий из тех, что я встретил несколько лет назад. Все это отражает непонимание роли Инженера Автоматизации и, как я объясню в дальнейшем, данное мнение действительно не соответствует сущности автоматизации тестирования.

Задача автоматизации тестирования не должна рассматриваться иначе, чем любая другая контекстно-зависимая задача автоматизации. Вообще говоря, компьютерная программа, которая выполняет набор операций вместо человека – реализует автоматизацию. Таким образом, любой блок кода по сути можно рассматривать как автоматическое устройство или робота. Скрипты, которые производят операции над GUI объектами (как тесты в QTP) не отличаются от других частей ПО. Говоря другими словами, проект тестовой автоматизации, несомненно, является специфичным видом проекта по разработке ПО. И как любой программный продукт проект автоматизации также имеет свой собственный документ с функциональными требованиями (Software Requirements Specifications) и дизайн (Software Test Design) документ (либо тест дизайн в одном из промышленных фреймворков, например HP’s Quality Center или Orcanos’ QPack), которыми должен руководствоваться инженер автоматизации при реализации требуемого кода.

Если это так, то проект автоматизации фактически должен разрабатываться и управляться как любой другой проект разработки, даже более того. А все потому, что инженер автоматизации сталкивается с задачами, которые обычно не касаются разработчиков. Некоторые основные задачи таковы:

  1. Во-первых, инженер автоматизации должен иметь общее понимание системы, так как автоматически скрипт может покрывать широкий спектр функциональности приложения. Члены команды разработки напротив не нуждаются в этом в силу разделения труда среди разных команд обычно координируемых тим-лидерами и менеджером проекта. Таким образом разработчик может сфокусироваться только на часть функционала,за которую он отвечает даже не имеяглубокого понимания системы целиком.

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

  3. В-третьих, GUI-элементы используемые командой разаработки и само поведение приложения могут поставить действительно сложные технологические проблемы касающиеся идентификации объектов на уровне QTP (или другого фреймворка). В большинстве случаев ребуются решения, расширяющие базовые возможности фреймворка особенно в случае использования сторонних и собственных комопонентов.


Следуя описанному выше, я думаю, мы можем заключить, что проект автоматизации определенно должен управляться также как проект разработки. Если это так, почему кто-то должен снова и снова становиться жертвой заблуждения о проекте автоматизации как о тривиальной задаче (методика ”записи-воспроизведения” ничего не напоминает?) в то время как верно обратное? Почему бы тогда не использовать широко применяемый при разработке подход – Объектно Ориентированное Программирование – чтобы достичь наилучших результатов? Далее я опишу методику реализации автоматизированных скриптов, основанную на расширении концепции OR ( GUI слой ) и базирующую на твердых принципах ООП.


Концепция слоев

Я надеюсь, что объяснил достаточно подробно, почему подход с использованием Объектного Репозитория (OR), повсеместно используемый в скриптах, далек от оптимального. Теперь, продолжая начатое обсуждение, позвольте взглянуть на концепцию разработки кода, разделенного на слои или собственно концепцию GUI слоя. Вообще, слои весьма полезны для максимизации повторного использования кода (возвращаясь к предыдущему обсуждению принципов ООП). Я бы определил GUI слой как множество классов, которые объединяют (инкапсулируют) вместе необходимые интерфейсы для манипуляции GUI объектами тестового приложения для выделенной функционально части. Другими словами – это множество классов, обеспечивающих связь между GUI тестового приложения (то есть определенных тестовых объектов) и Бизнес или Прикладным Слоем, о котором мы поговорим позднее. Может быть, было бы более подходящим назвать его Слой GUI-Бизнес Адаптера, но среди экспертов уже устоялся термин GUI Слой, для краткости. Я проиллюстрирую ниже, как такой слой может быть создан и, какие преимущества достигаются при применении данного подхода в рамках тестовой автоматизации.

Реализация GUI Слоя

Инкапсуляция Тестовых Объектов в Классы

Давайте возьмем проект тестовой автоматизации для типичного приложения и посмотрим, каким образом должен быть построен фреймворк для достижения описанных выше целей. Первым шагом будет создание списка всего GUI контекста в приложении – окон (страниц в Web приложениях), диалогов и всплывающих окон. Для каждого элемента этого списка, который в свою очередь выступает контейнером для других GUI объектов, мы определяем класс, например:

Class Login

End Class

Class MainWindow

End Class

Class CreateCustomer

End Class

и так далее для каждого контекста приложения. По причине того, что QTP не позволяет прямое создание класса определенного во внешней библиотеке с помощью оператора New, нам также необходимо определить следующую функцию (разновидность конструктора), которая вернет нам экземпляр GUI-слоя:

'——————————————————————————-
Public Function CreateLogin()
'——————————————————————————-
'Function: CreateLogin
'Creates an instance of the Login class
'
'Remarks:
'
'Arguments:
' N/A
'
'Returns:
' Object - As Login
'
'Owner:
' John Doe
'
'Date:
' dd-MMM-yyyy
'
'——————————————————————————-

Dim objLogin

Set objLogin = New Login

Set CreateLogin = objLogin
'——————————————————————————-
End Function
'——————————————————————————-

Второй шаг, очевидно, определить список элементов внутри каждого класса. Теперь, так как каждый класс, согласно вышеизложенному – это контейнер других GUI объектов, мы будем использовать Scripting.Dictionary для хранения ссылок на тест-объекты находящиеся на окне, диалоге или странице. (объект Dictionary широко обсуждался в статьях опубликованных в AdvancedQTP’s базе знаний). Таким образом, первый элемент который я представлю здесь, будет общим для всех GUI Layer классов, и я определю его как m_htChildObjects:

Class Login
Private m_htChildObjects 'As Scripting.Dictionary

End Class

Class MainWindow
Private m_htChildObjects 'As Scripting.Dictionary

End Class

и так далее для каждого контекста приложения (ht – префикс для HashTable, чем объект Dictionary на самом деле и является). Частный элемент m_htChildObjects будет доступен через свойство класса ChildObjects. Это свойство определено как:

'——————————————————————————-
'Property: ChildObjects
'Get and Set the m_htChildObjects member field
'
'Remarks:
' R/W
'
'Arguments:
' dic
'
'Returns:
' m_htChildObjects As HashTable
'
'Owner:
' John Doe
'
'Date:
' dd-MMM-yyyy
'
'——————————————————————————-

Public Property Get ChildObjects()
'——————————————————————————-
Set ChildObjects = m_htChildObjects
'——————————————————————————-
End Property
'——————————————————————————-

'——————————————————————————-
Public Property Let ChildObjects(ByRef dic)
'——————————————————————————-
Set m_htChildObjects = dic
'——————————————————————————-
End Property
'——————————————————————————-

Третий шаг – определение всех объектов внутри каждого контекста. Для этой цели я определю публичный метод Init:

'——————————————————————————-
Public Function Init()
'——————————————————————————-
'Function: Init
'Initializes the context and child objects
'
'Dependencies:
' IsContextLoaded(htContext)
'
'Remarks:
' N/A
'
'Arguments:
' N/A
'
'Returns:
' True/False
'
'Owner:
' John Doe
'
'Date:
' dd-MMM-yyyy
'
'——————————————————————————-

ChildObjects = CreateObject("Scripting.Dictionary")

With ChildObjects
.Add "Browser", Browser("name:=My App")
.Add "Page", ChildObjects("Browser").Page("title:=My App \- Login")
.Add "Username", ChildObjects("Page").WebEdit("html id:=Username")
.Add "Password", ChildObjects("Page").WebEdit("html id:=Password")
.Add "Submit", ChildObjects("Page").WebButton("outertext:=Submit")
End With

'IsContextLoaded is a function that iterates through the Dictionary and checks if the GUI objects "exist"
Init = IsContextLoaded(ChildObjects)
'——————————————————————————-
End Function
'——————————————————————————-

Часть кода, показанного выше, описывает типичный метод Init для GUI Layer класса страницы логина в Web приложении. Тестовые объекты добавляются, как элементы словаря ChildObjects и их свойства определены посредством Дескрипторного программирования (DP). Читатель может легко провести аналогию с Объектным репозиторием (OR). Благодаря этому встроенному методу мы можем быть уверены, что GUI-объекты всегда определяются в одном месте. В конце кода метода вы можете отметить, что он возвращает результат вызова функции IsContextLoaded которая принимает в качестве аргумента словарь, содержащий ChildObjects.
IsContextLoaded определятся в отдельной общей библиотеке, следующим образом:

'——————————————————————————-
Public Function IsContextLoaded(ByRef htContext)
'——————————————————————————-
'Function: IsContextLoaded
'Checks that the current GUI context is loaded
'
'Iterates through the htContext (HashTable) items and executes the Exist method with 0 (zero) as parameter.
'
'Remarks:
' N/A
'
'Arguments:
' ByRef htContext - As HashTable
'
'Returns:
' True/False
'
'Owner:
' Meir Bar-Tal, SOLMAR Knowledge Networks Ltd.
'
'Date:
' 11-Nov-2008
'
'See Also:
'
'——————————————————————————-

Dim ix, items, keys, strDetails, strAdditionalRemarks

'—————————————————————————
items = htContext.Items
keys = htContext.Keys

For ix = 0 To htContext.Count-1
IsContextLoaded = IsContextLoaded And items(ix).Exist(0)
strDetails = strDetails & vbNewLine & "Object #" & ix+1 & ": '" & keys(ix) & "' was"
If IsContextLoaded Then
intStatus = micPass
strDetails = strDetails & ""
strAdditionalRemarks = ""
Else
intStatus = micWarning
strDetails = strDetails & " not"
strAdditionalRemarks = " Please check the object properties."
End If
strDetails = strDetails & " found." & strAdditionalRemarks
Next
'—————————————————————————

Reporter.ReportEvent intStatus, "IsContextLoaded", strDetails
'——————————————————————————-
End Function
'——————————————————————————-

И она возвращает Истину если все объекты, определенные в словаре идентифицированы или Ложь если хотя бы один из объектов не найден. Эта функция универсальная и используется для всех проектов, которые я веду для того чтобы быть уверенным, что QTP не зависнет при попытке выполнения операций с несуществующим GUI-объектом. Еще одно преимущество этого метода в том, что он указывает точно на тот объект, который вы хотите проверить и изменить, делая поддержку значительно более легкой.


Инкапсуляция бизнес методов в классы

Следующий шаг, после определения дочерних объектов для тестируемого контента – это определение операций, необходимых для выполнения бизнес-сценариев в рамках данного контента. Это легко реализуется через методы класса. Например, класс Login, описанный выше нуждается в следующих методах для начала работы с ним: SetUsername, SetPassword и Submit. Они показаны ниже:

'——————————————————————————-
Public Function SetUsername()
'——————————————————————————-
'Function: SetUsername
'Set the Username field
'
'Dependencies:
' N/A
'
'Remarks:
' N/A
'
'Arguments:
' N/A
'
'Returns:
' N/A
'
'Owner:
' John Doe
'
'Date:
' dd-MMM-yyyy
'
'——————————————————————————-

ChildObjects("Username").Set GlobalDictionary("Username")
'——————————————————————————-
End Function
'——————————————————————————-

'——————————————————————————-
Public Function SetPassword()
'——————————————————————————-
'Function: SetPassword
'Set the Password field
'
'Dependencies:
' N/A
'
'Remarks:
' N/A
'
'Arguments:
' N/A
'
'Returns:
' N/A
'
'Owner:
' John Doe
'
'Date:
' dd-MMM-yyyy
'
'——————————————————————————-

ChildObjects("Password").Set GlobalDictionary("Password")
'——————————————————————————-
End Function
'——————————————————————————-

'——————————————————————————-
Public Function Submit()
'——————————————————————————-
'Function: Submit
'Presses the Submit button
'
'Dependencies:
' N/A
'
'Remarks:
' N/A
'
'Arguments:
' N/A
'
'Returns:
' N/A
'
'Owner:
' John Doe
'
'Date:
' dd-MMM-yyyy
'
'——————————————————————————-

ChildObjects("Submit").Click

'TODO: Verify data submission performed successfully
'——————————————————————————-

End Function
'——————————————————————————-

Отметим использование GlobalDictionary для получения требуемых значений для функций (username, password) и использование свойства ChildObjects для получения через тестовый объект ссылки на выполняемый объект.

Следующим шагом будет перемещение на Бизнес Слой (Business Layer), который реализует бизнес сценарий, построенный на базе GUI Слоя (GUI Layer). Например, для того чтобы выполнить логин в систему на основе вышеописанного примера мы реализуем следующую функцию:

'——————————————————————————-
Public Function do_login()
'——————————————————————————-
'Function: do_login
'Implements the business logic of the do_login Action.
'
'Remarks:
'
'Arguments:
' None
'
'Returns:
' Status
'
'Owner:
' John Doe
'
'Date:
' dd-MMM-yyyy
'
'——————————————————————————-

Dim intStatus, objLogin

Set objLogin = CreateLogin()
If objLogin.Init() Then
objLogin.SetUsername()
objLogin.SetPassword()
objLogin.Submit()

'If login succeeds
intStatus = micPass
Else
intStatus = micFail
End If

do_login = intStatus
'——————————————————————————-
End Function
'——————————————————————————-

Отметим использование класса Login описанного выше и его функции Init как меру предосторожности для уверенности, что необходимый контент загружен и не завис, как обсуждалось ранее. Как вы можете видеть, код вышеописанной функции достаточно просто для понимания, и не перегружен ссылками на OR объекты, источники данных как при обычной реализации. Если изменения на GUI затронут объекты в данном контенте – все изменения будут сконцентрированы только в данном пакете, как те что касаются собственно свойств объектов так и механизмов работы с дочерними объектами. Еще одно преимущество данной методики – это стандартизация. Разрабатывая код по данной схеме, мы достигаем высокой степени унификации кода написанного разными разработчиками и таким образом улучшаем управляемость тестового проекта.

Более продвинутая альтернатива последнему примеру – это упаковка таких бизнес-функций, используя Command Wrapper шаблон проектирования, как это описано в моей статье Function Pointers in VB Script (revised). Например:

'VB Script Document
Option Explicit

'——————————————————————————-
Class do_login
'——————————————————————————-
'Class: do_login
'Encapsulates the do_login Action.
'
'Remarks:
'
'Owner:
' John Doe
'
'Date:
' dd-MMM-yyyy
'
'——————————————————————————-
'——————————————————————————-
'Methods
'——————————————————————————-
'——————————————————————————-

Public Default Function Run()
'——————————————————————————-
'Function: Run
'Implements the business logic of the do_login Action.
'
'Remarks:
'
'Arguments:
' None
'
'Returns:
' Status
'
'Owner:
' John Doe
'
'Date:
' dd-MMM-yyyy
'
'——————————————————————————-

Dim intStatus

Set objLogin = CreateLogin()
If objLogin.Init() Then
objLogin.SetUsername()
objLogin.SetPassword()
objLogin.Submit()

'If login succeeds
intStatus = micPass
Else
intStatus = micFail
End If

Run = intStatus
'——————————————————————————-
End Function
'——————————————————————————-
'——————————————————————————-

End Class
'——————————————————————————-

Адаптация данной методики делает возможным реализацию продвинутых универсальных контроллеров (generic controller), которые загружают свои сценарии из внешних источников данных, таких как XML файл. Такие управляющие структуры были разработаны мной и моими партнерами в SOLMAR Knowledge Networks как часть нашего универсального фреймворка - Object Oriented comprehensive automation framework - My System.


Выводы


В данной статье рассматривался альтернативный подход реализации тестов при автоматизации, основанный на объектно-ориентированной методологии. Я показал, что автоматизацию не следует рассматривать иначе, чем разработку программ. Более того, я постарался отразить, что логически следуя данной мысли, мы приходим к заключению, что проект автоматизации должен рассматриваться как программный проект в идеале, и предложил расширение концепции Объектного Репозитория (OR) (которая показала несоответствие OR методологии ООП) для инкапсуляции интерфейсов GUI объектов: GUI Слой.
В статье также приводился практический пример реализации такого слоя и его вызов, используя Бизнес-Слой, и разъяснены в деталях преимущества такого подхода для достижения максимального эффекта от вложенных инвестиций (ROI) в проекте автоматизации относительно поддерживаемости, читаемости, масштабируемости, расширяемости и тестируемости. Следующие статьи расширят данную тему и покажут читателям, как получить выигрыш от реализации в фреймворке других шаблонов проектирования, помимо изложенных в рамках этой статьи.


Read more...

понедельник, 13 апреля 2009 г.

Нас публикуют за рубежом!



В рамках реализации проекта по перемещению мировой столицы тестирования в Минск (О.Бендер и Нью-Васюки нервно курят) состоялась публикация нашей статьи на специализированном сайте по автотестированию AdvancedQTP.com

А если серьезно, то ...


Я очень благодарен этому профессиональному сайту. Начиная с первой страницы (один слоган чего стоит: 'coz we're programmers - not users) становится понятно, что аудитория здесь собралась крайне серьезная. Мне очень повезло, что начиная свой путь с QTP я столкнулся именно с этим ресурсом. Многие сложные оказались предельно простыми после ознакомления с материалами, размещенными на сайте.
Кроме того, в силу ограничений коммерческого характера (и мне это абсолютно понятно), некоторые статьи не раскрывают все технические тонкости реализации какой-либо интересной функциональности, но дают представление об идее, которую приходится доводить до ума самостоятельно (что потрясающе интересно).

Думаю, что заслуженных диферамбов получилось достаточно :)

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

Честно говоря, были некоторые сомнения насколько окажется интересным материал, попадает ли он в тематику сайта, уровень владения языком опять-же. Но, спасибо активисту и основному редактору ресурса - Yaron Assa за его позитивный настрой и активность, статья была принята с хорошей оценкой с его стороны.

Поэтому, приглашаю вас во-первых, посетить этот действительно профессиональный ресурс, а во-вторых, порадоваться вместе с нами: AdvancedQTP-Universal class for data manipulations

С уважением,
Сергей Талалаев

С большой признательностью к моей коллеге Анне Валерьевне.

Read more...

четверг, 2 апреля 2009 г.

QTP: Сравнивая с …
Универсальный класс для работы с данными


Влияние мирового кризиса к сожалению сказалось и на моей персоне и мне потребовалось срочно и по возможности глубоко изучить новый для себя фреймворк - Quick Test Professional. И душа рвется поведать о результатах, которые надеюсь буду полезны не только мне одному.

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


1. Введение

У меня уже был опыт работы с продуктами HP Mercury, но он относился к предыдущей линейке, я имею в виду WinRunner. Естественно я ожидал некоторого сходства в процессах скриптостроения и организации самого фреймворка. Поэтому по свежим следам постараюсь изложить замеченные мною интересные моменты и привести свои примеры реализации некоторых функций.


2. Работа с Excel-данными

Еще работая с WinRunner, я убедился, что встроенная реализация Excel хранилища не настолько гибка, как мне бы хотелось. Поэтому, как всегда, я приготовился к миграции своих процедур для работы с Excel. И был немного удивлен отсутствию встроенных средств работы с БД. Но эта задача вполне по силам, когда за плечами вся мощь VB :)


2.1. Основные задачи

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

Эти трудносовместимые вещи отлично реализуются посредством встроенной в Excel валидации входных данных и также прекрасно уничтожаются попыткой редактирования Excel таблицы напрямую из QTP.
Более того уничтожается также любое кастомное форматирование, без которого нормально читаемая таблица превращается в клетчатый текст.

Было до вмешательства из QTP:



Стало после редактирования из QTP:



Чтобы избежать подобных казусов я давно применяю прямую вычитку из Excel файлов в массивы, используя для этого стандартные ODBC источники. Данная техника успешно прижилась уже на следующих тестовых фреймворках: Rational Robot, IBM Rational Functional Tester, WinRunner и надеюсь QTP

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


2.2. Предварительные шаги

В Excel документах имеется функциональность которая позволяет выделять значимые для пользователя подмножества ячееек в специальные структуры. Такие структуры называемые “именованными диапазонами” обеспечивают возможность обращаться к ним к ним через логические имена.
Кроме того (что гораздо более значимо для нас) такие диапазоны становятся видны как стандартные ODBC таблицы из внешних приложений.

Итак, для оформления требуемой совокупности ячеек в качестве “именованного диапазона” необходимо выполнить следющую последовательность действий:
- выделить все ячейки, планируемые для оформления в именованный диапазон
- создать именованный диапазон через “Define name” диалог (Formulas > Define Name)



или напрямую введя имя диапазона в Navigation Bar.



Для проверки корректности вновь созданного именованного диапазона – выделите все ячейки диапазона и проверьте значение в Navigation Bar. Он должен содержать логическое имя вместо A1 нотации.

Важно отметить одно требование обязательно при использовании именованных диапазонов в качестве источника данных:
- первая строка нашего диапазона должна содержать имена столбцов, а не данные


2.3. Со стороны функциональной библиотеки

После всех подготовительных шагов осталось совсем немного поработать руками, а точнее пописать код.
Раз уж QTP 9.5 предоставил нам замечательную возможность работать c “почти” объектами – грех было бы ей не воспользоваться. Поэтому весь наш функционал мы гордо завернем в класс с благозвучным названием TestData.

Стоит напомнить, что QTP не видит напрямую классы, объявленные во внешних библиотеках, поэтому для каждого класса должна присутствовать функция создания экземпляра класса, в данном случае – CreateTestData

Кроме того мы должны иметь возможность инициировать наш класс не только через загрузку из Excel источника но и напрямую из кода. Именно для этих целей появились два метода: SetData и GetData


Public Function CreateTestData ()
Set CreateTestData = new TestData
End Function

Class TestData
Private mTestTable()

Private Sub Class_Initialize()
End Sub

Private Sub Class_Terminate()
Erase mTestTable
End Sub


' @Documentation Initiates TestData object with external data
'-----------------------------------------------------------

Public Sub SetData (DataArr())
Dim i,j

ReDim mTestTable(UBound(DataArr, 1), UBound(DataArr, 2))
For i=0 to UBound(DataArr, 1)
For j=0 to UBound(DataArr, 2)
mTestTable(i,j) = DataArr(i,j)
Next
Next
End Sub


' @Documentation Extracts data from TestData object
'---------------------------------------------------

Public Sub GetData(DataArr())
Dim i,j

ReDim DataArr(UBound(mTestTable, 1), UBound(mTestTable, 2))
For i=0 to UBound(mTestTable, 1)
For j=0 to UBound(mTestTable, 2)
DataArr(i,j) = mTestTable(i,j)
Next
Next
End Sub


Итак, мы вплотную подобрались к центральной части нашего функционала – вычитке данных из Excel источника.
За данную часть функционала отвечают два взаимосвязанных метода: GetArrayFromStore и LoadFromStore
Первый позволяет нам выгрузить вычитанные данные во внешний массив, минуя наш класс, а второй наоборот – инициирует наш класс вычитанными данными.


' @Documentation Extracts test data from the Excel store
'------------------------------------------------------

Public Sub GetArrayFromStore(Arr(), TableName, StoreName)
Dim Connection
Dim i, j, fieldcount, rowsfetched
Dim ArrTemp()

Set Connection = CreateObject("ADODB.Connection")
Connection.ConnectionString = "DBQ=" + StoreName + _
";Driver={Microsoft Excel Driver (*.xls)}" + _
";DriverId=790;FIL=excel 8.0;MaxBufferSize=2048" + _
";MaxScanRows=8;PageTimeout=5;ReadOnly=1" + _
";SafeTransactions=0;Threads=3;UserCommitSync=Yes"
Connection.Open

Set ConnRs = CreateObject("ADODB.Recordset")
ConnRs.CursorType = 3
Call ConnRs.Open("select * from " + TableName, Connection)

fieldcount = ConnRs.Fields.Count
Redim ArrTemp(fieldcount - 1, 0)

'column names adding
for j=0 to fieldcount - 1
ArrTemp(j,0) = ConnRs.Fields(j).Name
next

rowsfetched = 0
ConnRs.MoveFirst()
While not ConnRs.Eof
rowsfetched = rowsfetched + 1
Redim Preserve ArrTemp(fieldcount - 1, rowsfetched)
for j=0 to fieldcount - 1
ArrTemp(j, rowsfetched + i) = ConnRs(j).value
next
ConnRs.MoveNext()
Wend
Connection.Close

'matrix transposition
Redim Arr(UBound(ArrTemp,2), UBound(ArrTemp,1))
for i=LBound(ArrTemp,1) to UBound(ArrTemp,1)
for j=LBound(ArrTemp,2) to UBound(ArrTemp,2)
Arr(j,i) = ArrTemp(i,j)
next
next

End Sub


' @Documentation Loads test data from Excel store to the TestData object
'-----------------------------------------------------------------------

Public Sub LoadFromStore (TableName, StoreName)
call GetArrayFromStore(mTestTable, TableName, StoreName)
End Sub


Как вы можете заметить, ничего сверхъестественного в реализации данного функционала нет. Более того очевидно, что с небольшими модификациями такую же процедуру можно применять для вычитки данных из любого ODBC источника.
Нам осталось добавить несколько сервисных методов, чтобы наш класс стал действительно удобным в использовании: GetCellByIndex, GetCellByName, ColumnCount, RowCount


' @Documentation Gets cell value by row-column indexes
'------------------------------------------------------

Public Function GetCellByIndex (RowIndex, ColumnIndex)
GetCellByIndex = mTestTable(RowIndex+1, ColumnIndex)
End Function


' @Documentation Gets cell value by column name and row index
'-------------------------------------------------------------

Public Function GetCellByName (ColumnName, RowIndex)
Dim j

for j = 0 to UBound(mTestTable,2)
If (ColumnName = mTestTable(0,j)) Then
Exit For
End if
next

GetCellByName = mTestTable(RowIndex+1, j)
End Function


' @Documentation Returns number of columns into the test data table
'------------------------------------------------------------------

Public Function ColumnCount()
ColumnCount = UBound(mTestTable, 2)
End Function


' @Documentation Returns number of rows into the test data table
'---------------------------------------------------------------

Public Function RowCount()
RowCount = UBound(mTestTable, 1) - 1
End Function


2.4. Со стороны тестового скрипта

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


Dim TestArr() ‘Dynamic array
Dim TestD

Set TestD = CreateTestData()

Сall TestD.LoadFromStore("NamedRange", "C:\ExcelStore.xls")
Сall TestD.GetArrayFromStore(TestArr, "NamedRange", "C:\ExcelStore.xls")
‘Call TestD.GetArrayFromURL(TestArr, "OrgChart@"+ "C:\ExcelStore.xls")

Call TestD.SetData(TestArr)
Erase TestArr
Call TestD.GetData(TestArr)

Print TestArr(1,1)
Print TestD.GetCellByIndex(2,2)
Print TestD.GetCellByName("Name", 2)
Print TestD.RowCount
Print TestD.ColumnCount


Обращаю ваше внимание, что массив (если вы решите выгружать данные из TestData объекта) должен быть динамическим, а не статическим.

Для более глубокого понимания функционала предлагаю пройтись по нему в режиме отладки и внимательно проконтролировать весь процесс.

Вы также наверняка заметили одну закомментированную функцию, я имею в виду GetArrayFromURL.
Я использую данную функцию для удобной реализации вложенных данных. В этом случае на уровне Excel каждая строка должна содержать дополнительную колонку, в которой хранится URL связанного массива данных.



Предлагаю вам реализовать данную функциональность самостоятельно.


3. Выводы

Возможно, кого-то, во время прочтения статьи, не покидало ощущение бесполезности реализации дополнительной функциональности имея стандартные средства работы с Eхcel. Частично я уже объяснял причины необходимости этого выше (Основные задачи). Но кроме этого хотелось бы еще добавить в копилку знаний несколько замечаний.

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

С уважением,
Сергей Талалаев

С большой признательностью к моей коллеге Анне Валерьевне.

Read more...

среда, 10 декабря 2008 г.

SQA Days 2008 - полная версия флипа "Использование MS Excel в качестве унифицированного хранилища данных для автоматизированных тестов"

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

Аннотация

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

1.1 Предыстория
1.1.1 Автоматизация: от эйфории до созерцания

Есть несколько типичных ошибок, которые допускются при первых попытках внедрения автоматизации функционального тестирования. Эти ошибки допускаются естественно из-за отсутствия опыта в такого вида разработках и кроме того в некоторой степени ”поощряются” кажущейся легкостью работы в современных тестовых фреймворках при использовании механизмов макрозаписи (трансляции действий пользователя напрямую в тестовый скрипт). К сожалению подход при котором вся тестовая команда записывает килотонны кода, что вызывает невиданный прилив энтузиазма как у самих членов команды так и у руководства, приводит в конце концов к плачевным результатам.
Рано или поздно наступает тяжелый момент, когда нужно остановиться, отдышаться и трезвым взглядом посмотреть на дело рук своих, чтобы трезво оценить во что же выльется переделка.
В нашем случае ситуация оказалась настолько запущенной, что было принято решении отказаться от существующих скриптов такого вида и написании их с нуля в строгом соотвествии с оговоренными правилами которые впоследствии оформились в документ под названием “Test scriprting guideline”.

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

1.1.2 Проблема больших чисел

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

Количество скриптов : Время затрачиваемое на их поддержку

Если отобразить эту зависимость в виде графика где по оси Х будет отображаться количество скриптов а по оси Y – время необходимое для поддрежки этого количства скриптов, то мы получим три варианта развития событий.
Первый вариант – график выше линейного, говорит о том, что при разработке скриптов не использовались методики оптимизации, наверняка есть повторимость кода и структура скриптов не унифицирована.
Второй вариант – линейный, очевидно гораздо лучше первого рассмотренного варианта, но тем не менее он предлагает обычный экстенсивный путь развития при котором чем большее количество скриптов мы хотим реализовать тем большая команда автоматизации нам потребуется.
Третий вариант – очевидно,что именно к нему и нужно стремится, предполагает, что при увеличении скриптов время требуемое на их поддрежку растет незначительно.



Для того чтобы поддержка скриптов не легла непосильным бременем на тестовую команду при разработке тестов нужно обязательно уделять внимание таким моментам как:
• Унификация структуры сриптов (с последующим документированием этой структуры)
• Вынос общих бизнес-функций в библиотеки/классы
• Использование внешних источников данных

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

1.1.3 Идентификация проблемы.

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



Основным требованием предъявляемым со стороны тестовой команды (а здесь мы имеем ввиду именно функциональных тестировщиков) является простота создания и поддержки тестовых данных и отсутствие необходимости изучения каких-либо узкоспециализированных инструментов и сложных техник.


Со стороны команды автоматизации основное требование – это простота интеграции в существующие скрипты. По крайней мере процесс интеграци долджне быть не сложнее чем при применении стандартных встроенных хранилищ.



Не всегда но тем не менее со стороны заказчика тоже просыпается интерес к тестовым данным, которые используются при проведении автоматических тестов. И основное требование с этой стороны – это доступное визуальное оформление этих тестовых данных.

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

1.2 Стандартные решения – достоинства и недостатки
1.2.1 Реализация внутренних хранилищ в семействах продуктов IBM Rational
В качестве встроенного хранилища данных в семействе продуктов Rational используются так называемые Датапулы (Datapools). Они представляют собой некий урезанный вариант таблиц базы данных.

Из положительных сторон можно отметить:
- встроенный механизм генераци данных
- родная поддержка на уровне скрипта
- возможность использования как для функционального так и для нагрузочного тестирования

Из минусов:
- неудобство редактирования данных
- отсутствие возможности группировки данных


1.2.2 Реализация внутренних хранилищ в семействах продуктов HP Mercury
В качестве встроенного хранилища данных в семействе продуктов HP Mercury используются стандартные Excel файлы.

Из положительных сторон можно отметить:
- удобство редактирования
- родная поддержка на уровне скрипта

Из минусов:
- при редактировании через встороенный редактор из файла удалятся всё форматирование
- отсутствие возможности группировки данных


1.2.3 Другие варианты хранения данных
• CVS файлы
Неудобство работы напрямую в файле. При использовании того же Excel в качестве редактора получаем 2-х проходную работу. Проблемы с группировкой и отсутсвием валидации на входе.
• XML файлы
Персонал должен как минимум понимать структуру XML, владеть одним из редакторов для манипуляции с файлами такого вида. Сложно задается валидация входных значений.



1.3 Поиск компромисса
1.3.1 Почему Excel?

При выборе варианта хранилища данных мы в качестве основного критерия выбрали удобство подготовки и редактирования данных. Акцент при выборе был сознательно смещен в эту сторону так как продукт был действительно большим и сложным и без помощи функциональной тестовой команды автоматизаторам было бы нереально подготовить такой объем данных.
Со стороны команды автоматизации было сделано допущение (впоследствии оно оказалось верным), что на уровне скрипта мы сможем создать механизмы по крайней мере не уступающие стандартным в удобстве использования. С этой позиции Excel был лучшим кандидатом, но в ходе реализации выяснялись некоторые особенности изучив которые мы смогли получить эффективную отдачу от выбранного инструмента. О них поговорим в следующей части доклада.

1.3.2 Хитрости и трюки

Для того чтобы получить видимые для ODBC таблицы в Excel- файле вы должны определенным образом разметить интересующие вас подмножества ячеек. Для этой цели служит функциональность называемая Names (именованные диапазоны). Создать именованный диапазон можно через “Define name” диалог (Insert > Name > Define) или через Formulas > Define Name в 2007-ом офисе.



После такого выделения ваши имена становятся доступны как таблицы для ODBC драйвера. Для проверки того что диапазон задан верно необходимо выделить помеченые ячейки и в Navigation bar должно отбразиться заданное имя.




1.3.3 «Ложка дегтя»: ограничения использования

Конечно все это было бы слишком хорошо если бы не было каких-либо ограничивающих факторов и они к сожалению есть:
- мы не сможем использовать наши тестовые данные для нагрузочных тестов как например в случае использования “родных” хранилищ Rational;
- у нас не будет возможности запускать наши тесты в многоплатформенной среде даже если сама тестовая платформа это позволяет.

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


1.4 Из личного опыта: «Датадривен – это просто»
1.4.1 Задача: разработать автоматические тесты с возможностью кастомизации без изменения кода.

Кастомизация предполагалась следующая:
- скрипты должны были выполнятся как в рамках Smoke тестов так и в рамках основного цикла тестирования
- существовала необходимость использовать скрипты в том числе для загрузки некоторых специфичных начальных тестовых данных с UI (общесистемные данные грузились напрямую в БД на этапе сборки билда)

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

1.4.2 Вариант решения

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

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

1.4.3 Анализ полученного результата

В результате мы получили достаточно гибкую структуру решающую все поставленные задачи. Кроме того строгая унификация подходов к разработке избавляла нас от серьезных временных затрат при вхождении нового человека в команду автоматизации и при отладке скриптов после изменения UI.

Из минусов можно отметить следующий момент. Так как фреймворк реализовывался на обычном процедуральном языке (расширение VB) то все сервисные механизмы по работе с property файлами должны были присутствовать на уровне скриптов. И хотя реального кода там было не более 10 строк тем не менее это захламляло скрипт.
Дальнейшая реализация такого же подхода в рамках OO-языка (Functional Tester + Java) показала насколько эффективно сервисный код может быть скрыт на верхнем уровне иерархии.

1.5 Непознанный мир Excel
1.5.1 Возможность использования Excel в качестве источника XML-данных

Начиная с 2003-ей версии офиса в Excel появилась возможность интеграции с XML, причем как в сторону загрузки данных в Excel таблицы так и в сторону экспорта табличных данных в XML файл. Эта функциональность (называемая в офисе 2003 Lists а в 2007 – Tables) добавила еще больше гибкости в процедуру подготовки тестовых данных. Теперь появилась возможность оперировать с текстовыми данными практически любого вида. Единственно, что требуется дополнительно реализовать - это XSLT преобразование из полученного в процесе экспорта XML файла к требуемому для приложения виду.



1.5.2 Варианты применения

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

1.6 Из личного опыта: «Пойди туда, не знаю куда – найди то, не знаю что»
1.6.1 Задача: протестировать процедуру миграции БД

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

1.6.2 Вариант решения

Вот тут как нельзя кстати пригодилась новая функциональность Excel позволяющая выгружать данные в XML.
Мы сначала подготовили данные для понятных нам тестовых случаев и согласно предполагаемой структуре сделали прослойку для генерации скриптов (то есть приготовили набор XSL файлов необходимый для конвертации выгружаемых XML в требуемый нам формат).
Имея на руках уже готовые тестовые данные разговаривать с заказчиком стало гораздо проще. Стало очевидным что с нашей стороны были сделаны все шаги и без их активного участия дальше двигаться невозможно. Поэтому началось активное общение с разбором возникающих проблем и постепенное доведение наших скриптов до рабочего состояния.

1.6.3 Анализ полученного результата

Из несомненных плюсов примененного подхода хочется отметить, что мы смогли начать работу даже не имея на руках полностью разжеванной спецификации по БД, что при любых других вариантах решения привело к большим затратам по модификации готовых сриптов. Нам этого удалось избежать, сохранив по максиму уже подготовленные данные.
Из минусов или скажем так из особенностей нужно отметить что на стороне тестовой команды должен был присутствовать человек имеющий опыт работы с XML+XSLT. Но это, я считаю, является очень хорошим стимулом к изучению на практике новых областей не совсем типичных для просто функционального тестирования.

1.7 Из личного опыта: «Хотели бы помочь, но по-своему»
1.7.1 Задача: получить тестовые данные для проведения UAT от заказчика

В ходе работ по ”оживлению” старого демо-приложения выяснилось, что мы не можем убедиться в корректности работы функциональности отчетов в восстановленном функционале из-за полного отсутствия документации на эту часть приложения. Заказчик воспринял ситуацию адекватно и предложил свою помощь в разрешении проблемы, а именно предложил нам взять на себя подготовкку тестовых данных для этой части функционала. Наша радость к сожалению была очень недолгой, когда мы увидели в каком виде к нам начали приходить эти данные. Ни о какой организованной струтуре речи ни шло. Данные для полей с ограниченным набором списковых значений например могли отличаться от набора к набору ( как пример в одном наборе период назывался “semi-annual”, а в другом – “Semi annual”). Мы пришли к выводу, что на вычистку таких данных уйдет больше времени, если они не будут жестко следовать предопределенному формату.

1.7.2 Вариант решения

Решено было на основании уже полученных первых данных от заказчика и дальнейших консультаций подготовить шаблон для ввода данных с жесткими ограничениями на вводимые данные. В качестве оболочки для создания такого шаблона был выбран Excel с его функциональностью по валидации вводимых данных. Использовались такие типы валидаии как
- ограничение вводимых значений только значениями из списка
- задание диапазонов допустимых значений
В дальнейшем предполагалось использовать механизм выгрузки подготовленных данных в XML формат и конвертацию полученных XML файлов в последовательность SQL-операторов для загрузки данных напрямую в БД.

1.7.3 Анализ полученного результата

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


С уважением,
Сергей Талалаев


Read more...