Всем, доброго времени суток!
Этот топик о том как мы тестируем веб-интерфейс нашего продукта Plus1 WapStart. Мы используем Page Object, т.к. этот паттерн имеет много общего с реальными задачами и позволяет писать автотесты простыми для чтения и понимания.
Что такое Page Object
Page Object — это паттерн для реализации умных автоматических проверок. Gem page-object является имплементацией этого паттерна, который помогает в создании гибких страниц с объектами для тестирования браузерных приложений. Суть в том, чтобы создавать уровни абстракции для отделения тестов от предметов тестирования, и обеспечить простой интерфейс для элементов на странице. Gem работает с watir-webdriver и selenium-webdriver.
Установка Ruby и gems
Установим RVM:
$ bash -s stable < <(curl -s https://raw.github.com/wayneeseguin/rvm/master/binscripts/rvm-installer)
Для запуска примеров понадобиться последняя версия Ruby и gems:
$ rvm reload
$ rvm install ruby-1.9.3-p125
$ rvm gemset create page-object && rvm use ruby-1.9.3-p125@page-object
$ gem install rake page-object
Hello, Page Object!
Создаем RegistrationPage для страницы регистрации — для этого включаем модуль PageObject, указываем адрес страницы и описываем элементы:
class RegistrationPage
include PageObject
page_url "http://www.passport.wapstart.ru/registration/"
text_field(:email, :name => 'mail')
text_field(:password, :id => 'hidden-password')
select_list(:source, :name => 'informationSource')
checkbox(:agreement, :name => 'agreement')
button(:register, :name => "register")
end
На странице описаны шесть методов, каждый из которых дополнительно сгенерирует еще несколько, об этом далее… Добавляем данные по умолчанию:
DEFAULT_DATA = {
'email' => 'habrahabr@gmail.com',
'password' => 'qwerty',
'source' => 'Прочитал статью, новость о WapStart'
}
Создаем метод для заполнения только обязательных полей:
def default(data = {})
populate_page_with DEFAULT_DATA.merge(data)
check_agreement
register
end
Все базовые page objects определены, используем их в автотесте. Выберем драйвер selenium-webdriver, передав его в конструктор PageObject:
browser = Selenium::WebDriver.for :ff
registration_page = RegistrationPage.new(browser, true)
registration_page.default
Аргумент true открывает page_url, если мы попадаем на эту страницу кликом по ссылке, то его можно не передавать. Запустим пример:
$ ruby tests/RegisterDefault.rb
Таким образом в автотестах уходим от использования find_element и локаторов, код легко читаемый и повторно используемый.
Динамическая генерация методов доступа к элементам страницы
Accessors — методы класса, добавленные на страницу, подключением модуля PageObject. Методы генерируют еще один набор методов, которые обеспечивают доступ к элементам веб-страницы:
Пример полностью описанной страницы регистрации:
require 'page-object'
require 'selenium/webdriver'
class RegistrationPage
include PageObject
page_url "http://www.passport.wapstart.ru/registration/"
DEFAULT_DATA = {
'email' => 'habrahabr@gmail.com',
'password' => 'qwerty',
'source' => 'Прочитал статью, новость о WapStart'
}
text_field(:email, :name => 'mail')
text_field(:password, :id => 'hidden-password')
checkbox(:showPassword, :id => 'showPassword')
select_list(:source, :name => 'informationSource')
text_field(:fio, :name => 'fio')
text_field(:phone, :name => 'phone')
select_list(:purpose, :name => 'registrationPurpose')
checkbox(:haveCode, :id => 'havePartnerCode')
text_field(:code, :id => 'plus1PartnerCode')
checkbox(:agreement, :name => 'agreement')
button(:register, :name => "register")
# Exception
span(:errorCode, :xpath => "//form[@id='registrationForm']/table/tbody/tr[9]/td[2]/span/span[2]")
def default(data = {})
populate_page_with DEFAULT_DATA.merge(data)
check_agreement
register
end
end
Пример автотеста для проверки валидности партнерского кода:
describe "RegisterUser" do
let(:browser) { @browser ||= Selenium::WebDriver.for :ff } #Initialize new instance of Browser(driver)
it "InvalidCode" do
page = RegistrationPage.new(browser, true)
page.email = 'habrahabr@gmail.com'
page.password = 'qwerty'
page.source = 'Прочитал статью, новость о WapStart'
page.check_haveCode
page.code = 12345678
page.check_agreement
page.register
page.errorCode?.should be_true
end
after { browser.close }
end
Примеры доступны на GitHub:
$ git clone git@github.com:ivaravko/pageobject-example.git
$ cd pageobject-example/
pageobject-example$ rake
Открытие страницы из другой страницы
В большом проекте много страниц и они связаны между собой, для того чтобы выполнять переход добавим следующий шаг в default метод класса RegistrationPage — LoginPage.new(browser, true). Это позволит перейти на страницу ввода логина и пароля, не изменяя автотест.
def default(data = {})
populate_page_with DEFAULT_DATA.merge(data)
check_agreement
register
LoginPage.new(browser, true)
end
Автор топика ivaravko
Ссылки
Блог автора гемаСтраница на GitHub
Документация