Pull to refresh

Тестирование Web UI с Викой в удовольствие или Виртуальный Интеллект в тестировании

Reading time12 min
Views13K
Добрый день, дорогие Хабра-читатели. В этот раз в рубрике IT я хотел с вами немного помечтать о будущем. Об эпохе, когда искусственный интеллект не будет диковинкой, и роботы станут нашими близкими друзьями…

Но зачем мечтать, — подумал я. Лучше я расскажу вам об одном таком создании.

Встречайте VIQA WTL – Virtual Intelligence Quality Assurance Web Testing Tool, или по-простому Вика.

Вика — инструмент с Виртуальным Интеллектом для тестирования Web UI (сайтов, по-просту говоря) на языке, понятном пользователю. Инструмент представляет из себя обертку вокруг Selenium и позволяет описывать тестовые сценарии, используя такие понятия как: кнопки, текстовые поля, чеклисты и выпадающие списки, сайт, страницы и блоки. Т.е. использует популярный паттерн PageObjects.

В дополнение к реализации этой концепции, инструмент обладает широким спектром сопутствующих возможностей и большой приспосабливаемостью к конкретному окружению (о чем речь пойдет ниже).

Инструмент, используемый мною в работе в i-Free, был представлен на конференции SQA Days 15 (текст презентации и видео будут выложены в ближайшее время организаторами). В презентации Вика описывалась формате сравнения с наиболее популярным инструментом в этой области Yandex QA Tool. В данной статье я постараюсь более подробно рассказать о самом инструменте без выделения его сильных и слабых сторон (желающим разобраться в этом предлагается сделать это самостоятельно в комментариях и/или послушать видео с конференции).

Virtual Intelligence


Начну с названия. Я думаю, вам интересно узнать, причем здесь Виртуальный Интеллект, и что под этим я подразумеваю?
image

Название взято из очень популярной компьютерной игры Mass Effect. История примерно такова:
Некая галактическая раса Кварианцев создала Искусственный Интеллект, поняв опасность содеянного, вступила в борьбу со своими созданиями, проиграла ее и была изгнана со всех планет своего Мира расой платформ, наделенных ИИ.
После этих событий в галактике были запрещены разработки ИИ из-за опасности их выхода из-под контроля. В противовес ИИ в галактике широко используются ВИ. Виртуальные интеллекты, использующие человекоподобные интерфейсы, но не обладающими способностью к самообучению (а следовательно, безопасные в использовании).

Итак, в моем понимании ВИ:
  1. Человеческий язык. Умная программа, взаимодействующая с человеком на его языке.
  2. Простота использования. Программа достаточно «умная» для того, чтобы иметь решения для разных уровней пользователей (низкий порог вхождения, наличие реализаций для всех своих функций «по умолчанию»)
  3. Настраиваемость. Программа, обладающая способностями к обучению (кастомизации) под конкретное окружение (в отличие от ИИ, обучение производится человеком, а не обучающим модулем ИИ)


PageObjects


Концепция PageObjects, в общем, говорит о том, что при тестировании Web UI хорошо бы смотреть на Web страницы и элементы на них как на объекты и, соответственно, иметь сущности для этого в коде.

Попросту говоря, вместо того, чтобы искать теги на странице по локаторам и селекторам, нужно выделить логический функционал в класс (к примеру, «кнопка») и работать с объектом этого класса. А не с тегами и локаторами.

Также вышесказанное подразумевает разделение кода тестовых сценариев и кода, описывающего объекты на страницах вашего сайта и работу с ними.

При этом Page Objects — это лишь концепция, и она почти не предлагает инструментов для реализации подхода, кроме PageFactory
P.S. Подробнее о PageObjects можно почитать здесь code.google.com/p/selenium/wiki/PageObjects или поискать информацию в интернете.

Другие реализации PageObjects


Выступая на конференции SQA Days 15, я постарался рассказать о другом инструменте, реализующем шаблон PageObjects – HtmlElements, являющимся, на мой взгляд, лидером в этой сфере. И постарался подробно описать то, чего мне не хватило и почему я решил создать свой фреймворк для схожей задачи. В этой статье я не буду делать сравнений, а просто расскажу о том, что же умеет Вика.

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


В основе всех элементов у Вики лежит VIElement. В отличие от супер WebElement-а WebDriver-а, который является объединением всех «элементов» и умеет делать все, даже то, чего не умеет (например, сделать SendKeys в кнопку), VIElement является общей частью всех элементов (пересечение — общие свойства всех элементов) и умеет делать то, что свойственно всем элементам. И не умеет делать ничего лишнего (все методы VIElement всегда применимы и дадут результат).

