Мне тоже так показалось. спасибо. А по поводу второго вопроса, также поступать как с Листами?
Да, повторяющийся функционал принято выносить в отдельные элементы (методы, классы и т.д.), которые:
- инкапсулируют в себе необходимую логику поведения элемента
- могут быть переиспользованы
А если например представить, что (элементов стало много) есть в общей сложности 50 видов кнопок и 1000. И они могут быть на странице, а могут не быть, ну и различные комбинации бывают. В этом случае я думал что нужно делать некую видимость элементов для конкретной страницы (karaoke.footer().save(); // после футера видно будет только 15 методов
) или все же нужно в один класс все 50 кнопок поместить и по мере необходимости унаследовать этот класс?
P.S. вопрос практически похожий но я хотел это посмотреть с более глобальной точки зрения.
- Любой повторяющийся элемент интерфейса - это отдельный класс, реализующий паттерн PageObject
- Сложность возникает тогда, когда один и тот же элемент интерфейса, например, список объектов, который с виду выглядит одинаково на разных страницах и так и просится выделить его в отдельный класс и переиспользовать, в реальности оказывается реализован на разных страницах по-разному: имеет разную верстку, разные id элементов и т.д.
Придерживайся правила в п.1 и не забывай по поводу п.2 требовать с разработчиков одинаковой реализации одинаковых элементов на разных страницах
Хорошо, но если я вынес элементы в отдельный класс (Button.class
) и тут встречается страница где 3 кнопки отсутствуют. Я наследую класс с элементами кнопок для Karaoke.class
, но в этом случае будет видимость нескольких кнопок которые не доступны по сути у Karaoke.class
такое поведение правильно?
karaoke.footer().save(); // кнопка save - доступна для формы караок
karaoke.footer().print(); // кнопка print - не доступен для формы караок
Если элемент переиспользуется на разных страницах, класс работы с этим элементом не должен быть встроен в страницу
Понял, спасибо.
God object - это всегда плохо
Так ведь общие элементы в одном классе которых как-раз может накопится до 50, уже по сути будет являться God Object, разве нет?
Какие же они “общие” если
Вы тогда наверно имели в виду “Пихать все в один класс описывающий страницу” да? (в данной теме)
Хорошо, а допустим есть Footer с кнопками, который есть на главных страницах меню(караоке, видеофильмы итд) если мы откроем форму одной из этих страниц, то там есть тоже Footer со своими кнопками, а внутри формы есть Popup в котором тоже есть Footer и тоже со своими отличными кнопками. То есть 3 разные страницы со своим Footer. Как быть в такой ситуации?
Если на разных страницах разные футеры, значит они должны быть представлены разными PageObject-классами фреймворка. Причём, если этот футер уникален для этой конкретной страницы (на других страницах не используется), то его вообще нет необходимости выносить в отдельный класс, а реализовывать в классе самой страницы
Иногда декомпозиция (классы, иннер классы) имеет место быть, для уменьшения нервов и износа скролла мыши.
Можете глянуть в сторону использования фреймворка html elements
Хотя в нем есть конечно свои недочеты, но как вариант - можно посмотреть и почерпнуть из него что-то для себя
Решил вынести в отдельный класс Footer для форм, так как кнопки там одинаковые. И опять сразу возникла проблема (по видео с Михаилом по PageObject) говорится что мы в каждом методе должны возвращать объект страницы с которой продолжаем работать. В следующем случае я должен возвращать, что-то после метода public void save()
?
public class Footer{
public void save(){
}
}
public class Karaoke extends Page{
public Footer button(){
return new Footer(driver);
}
}
public class Movie extends Page{
public Footer button(){
return new Footer(driver);
}
}
По-хорошему, да
Но Сохранение не закрывает карточку, а значит возвращает туже страницу с которой мы работали Karaoke. То есть на каждую страницу придется тогда делать свой возврат
public class Footer{
public Karaoke save(){
return new Karaoke(driver);
}
public Movie save(){
return new Movie(driver);
}
public Serials save(){
return new Serials(driver);
}
Понимаю что это не правильно, как быть?
Так просто не получится сделать, поскольку перегрузка методов не работает с разными возвращаемыми типами.
Вот тут тебе и пригодятся интерфейсы И генерики (они же дженерики, generics)