t.me/atinfo_chat Telegram группа по автоматизации тестирования

Зависимые тесты и dataProvider, как правильно построить зависимость

test-data
java
selenium
webdriver
testng
Теги: #<Tag:0x00007f9c5c86d558> #<Tag:0x00007f9c5c86d3a0> #<Tag:0x00007f9c5c86d1c0> #<Tag:0x00007f9c5c86cfb8> #<Tag:0x00007f9c5c86ce50>

(Анастасия Кашина) #1

Проблема:
Имеется два документа: краткая анкета и полная анкета. Полную анкету можно создать только на основе кратной. Плюс в этих анкетах есть параметризация (dataProvider). Таким образом у меня есть зависимые тесты. Но проблема возникает как раз на стыке зависимости и параметризации.
Если, например, в сценарии (xml) где полная анкета имеет параметризацию, указывать последовательность тестов так:

    <test name="createAppWithEnterMinimumField">
        <classes>
            <class name="com.multi.dso.CreatePreAppTest">
                <methods>
                    <include name="createPreAppWithNoPatronymicOfPerson"/>
                </methods>
            </class>
            <class name="com.multi.dso.CreateAppTest">
                <methods>
                    <include name="createAppWithEnterMinimumField"/>
                </methods>
            </class>
        </classes>
    </test>

То будет создана только одна краткая анкета и несколько полных. А нужно, чтобы они именно совместно были.

Я попыталась протягивать тестовый метод создания краткой анкеты в полную:

public class CreateAppTest extends CreatePreAppTest

