последовательное выполнение тестов через @Dataprovider, @Factory

factory
design-patterns
dataprovider
testng
java
Теги: #<Tag:0x00007f7b68fdae90> #<Tag:0x00007f7b68fdad50> #<Tag:0x00007f7b68fdac10> #<Tag:0x00007f7b68fdaad0> #<Tag:0x00007f7b68fda990>

(Alliness) #1

Добрый день.
Интересует возможность выполнение BDD сценариев в testNG.
Для начала опишу ситуацию:

Есть сьют “Check Results” (Как примеру, результаты поиска в интернет магазине) который состоит из нескольких тестов. По окончании этих тестов создается список айдишников товаров.

Задача, передать эти айдишники в след. сьют “Check Results Item” (Как пример, Страница выбранного товара), который так же состоит из нескольких тестов. И от кол-ва айдишников с списке выполнить нужное кол-во итераций сьюта c последовательным выполнением тестов.

Пытался решить изначально через DataProvider+Factory+Group-By-Instances. Но т.к. TestNG изначально создает сьют и связка dataProvider+Factory вызывается раньше всех, список айдишников еще не сформирован.

Пример кода :


@TestSuite(groupByInstances=true)
public class CheckResults extends TestScenario{

    private List<Object> items;

    @Test
    public void ResultsTestA() {
        //some tests of results page.
    }

    @Test
    public void ResultsTestB() {
        items = new ArrayList<>();
        items.add("item#1");
        items.add("item#2");
    }

    @DataProvider
    public Object[] itemsProvider() {
        return items.toArray();
    }

    @Factory(dataProvider = "itemsProvider")
    public Object[] itemTestFactory(String itemId) {
        return new Object[]{new ItemTest(itemId)};
    }

    private class ItemTest {

        private final String itemId;

        public ItemTest(String itemId) {
            this.itemId = itemId;
            //goto item page.
        }

        @Test
        public void ItemTestA(){
            //some test of item
        }

        @Test
        public void ItemTestB(){
            //some test of item
        }
    }
}

Второе решение это создать новый TestNG Runner в рамках первого сьюта. и скормить ему сьют “Check Results Item”. передав список айдишников через ITestContext. Это решение работает, но создаются неверные результаты репортов.


===============================================
ResulstSuite
Total tests run: 6, Failures: 1, Skips: 0
===============================================

[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 4.584 s - in TestSuite
[INFO]
[INFO] Results:
[INFO]
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------

Тестов выполнено 6, из них 1 фейл. Но maven видит только один. И говорит что все ок.

Так же были попытки использования слушателей IAlterSuite, IAnnotationTransformer’s, IMethodInterceptor, но результатов не дали.

Env: Java 8, TestNG 6.14.3, Allure 2.6


(Bohdan Kuso) #2

Добрый день! В данном случае, можно поступить следующим образом:

  1. Создать пустую private переменную типа List listOfId; (Стринговый массив Selenide позволяет достать одним методом .texts())
  2. Сделать так, чтобы тесты которые собирают id присвоили полученный массив в переменную listOfId.
  3. Написать @DataProvider метод так, чтобы он возвращал listOfId.toArray()
  4. Написать тестовый метод, с аннотациями dataProvider = <Созданный в шаге 3 провайдер>, dependsOnMethods = <имя тестового метода, собирающего массив listOfId>, и принимающий значение String id
  5. Запустить.

(Alliness) #3

Да я уже подобным метогом и решил проблему, отказавшись от фабрики. Сейчас у меня выглядет как то так:

public class CheckResults extends TestScenario{

    private List<Object> items;

    @Test(groups="mainGroup")
    public void ResultsTestA() {
        //some tests of results page.
    }

    @Test(groups="mainGroup")
    public void ResultsTestB() {
        items = new ArrayList<>();
        items.add("item#1");
        items.add("item#2");
    }

    @DataProvider
    public Object[] itemsProvider() {
        return items.toArray();
    }

    @Test(dataProvider="itemsProvider", dependsOnGroup="mainGroup")
    public void itemTestRunner(String item){
        testStepA(item);
        testStepB(item);
    }

    @Step
    private void testStepA(String item){

    }
    
    @Step
    private void testStepB(String item){

    }
}

Единственный минус - это testStepA, testStepB теперь не тесты, а степы.