Здравстуйте!
Хочу узнать о хороших вариантах архитекры проекта автоматизированных тестов.
На данный вопрос натолкнула статья: How To Structure Your Test Code
Так как статья на английском, а народ еще и ленивый, я приведу основные выдержки из статьи тут.
Два основные подхода:
- Один тест кейс на класс
- Используй наследование с умом
Стркуткра проекта при таком подходе выходит следующая:
- Базовый класс для тестов (содержит общие аспекты для всех тестов, такие как запуск браузера)
- Один или более промежуточных тест класов (содержат общие методы для группы тестов)
- Сам тест класс (в котором тесты запускаются)
Картинка с визуализацией:
Код базового класса:
class Test {
protected setUpBeforeTestClass(){
// initialize a browser driver, connect to servers
}
protected setUpBeforeTestMethod() {
// initialize testPage
// login to the app, if necessary
}
protected tearDownAfterTestMethod() {
// logout of the app, if necessary
}
protected tearDownAfterTestClass() {
// close connections, close browser as needed
}
}
Код промежуточного класса:
class PostTest extends Test {
protected setUpBeforeTestClass(){
// no changes needed
super.setUpBeforeTestClass();
}
protected setUpBeforeTestMethod() {
// do the parent actions, then add some post-specific actions
super.setUpBeforeTestMethod();
testPage.goToPostPage();
}
protected tearDownAfterTestMethod() {
// logout of the app, if necessary
}
protected tearDownAfterTestClass() {
// close connections, close browser as needed
}
}
И наконец код класса с тестом:
class CreateNewPostTest extends PostTest {
public testCreateValidNewPost(){
// test is ready to go!
testPage.createNewPost(postDetails);
assert testPage.isPostPresent(postDetails);
}
public testCreateInvalidNewPost() {
// test is ready to go!
testPage.createNewPost(invalidPostDetails);
assert !testPage.isPostPresent(invalidPostDetails);
}
// and so on
}
Что кажется плохим в данной архитектуре:
В данной архитектуре меня смущает трехуровневое наследование, кроме того, если какие-то шаги нужно использовать повторно в других тестовых классах, нам придется вызывать методы другого тестового класса. Мне кажется что это не совсем красиво выглядит. Кроме того, обязательно случиться ситуация что для разных тестовых классов будут использоваться одни и те же шаги и чтобы всунуть их в такую архитектуру, нужно будет добавлять их в промежуточные классы. Но таким образом выйдет дублирование кода. Если же повторяющиеся шаги выносить в третьи классы, то тогда пропадает необходимость в промежуточных классах.
Идея с общим тестовым классом впринципе понравилась, но идея промежуточного классом с общими шагами кажется плохой.
Лично я в данный момент использую следующую архитектуру:
-
Много тестовых классов, которые отвечают за открытие браузера, его закрытие и за запуск тестов. Если это тест с несколькими проверками (например, покупка билета), то основные действия выполняются при инициализации класса (pre-condition), а каждая отдельная проверка (сами тесты) выполняются в отедльных методах этого класса.
Если же тест содержит только одну проверку (как тест успешной авторизации), то данные тесты группируются в одном классе (например, тест класс для авторизации у меня содержит 2 теста - успешная и неуспешная авторизация). -
Классы с общими действиями. Эти классы не наследуются, просто их объекты создаются в классах с тестами. Наприер, класс с общими действиями по покупке билета содержит методы: “Добавить билет в корзину”, “Изменить кол-во билетов”, “Оплатить билет”; тогда все эти методы вызываются в тестовых классах, что позвляет избежать дублирования кода.
-
PageObjects - классы в которых реализована логика взаимодействия со страницами сайта. Методы этих классов используются для классах с общими действиями, а также в тестовых классах.
В моем подходе в минусы можно занести:
- Дублирование кода запуска и закрытия браузера
- Все остальное что вы напишите в комментариях
О своей архитектуре я рассказал, пожалуйста поделитесь и вы своими идеями и наработками!