Как я уже говорил, Вика реализует паттерн PageObjects и даже несколько расширяет его.

У Вики есть отдельные классы для таких понятий как: Сайт (VISite), Страница (VIPage) и для каждого элемента вроде кнопки (Button), чекбокса (Checkbox), текстового поля (TextField) и т.д.

Любой элемент у Вики может являться как отдельным логическим элементом, так и объединением любых наборов элементов. К примеру, Checkbox состоит из 3-х элементов. VIPage может включать в себя любое количество элементов. В связи с таким подходом у Вики нет Blocks (как у Яндекса), Блоки элементов являются обычными VI Элементами, которые состоят из других элементов (см. Пример 1).

Структура

Согласно шаблону PageObjects, структура вашего сайта описывается отдельно от тестов.

Структура описания тестового сайта следующая:
  • VISite
    • Page1
      • Section1
        • Element1
        • [Element2]
        • [Section]
      • [Section2]
        • [Element]
    • [Page2]
    • [Page3]


Подробнее См. Пример 2.

VISite


Корневым элементом является VISite. VISite включает в себя всю общую информацию о тестируемом сайте:
Настройки WebDriver, Настройки таймаутов и логирования, адрес доменного урла, список страниц.
VISite имеет два дефолтных действия: Open для открытия произвольного урла и OpenHomePage по доменному урлу.

VIPage


VIPage – описывает тестируемую страницу. Состоит из элементов и групп элементов. Может иметь ожидаемый Url и Title. Настройки: проверять или нет ожидаемый тайтл/урл (по умолчанию, если Url – указан, он проверяется, иначе нет. Аналогично Title)
Элементы

Простые

ClickableElement, TextElement, ClickableText, Button, Checkbox, Link, TextArea, TextField


Списки элементов

CheckList, DropDown, RadioButtons


Составные элементы

imageВы можете группировать элементы как вам удобно. Например, можно объединить в группу элементы, входящие в футер или хедер страницы. Или в форму для логина. Описать их и использовать на разных страницах. Все составные элементы имеют «контекст» — локатор html элемента, в котором они находятся. Локаторы элементов в группе ищутся «внутри данного элемента». Используется ByChained.

Массовое заполнение в одну строчку


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

Логичным является желание объединить такие элементы в блок (к примеру «паспортные данные»), и в тесте сказать «заполни паспортные данные». Учитывая, что такие данные обычно являются входными данными теста и в дальнейшем скорее всего будут использованы для проверки результатов, логично использовать для работы с ними некий объект MyPassportData.

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

Описывая страницу, вы в любом случае опишите все эти поля, и PageObjects намекает нам объединить их в блок или страницу – VIElement в терминах VIQA (допустим, PassportSection). Каждый VIElement, как говорилось ранее, может быть объединением элементов, из которых он состоит. Для заполнения всех этих полей вам всего лишь нужно обучить поля (см. пример 3), выполнить метод FillFrom у PassportSection и передать ему в качестве параметра MyPassportData.

PassportSection. FillFrom(MyPassportData);


Интерфейсы

Все элементы у Вики построены на основе интерфейсов. Т.е. у вас, конечно, есть дефолтная реализация, но главное — это то, какой смысл человек вкладывает в объект. К примеру, когда мы говорим о кнопке, нас мало волнует, как выглядит эта кнопка и уж тем более еще меньше беспокоит html код этой кнопки.

Мы знаем, что кнопка – это то, на что можно нажать. Ну, и иногда у кнопок бывают названия.

На основании такого подхода у любых кнопок в VIQA есть действие Click и атрибут Label. У этих действий есть реализация по умолчанию (click делается на локатор кнопки, а лейбл – это значение атрибута value по этому локатору), но, если ваша кнопка это вовсе не , а, к примеру: Кнопка
То вы все равно можете использовать Button, просто «обучив» его по-другому совершать эти действия.

C точки зрения написания кода интерфейсы скрывают от программиста все лишнее что можно делать с этим классом и оставляют только действия пользователя.

Список Интерйфейсов:

IButton, ICheckbox, ICheckList, IClickable, ILabeled, ILink, ISelector, ISetValue, ITextArea, IVIElement

VIAction


