Добрый день,
Много не ругайтесь, вопросов много. В первую очередь по поводу структуры фреймворка.
Итак, связка: Selenium + TestNG + HTMLElements (понравилась идея разбития на блоки и типизация). (Только, пожалуйста, особо к технологиям не привязывайтесь, т.к. тот же HTMLElement можно убрать)
Примерная структура страницы приведена на рисунке.
Есть хедер, на котором находится изображение, под ним текст. Слева от них меню.
Сама страница разбивается на три блоке - Left, Content, Right.
В Left и Right находятся меню (так же допускаются другие элементы, это не столь важно)
В Content - сам контент. Варьируется от текстов до форм и пр. содержания.
Изначально я думал разбить страницу на блоки. Соотвественно - HeaderBlock, LeftBlock, RightBlock, ContentBlock.
А дальше все это выдать в классе PortalPage.
В итоге, пришел к выводу, что ни черта не понимаю, как конкретно работать с PageObject Pattern.
Поэтому первый вопрос:
- Что мы конкретно реализовываем в блоках?
Возвращаем элементы геттерами? И никаких действий. Или наоборот, определенный набор действий, который мы возвращаем классу PortalPage?
Возьмем за пример Хедер.
@Block(@FindBy(id = "headerBlock")
public class HeaderBlock extends HTMLElement{
//Сами элементы
@FindBy(id = "image")
Image image;
@FindBy(id = "headerText")
TextBlock headerText;
@FindBy(id = "headerMenu")
List<WebElement> headerMenuList;
//геттеры
public List<WebElement> getHeaderMenuList(){
return headerMenuList;
}
public TextBlock getHeaderText(){
return headerText;
}
public Image getImage(){
return image
}
//Методы для обработки
public boolean isImageVisible(){
Utils.isImageVisible(image); // многие методы для работы с часто встречающимися элементами выведенны в отдельный класс.
}
}
Дальше, допустим, идет PortalPage class
public class PortalPage{
protected WebDriver driver;
private HeaderBlock headerBlock;
public PortalPage(WebDriver driver){
PageFactory.initElements(new HtmlElementDecorator(driver), this);
this.driver = driver;
}
public boolean isHeaderImageVisible(){
return headerBlock.isImageVisible();
}
}
ну и тест
public class TestPortal(){
PortalPage portal;
@BeforeTest
public void PseudoSetUp(){
portal = new PortalPage(driver)
}
@Test
public void pseudoTest(){
Assert.assertTrue(portal.isHeaderImageVisible, "true");
}
}
Т.е. вопрос, где я должен был реализовать определения, видно изображение или нет?
Если так, как указано выше, то не является ли дублирование указание этого метода в классе PortalPage?
-
Второй вопрос - Все блоки кроме content - статические. Т.е. их содержание не изменяется (разве что меню в зависимости от страницы подсвечивается).
Но вот сам блок контент содержит в себе абсолютно не зависимую друг от друга информацию, формы и т.д.
Как это реализовать? (естественно, в теории :)) Писать под каждую страницу отдельный блок? т.е. Page_1_Block, Page_2_Block.
Но как их тогда инициализировать? Не буду же я в классе PortalPage инициализировать все возможные блоки? Получится еще то полотно. -
Подскажите, как вообще лучше реализовать именно структуру фреймворка.
На сегодня у меня примерно так, но в области автоматизации ГУИ я абсолютный новичок
ru.qa.projetname
configuration - пэкедж с классами, для конфигурации
common - пэкедж для общих проблем
constants - константы
utils - утилиты, вроде работы с файлами и т.д.
testObject - тестовый объект
portal
pages - страницы (прим. PortalPage)
blocks - блоки (прим. HeaderBlock)
utils - утилиты для работы со списками элементов, таблицами и т.д
constants - константы, признаюсь честно, на сегодняшний день я храню здесь локаторы, т.к. пока что не придумал, где их хранить удобнее.
Ну и по большому счету все (что требуется на текущий момент), сами тесты находятся в Main/src/test
- Все ассерты, как я понимаю, надо писать в теле тестов?
Если что-то описано непонятно, спрашивайте, попытаюсь объяснить доходчивее. Примеры, конечно же, липовые, но близкие к оригиналу.
Похожие темы я искал, но к сожалению, не нашел.
Спасибо!
С уважением,
Картинку вставлять не стал, т.к. получилась уж очень большая, но вот ссылка на нее.
@ArtOfLife: перезалил картинку и отформатировал код.