И далее уже в тесте создания полной анкеты вызывать тестовый метод создания краткой анкеты:

    @TestRailCaseId("139")
    @Test(description = "Анкета без доп. информации"
            , dataProvider = "getOccupationNameWithoutInfoOfWork"
            , dataProviderClass = TestCreateAppData.class
    )
    public void createAppWithEnterMinimumField(String occupationName) throws Exception {
// Создание краткой анкеты
            createPreAppWithNoPatronymicOfPerson();

Таким образом у меня всегда создается краткая анкета для полной. И вкупе с параметризацией это хорошо работает.

Но проблема в том, что этот метод создания краткой анкеты вызывается не как тестовый метод (со всей инициализацией нового браузера и пр) и соответственно я не могу получить результат выполнения этого теста, а так же значения аннотации TestRailCaseId для того, чтобы пушить результат в TestRail. Так же при таком решении есть проблемы с адресной строкой брайзера - не всегда очищается.

Сами автотесты дергаю Gradle таской, которая считывает xml:

task createAppTest(type: Test) {
    useTestNG {
...
        suites 'src/test/resources/create-app.xml'
    }
}

Как правильно решить вопрос зависимости автотестов? Можно ли как-то из одного теста инициировать запуск другого? Какие вообще есть варианты?

Так же бывает проблема, когда нужно в ходе регресса прогнать параметризованный тест только один раз. Как сделать так, чтобы dataProvider срабатывал только единожды?


(Vatslau) #2

я бы сохранил данные анкеты в файл(ы)
и потом если нужно использовал в другом тесте через чтение данных

PS есть же “depends on” с указанием теста от которого зависит тест
1-й сгенерил данные и ок
2-й зависимый от первого считал данные и выполнил свои действия

но вообще лучше создать в БД приложения эти анкеты потом использовать(не факт конечно что у вас есть доступ)


(Анастасия Кашина) #4

DependsOn даст мне только то, что если упадет тест, от которого зависит второй, то и он не выполнится. Но это не позволит мне проталкивать первый тест во второй. И вообще никакой роли не будет играть при параметризации. Хранение данных краткой анкеты в файле… Тоже не вижу как это поможет, если для полной анкеты нужно наличие уже созданной сущности краткой анкеты, а не просто набор данных


(Vatslau) #5

анкеты наверняка ассоциированы с юзерами?
воможно есть урл анкеты?
ну вот
генерим данные (не важно как в данном случае)
юзер1 - анкета1
юзер2 - анкета2

Используем данные(можно через провайдер)
Залогиниться юзером-X
c анкетой Х
Исполнить скрипт

Тесты можно выстроить в порядке приоритета 1-2-3 итд

вообще не очень понятно зачем связывать тесты
почему не может быть в базе создано(не важно как хоть руками) Х вариантов анкет для всех тестов где не тестируется создание анкет

если по каким-то причинам создание анкет нельзя разделить
то и тесты не стоит разделять - тк это 1 флоу
и лучше запихнуть все в 1 датапровайдер
Если объект большой - json/yam и работа через модели
dataProvider = “importFullFormObject”

если нужно динамическое тестирование формы
прийдется продумать создание объекта в before suite
есть много библиотек для рандомизации данных полей


(Vladislav Sobol) #6

Если создание короткой анкеты и создание длинной анкеты это два разных теста то они действительно должны быть разными. Если перед полной анкетой всеже необходимо иметь созданую короткую анкету и не тестить создание короткой анкеты по 2 раза можно попробовать

  1. Перед тестом полной анкеты создать короткую с помощью API колов. Это будет быстрее чем через UI и протестируете вы именно создание полной анкеты.
  2. Анкеты ведь хранятся гдето в базе, можно перед тестом полной анкеты заинсертить в базу значения короткой анкеты для юзера Х, а в самом тесте им логиниться и продолжать тестить именно полную анкету.

(Sergey Korol) #7

Правильную идею подали выше насчет API или DB.

А вообще, все упирается в постановку задачи. Если рассматривать условие создания краткой анкеты, как precondition к функционалу создания полной, то любые упоминания “зависимых” тестов сразу же испарятся.

По факту у вас должно быть 2 независимых теста. И если с первым все просто - создали краткую анкету через UI, провели верификацию -> профит. То второй тест должен посредством DataProvider сходить на API / DB / whatever, подготовив нужные данные on-fly, и прередать на вход тесту. С API шансы получше повторить реальный flow и создать все необходимые сущности.

Если вы тестируете функционал полной анкеты, то нет никакого смысла дублировать шаги создания краткой через UI, ибо у вас уже есть выделенный для этого тест. Основная задача - приведение системы в пригодное для тестирование состояние путем прекондишенов. А пытаться обыграть связи двумя тестами - вариант заведомо проигрышный.


(Анастасия Кашина) #8

Спасибо за вариант с DB! Нужно будет посмотреть сколько таблиц участвуют в формировании краткой анкеты. С Api нет возможности попробовать, ибо такого вообще не существует.
Остался вопрос с DataProvider: можно ли вызвать тест с dataProvider только один раз, для регресса? И если да, то как?


(Vladislav Sobol) #9

С Api нет возможности попробовать, ибо такого вообще не существует

Не совсем понятно что вы имеете ввиду под не существует. Ваше приложение как-то и куда-то ведь отправляет данные которые ввел юзер, они потом гдето сохраняются, запись в базу происходит, иначе это просто ХТМЛ страничка :slight_smile:
С базой может быть такой вариант что прийдется трогать несколько таблиц и это будет менее удобно чем через апи послать данные на один эндпоинт который уже сам все сделает (как это работает в реале), но если там 1-2 таблицы то тут выбирайте как вам удобнее.

Остался вопрос с DataProvider: можно ли вызвать тест с dataProvider только один раз, для регресса? И если да, то как?

Тоже не совсем понятно. Создайте датапровайдер с одним значением, тест прогонится один раз.


(Анастасия Кашина) #10

Имеется в виду, что у меня нет доступа. Только через ДБ

Если изначально был тест с DataProvider, у которого более одного значения. Есть suite, где этот тест прогоняется с полным набором, и есть регрессионный suite, где этот тест желательно прогнать только единожды.


(Vladislav Sobol) #11

Что вам мешает иметь 2 датапровайдера ? Один с кучей значений, а другрй только с одним.
И иметь 2 теста один использует большой датапровайдер, а второй исрлозует провайдер с одним значением. Один сют бегает с полнцм набором, а регрессионный гоняет тест только с одним значением

В итоге у вас получится:

@DataProvider(name = "ManyValues")
    public Object[][] manyValues() {
        return new Object[][]{
                // Name, LastName, Age
                {"Name_1", "Lastname_1", "male", 25},
                {"Name_2", "Lastname_2", "female", 21},
                {"Name_3", "Lastname_3", "male", 30},
                // and many more lines
                {"Name_N", "Lastname_N", "male", 99},

        };
    }

    @DataProvider(name = "OnlyOneValue")
    public Object[][] onlyOneValue() {
        return new Object[][]{
                // Name, LastName, Age
                {"Name_1", "Lastname_1", "male", 25},
        };
    }

    @Test(description = "Test with dataprovider (ManyValues)",
            dataProvider = "ManyValues")
    public void testWithManyValuesinDataprovider(String name, String phone, int age) {
        // DO your test
    }

    @Test(description = "Test with dataprovider (OnlyOneValue)",
            dataProvider = "OnlyOneValue")
    public void testWithOnlyOneValueinDataprovider(String name, String phone, int age) {
        // DO your test
    }

В XML полного сюта вы добавите testWithManyValuesinDataprovider

В XML регрессионного сюта вы добавите testWithOnlyOneValueinDataprovider


(Sergey Korol) #12

Можно и одним DP ограничиться, если манипулировать переменными окружения. Условный код:

public StreamEx<YourDataType> getData() {
    return StreamEx.of(readDataSource(SUITE));
)

Где readDataSource допустим принимает переменную окружения SUITE, и отдает какой-то набор данных из таблиц, файлов и т.п. по заранее установленным правилам. Если чуть более детально продумать интерфейс, то выйдет вполне себе красиво, лаконично и переиспользуемо.