Все действия с элементами осуществляются не напрямую, а при помощи делегатов и проходят через VIAction.
То, как будут выполняться действия для конкретного элемента или для всех элементов в целом, можно настроить самостоятельно:
Общий
По умолчанию делается следующее:
Для действий без получения результата (вроде Click)
  • Действие записывается в лог с указанием названия элемента, типа и локатора
  • Выполняется само действие

Для действий с результатом (Вроде GetLabel):
  • Действие записывается в лог с указанием названия элемента, типа и локатора
  • Выполняется само действие
  • Если есть правило получения текста из полученного действием объекта, то логируется результат
  • Результат отдается дальше в код

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

Для одного элемента

Аналогично вы можете настроить работу для конкретного элемента, переопределив его VIAction.
К примеру, если вам нужно указать Frame или проверить видим ли данный элемент на интерфейсе или нет. Пример 5

Каскадная инициализация


Все Элементы можно описывать, как с помощью удобных атрибутов, так и с помощью конструкторов (и даже используя оба способа одновременно) См. Пример 6.

Так как Вика реализует шаблон PageObjects, она умеет инициализировать все описываемые элементы из атрибутов каскадно.
Для этого нужно всего лишь создать VISite.

var mySite = new VISite(“http://mysite.com”)


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

Логирование


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

VISite.Logger = new MyLogger();


Настройка Таймаутов.

По умолчанию у сущности VISite есть 3 типа таймаутов:
  • WaitWebElementInSec – таймаут для ожидания элемента на открытой странице (5 секунд)
  • WaitPageToLoadInSec – таймаут для ожидания элемента на новой странице (20 секунд)
  • RetryActionInMsec – таймаут для (повторного поиска элемента) (0,5 секунды)


Вы можете указать при описании элемента, что клик на него вызовет открытие новой страницы. И тогда при следующем действии Вика будет использовать таймаут WaitPageToLoadInSec вместо WaitWebElementInSec (Пример 7).

SmartSearch и SmartClick


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

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

• Implicitly wait не нашел элемент или при нажатии на него произошла ошибка, но таймаут на ожидание еще не прошел? Поищи еще разок.
• Все равно не удалось? Может быть, предыдущее действие (например, Click не сработал? Попробуем кликнуть еще разок и найти элемент)
Функцию Стабильного Смарт-поиска можно отключить, если вы считаете, что с ее помощью можете пропустить баги с реальным не-нажатием на элемент. На мой взгляд, вероятность того, что это будет реальный баг, и кнопка наживается только со второго раза, крайне мала.
В данном случае Вика лишь предоставляет вам инструмент. Использовать его или нет — ваш выбор.

Дополнительно


KillAllRunWebDrivers

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

Для этого перед запуском тестов в (SetUpFixture) вам надо запустить метод:

VISite.KillAllRunWebDrivers();


И вы можете забыть про незакрытые окошечки. Вика заботится о вас.

Запуск драйвера

Если вы пишите тесты под WebDriver, то обычно у вас есть некий beforesuit класс, где вы инициализируете свой WebDriver один раз и дальше с ним работаете. Зачастую при написании тестов нужно внести какие-то небольшие изменения в тестовый сценарий до выполнения действия Open (к примеру, отладка различных действий в BeforeTest: чистка базы, чтение настроек базы или логера или сервисов и т.д. Или проверка корректности получаемых данных из DataSource для теста или еще что-нибудь, что не требует запуска браузера). Для таких задач, запуская свой тест, вы будете каждый раз ждать запуска драйвера, затем открытие страницы сайта и только потом код остановится в дебаге на вашем брейкпоинте. На это может уходить 2-5 секунд на каждый запуск. Для кого-то это может быть не заметно, но, если вас это пустое ожидание раздражает так же, как и меня, то знайте, в VIQA вам не придется тратить это время впустую.
В VIQA драйвер передается в виде делегата (не важно дефолтный он или настроенный вами). Запуск драйвера происходит только при вызове метода Open, т.е. только тогда, когда это уже точно необходимо. До этого момента Вика вас не заставит ждать. Вика заботится о вас.

Во весь экран

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

Планы:
  • Перевести фреймворк и на Java
  • Добавить новые элементы в библиотеку (к примеру, из HTML5)
  • Добавить новые функции фреймворку (собрать то, что не умеет делать Selenium и что делается используя JavaScript и добавить во фреймворк: работа с невидимыми объектами, setAttribute и прочие хаки )
  • Добавить возможности сбора статистики по умолчанию, вывода красивых графиков и интеграцию с популярными системами уже делающими это.


Мне хочется сделать Вику в первую очередь удобной для каждого пользователя, поэтому буду рад вашим комментариям, пожеланиям и критике.
Скачивайте, пробуйте, пишите )
Подписывайтесь на новости группы: vk.com/viqatools
Пишите свои вопросы на email проекта: viqablog@gmail.com

