Test Data Supplier - TestNG Dataprovider на стероидах
Привет, друзья! Сегодня хочу поделиться рецептом, который поможет сделать тесты еще лучше.
На большинстве своих проектов я сейчас использую связку инструментов Java/Kotlin + TestNG
Allure + Gradle. Ранее я уже писал о некоторых подходах, которые позволяют нам более
удобно готовить данные для тестов,
работать с базой данных и писать меньше аннотаций для Allure.
В этой заметке хочу рассказать о том, как улучшить Dataprovider. Очень часто в тестах приходится оперировать различными наборами данных. В каких-то случаях данные проще захардкодить, в каких-то - тащить из внешних источников. В большинстве случаев для оптимизации кода и параметризации я использую TestNG Dataprovider.
Давайте возьмем для примера простой тест - логин форма с тремя полями и валидацией.
@Test(dataProvider = "Authentication")
public void errorMessageOnLoginWithBadCredentials(String email, String password, String errMsg) {
User badUser = new User(email, password);
at(LoginPage.class)
.loginAs(badUser)
.errorMessage
.shouldHave(exactText(errMsg));
}
@DataProvider(name = "Authentication")
public static Object[][] credentials() {
return new Object[][]{
{" ", " ", "Username is required"},
{"admin@gmail.com", "UserTest@123", "Login and / or password do not match"},
{"admin@gmail.com", " ", "Password is required"},
{"ololo@ololo.com", "admin", "Login and / or password do not match"}
};
}
Очень простой сценарий: в разных случаях пользователю будут показываться разные сообщения об ошибке. Здесь я применил Dataprovider, так как для каждой итерации у нас меняются лишь входные данные для теста.
Вроде как все отлично и даже работает.
Есть ли что-то, что можно улучшить? (люблю этот вопрос на собеседовании =))
Конечно, стоит посмотреть на уродливый дата провайдер. Вот этот Object[][] - то прям боль. Учитывая то, что мы живем в 2018 году, пишем на Java 8, которая поддерживает Stream API и имеет хороший Collection API. Двухмерный массив объектов - это несерьезно!
И даже с помощью няшного Котлина нельзя особо улучшить ситуацию.
@DataProvider
fun data(): Array<Array<String>> {
return arrayOf(
arrayOf(" ", " ", "Username is required"),
arrayOf("admin@gmail.com", "UserTest@123", "Login and / or password do not match"),
arrayOf("admin@gmail.com", " ", "Password is required")
)
}
Остается смириться и писать такой вот говнокод. Но на самом деле ситуацию можно поправить с помощью библиотеки Test Data Supplier. Ее автором является один мой друг - Сергей Король.
Я о ней знал давно, но как-то попробовав ее еще на начальных этапах, не особо проникся идеей. Пока на днях не решил внедрить ее в один из новых проектов.
Подключение выполняется достаточно просто. Однако там есть один нюанс: для корректной работы требуется подключение DataProviderTransformer лисенер. Так вот подключать этот лисенер стоит либо через Gradle, либо через TestNG xml. Подключение через аннотацию @Listeners не даст желаемого результата. Учтите этот момент, я уже этот путь прострадал за вас=)
После подлючения вам станут доступны все плюшки этой библиотеки.
Можно легко переписать ваши унылые дейтапровайдеры на новый лад:
@DataSupplier
fun data(): Array<Array<String>> {
return mapOf(
User(" ", " ") to "Username is required"),
User("admin@gmail.com", "UserTest@123") to "Login and / or password do not match"),
User("admin@gmail.com", " ") to "Password is required"
)
}
Тест в таком случае трансформируется в такую штуку:
@Test(dataProvider = "data")
fun errorMessageOnLoginWithBadCredentials(User user, String errMsg) {
at(::LoginPage)
.loginAs(user)
.errorMessage
.shouldHave(exactText(errMsg));
}
Все становится прям огненно круто. Есть, правда, один досадный момент: для полной поддержки нужно установить Idea плагин - test-data-supplier-plugin. Сама библиотека поддерживает разные навороты, о которых можно почитать в документации.
В общем всем рекомендую как минимум посмотреть на эту библиотеку, как максимум - прикрутить ее к себе в проект и пробовать.
Спасибо, что читали. Надеюсь, многим эта заметка поможет вывести тесты на новый уровень.