Структура папок и имена классов
В данный момент, в проекте есть один библиотечный пакет:
org.swd.starterj.core
и один тестовый проект «Demo»
Я сразу же разделил его на пакет тестов: org.swd.starterj.demo
и пакет бизнес-логики, где, в том числе, будут хранится декларации PageObjects. Это org.swd.starterj.demo.testmodel
Для тестирование одного приложения, назовём его “Demo”, тестовых пакетов может быть много: org.swd.starterj.demo.smoke
, org.swd.starterj.demo.acceptance
, org.swd.starterj.demo.somefeaturename
, но все они используют ресурсы из Тестовой Модели org.swd.starterj.demo.testmodel
Имена классов
Кстати, и тестовых проектов, таких как «Demo» может быть несколько. И у каждого будет своя тестовая модель и свои пакеты тестов.
В пакете «Core» я храню все то универсальное, что имеет отношение только к вебдрайверу, но не имеет отношения к конкретным проектам: универсальные базовые классы, интерфейсы, методы-помощники.
В Тестовой Модели для конкретного проекта, я обязательно переопределяю базовый класс и называю его MyBasePage
Если что-то что начинается с префикса My...
, то это означает, что оно специфично для конкретного тестового проекта. В данном случае, MyBasePage
– это базовый класс для проекта “Demo”. Если вдруг я захочу добавить ещё один тестовый проект, назовём его “ATInfoTests”, то в нем также будет присутствовать своя тестовая модель, а в ней класс с именем MyBasePage
…
Я сам вижу что не совсем хорошо это расписал… но пока не могу придумать лучшего текста
Автоматический вызов PageFactory.initElements
Я начал работу с поддержкой пейджобжектов. Добавил новый пакет org.swd.starterj.core.pageobjects
с базовым классом CorePage и интерфейсом SelfTestingPage
Так же, добавил в Demo-проект свой базовый класс для Пейджобжектов:
public abstract class MyBasePage extends CorePage implements SelfTestingPage
Кода в CorePage не много, но вот что он делает…
public abstract class CorePage {
public WebDriver getDriver()
{
return SwdBrowser.getDriver();
}
public CorePage()
{
PageFactory.initElements(getDriver(), this);
}
}
Инициализация элементов дочернего PageObject класса проводится посредством вызова PageFactory.initElements из конструктора самого базового класса.
В C# и Java есть такая особенность, что если есть классы с конструкторами без параметров:
C → B → A
То конструктор базового класса A будет автоматически вызван при создании класса C.
Я обычно не передаю никаких значений в конструкторы PageObject, но если понадобится – то вызов необходимых методов уже нужно будет разрулить руками.
Использование интерфейса SelfTestingPage можно наблюдать в смоук тестах в файле:
Smoke_test_for_each_pageobject.java
public void testPage(MyBasePage page)
{
page.invoke();
page.verifyExpectedElementsAreDisplayed();
}
@Test
public void test_EmptyPage()
{
testPage(MyPages.getEmptyPage());
}
Так что для добавления новой страницы в смоук тест, нужно добавить новый тест, по аналогии выше.
test_SomeRealPagе
А в самой странице (SomeRealPagе) , реализовать три метода: invoke(), isDisplayed() и verifyExpectedElementsAreDisplayed()
Сам же набор смоук тестов откроет каждую страницу при помощи invoke(), а дальше вызовет метод для само тестирования PageObject класса – verifyExpectedElementsAreDisplayed().
Самый универсальное и минимальное что можно сделать в verifyExpectedElementsAreDisplayed() – это проверить то, что каждый важный контрол, который задекларирован в пейджобжекте все ещё присутствует на реальной странице. Но, этим можно не ограничиваться, и придумать дополнительные проверки.
Такие смоук тесты обычно работают очень быстро и позволят выявить расхождение между декларациями пейджобжектов и реальными страницами до прогона основных тестов.