Наслаждайтесь тестированием вместе с Викой.

UPD: Видео с конференции SQA Days 15 vimeo.com/95245507



Приложение:


Пример 1

public class Checkbox 
{
    public TextElement TextElement;
    public VIElement CheckSignElement;
}

public class LoginForm
{
    public TextField LoginTxtField;
    public TextField PasswordTxtField;
    public Button LoginButton;
}


Пример 2
[Site(Domain = "http://market.yandex.ru/")]
    public class MySite : VISite
    {
        [Page(Title = "Мой Сайт", Url = "http://mysite.ru/")]
        public HomePage HomePage;

        [Page(Title = "Другая страница", Url = "http://mysite.ru/somepage")]
        public SomePage SomePage;
    }

    [Page(Title = "Мой Сайт", Url = "http://mysite.ru/")]
    public class HomePage : VIPage
    {
        [Name("Секция поиска")]
        [Locate(ByClassName = "search")]
        public static SearchSection SearchSection;
    }

Note: Атрибуты для Page можно указать в одном месте или перед переменной в классе сайта или над самим классом страницы.

public class SearchSection : VIElement
{
    [Name("Поле Поиска")]
    [Locate(ByXPath = "//*[@class='search_input']
    public TextArea SearchTextField;

    [Name("Кнопка 'Найти")]
    [Locate(ByXPath = "//*[contains(text(),'Найти')]
    [ClickReloadsPage]
    public Button SearchButton;

    public void SearchProduct(string productName)
    {
        SearchTextField.NewInput(productName);
        SearchButton.Click();
    }
}

Note: В секции описаны два элемента и одно действие.

Пример 3
public class PassportData
{
    public string Number; 
    public string Series; 
    public FullName FullName;
}
public class FullName
{
    public string Name; 
    public string SecondName;
}

[FillFromField("Number")]
public TextField PassportNumberTxtField;

Note: чтение поля Number из бизнес-сущности, которая будет передана в качестве данных.

[FillFromField("FullName.Name")]
public TextField PassportNameTxtField;

Note: чтение поля Name из объекта поля FullName

public ITextArea PassportSeriesTxtField = new TextField() { 
        FillRule = ToFillRule<PassportData>(pd => (pd.Number != “”) ? pd.Series : “”)),
}


Note: FillRule дает полную свободу

Пример 4
(viElement, actionName, viAction) =>{
        VISite.Logger.Event(viElement.DefaultLogMessage(text));
viAction.Invoke();
}


Note: VIAction по умолчанию для действий без получения результата
(actionName, viAction, logResult) =>{
    VISite.Logger.Event(DefaultLogMessage(text));
    var result = viAction.Invoke();
    if (logResult != null)
        VISite.Logger.Event(logResult.Invoke(result));
    return result;
} 

Note: VIAction по умолчанию для действий с получения результата
Пример 5
new RadioButtons(“Сенсорный экран”, “#sensorScreen”) {
    VIAction = (viElement, text, viAction) => {
        if (!FirstSensorRadioButton.IsDisplayed)
            SensorBlock.Click();
        viAction.Invoke();
    }
};


Note: Пример переопределения VIAction для конкретного элемента. Позволяет не беспокоится о том видим или нет чекбокс в момент действия.
Пример 6
[Name(Name = "Wi-fi"), Locate(ByXPath = "//*[@class=‘my-checkbox']")]
public ICheckbox MyCheckbox1;

[Name(Name = "Wi-fi"), Locate(ByClassName = “my-checkbox")]
public Checkbox MyCheckbox2;

public ICheckbox MyCheckbox3 = new Checkbox("Wi-fi", "#my-checkbox");

public Checkbox MyCheckbox4 = new Checkbox("Wi-fi", By.CssSelector("#my-checkbox"));


Пример 7
[Name("Кнопка 'Найти'")]
[ClickReloadsPage]
public IButton SearchButton;


Note: Аттрибут ClickReloadsPage при описании Элемента

MyButton.WithPageLoadAction.Click()

Note: Прямо в коде

MyButton.WaitTimeout(20).Click()

Note: Или задать таймаут ожидания вручную.
Tags:
Hubs:
+7
Comments4

Articles

Information

Website
www.i-free.com
Registered
Founded
Employees
501–1,000 employees
Location
Россия