Параллельный запуск в нескольких браузерах Selenide, TestNG, Gradle, Allure.Какой нормальный паттерн?

grid
gradle
testng
selenide
allure
Теги: #<Tag:0x00007f7b70a5be58> #<Tag:0x00007f7b70a5bd18> #<Tag:0x00007f7b70a5bbd8> #<Tag:0x00007f7b70a5ba70> #<Tag:0x00007f7b70a5b930>

(Роман Румянцев) #1

Хочу сделать параллельный запуск тестов на нескольких браузерах.
Использую Selenide, TestNG, Allure и Gradle. + Grid.
Пока решил сделать хотя бы последовательный запуск.
Сначала пришел к идее передавать браузер в качестве параметра в Suite testNG но @asolntsev где то писал что это плохая идея(открывается один браузер на все тесты). Он говорит, что надо юзать несколько задач в Gradle. Но в таком случае мне не понятно как с этим всем должен отработать Allure, ведь отчетов получается несколько.
Посоветуйте нормальный паттерн, пожалуйста.


QAweekly #45: Travis CI, ресурсы для изучения REST API, матрицa критичности-сложности, тестовые задания, параллельный запуск в нескольких браузерах, причина появления багов.
(Vasiliy Rakshin) #2

Самое простое - раз вы используете TestNg - запуск нескольких потоков с помощью него. Это поможет распараллелить запуск на 1 машине. Сначала напишите хотя бы 2 теста, не столь важно, в одном классе они будут или двух. А далее, просто применив 2 параметра для запуска:
-Dparallel=methods -DthreadCount=2
запустить их на выполнение.
Для каждого запуска создаётся отдельный отчет, но при финальной сборке Аллюра должен получиться сводный отчет, где будут 2 этих теста.
Либо, если вы используете xml для запуска тестов - то читайте это - Параллелизм в TetsNG


(Роман Румянцев) #3

Что от я не особо заметил разницы в Вашем решении с тем что у меня уже не работает. Даже без параллельного запуска.
Сделал xml

<suite name = "testGoogleSearchInDiffBrowsers">
    <test name = "testInFirefox">

        <parameter name = "browser" value="firefox"/>

        <classes>
            <class name = "com.tw1911.test1.GoogleSearchTests" />
        </classes>

    </test>
    <test name = "testInChrome">

        <parameter name = "browser" value="chrome"/>

        <classes>
            <class name = "com.tw1911.test1.GoogleSearchTests" />
        </classes>

    </test>

</suite>

В тесте

    @Parameters("browser")
    @Test
    public void testGoogleSearch(String browser){
        Configuration.browser= browser;
        open("http://google.com");
    }

В итоге оба раза открывается один и тот же браузер.
Как сделать что бы это нормально работало?


(Vasiliy Rakshin) #4

А если попробовать -Dparallel=tests -DthreadCount=2 ?
При использовании параметров - как у вас, вот так просто без дополнительных телодвижений - никак (ну думаю, тут грид тогда надо разворачивать, тогда можно).
Используйте датапровайдер, у него хоть есть параллелизм:

@DataProvider(parallel = true)

(Роман Румянцев) #5

Да тут сейчас речи о параллелизме не идет. Проблема пока возникает при ПОСЛЕДОВАТЕЛЬНОМ запуске. Но так как конечная цель - параллельный запуск, я решил спросить сразу как правильно.


(Vasiliy Rakshin) #6

Дорогой Роман, давайте уж тогда последовательно, в чём проблема? Какую ошибку получаете, что делаете?


(Funker) #7
  1. я бы сделал сперва просто парралелизации, и добился бы приличной стабильности с одним браузером не важно с камим на 2-5 потоков, тут много будет нюансов и все такое.
  2. этап №2 - разные браузеры. Это можно сделать на уровне CI Jobs это делается очень просто, нужно в просто передать имя браузера как параметр и все.
  3. а теперь все эти jobs там не знаю сколько 2 или 5 их будет запустить одновременно и как источник браузров будет selenoid или ему аналоги как этот https://opensource.zalando.com/zalenium/ , тут вообще все просто он очень хорошо документирован. Чистый Selenium Grid походу как-то отмирает, и не ипользуется больше.

Из всего выше перечисленного самый сложный это пункт #1
Замечание: вот это все, что вы пытаитесь делать через testNG xml это все fun но вы сами прийдете, что это фигня. Все нужно через командную строку передавать как параметы, начитая от браузера, заканчивая какие тесты и во сколько потов запускать! У всех параметров должны быть defaults заначения если их не задать в командной строке


(Роман Румянцев) #8

Все очень просто:
Создал 1 тест с кодом из 3 сообщения.
К этой задаче создел сьют для TestNG. Код приведен в третьем сообщении.
Далее выполняю этот сьют из Gradle.

test {
    useTestNG() {
        suites 'src/test/resources/runlist/my_test.xml'
    }
}

В результате тест запускается 2 раза в одном и том же браузере. Для начала хотелось бы решить эту проблемы, потом уже переходить к параллелизму.


(Funker) #9

не не не, один и тот же тест запускается 2 раза, это длается не так
http://testng.org/doc/documentation-main.html вот так invocationCount через параметр, я использую эту фичу когда делаю дебаг. После окончательного написания теста, делаю invocationCount=10 и проверяю на сколько он стабилен, не падает ли 1-2-3 раза из 10. Если да, то нужно смотреть почему и делать его более стабильным

И так не получится, чтоб было 2 потока, да такая возвожность есть у TestNG но для браузерных тестов оно плохо работает.
Из моего опыта самый лучшый способ парралелизации так это парралелизация по классам. оно более ставильно и работает как ожидается. Внутри класса парралелить выполнение тестов это работает, но как-то сильно не стабильно ИМХО.


(Роман Румянцев) #10

Проблема же не в том как это передается, а в том как с этим работает Selenide и TestNG. Вот с этой проблемой мне бы хотелось разобраться для начала.


(Funker) #11

вот пример как это можно делать, здесь все понятно на мой взгляд.

mvn clean -Dthreads=3 -Dselenide.browser=chrome -Dselenide.browserSize=1440x900 -Dapp.url=https://google.com -Dgroups=destinations,metrics -Dremote=http://127.0.0.1:4444/wd/hub test

(Роман Румянцев) #12

Хорошо, сделаю я так. Дальше запущу AllureReport и что я получу?


(Vasiliy Rakshin) #13

Надо

@Parameters({"browser"})

И попробуйте в конце теста, или в новом методе с @AfterMethod закрывать браузер (Selenide.close()), т.к. не помню, если браузер запущен, и вы изменили настройку, то она вряд-ли применится.


(Роман Румянцев) #14

Решение проблемы с браузером - закрывать его. Все правильно.
А подскажите, теперь же если параллельно запустить оба теста они должны отработать параллельно в 2 браузерах?


(Funker) #15

это просто запуск тестов, Allure тут не причем, если вы запускаиете локоально то нужно потом сгенерить репорт командой mvn site
Репорт и тесты это разные сущности. В процессе рана тестов allure listener просто собирает и кладет в папку targer/allure-results все артифакты тестов, что вы там в тестах накофигурили, затем на основет этих тестовых артефактов нудно сгенерить/построить отчет командой выше ИЛИ это за вас делает ваш CI в моем случае это Jenkins


(Роман Румянцев) #16

Теперь запускаю параллельно, и теперь то же самое, открывается только один браузер. Я чувствую что Selenide надо выкинуть на мороз с этого праздника жизни.


(Vasiliy Rakshin) #17

Как вы запускаете параллельно?


(Роман Румянцев) #18

Запускал вот так:

    @DataProvider(name = "browser-provider", parallel = true)
    public Object[] provide() throws Exception {
        return new Object[]{"firefox", "chrome"};
    }

 //   @Parameters({"browser"})
    @Test(dataProvider = "browser-provider", threadPoolSize = 2)
    public void testGoogleSearch(String browser){
       Configuration.browser=browser;
        open("http://google.com");
        $(By.name("q")).setValue("Тестовое задание");
        $(By.xpath("//input[@value='Поиск в Google']")).click();
        $(By.id("resultStats")).shouldBe(Condition.visible);
        Selenide.close();

    }

Добился что бы работало

    @DataProvider(name = "browser-provider", parallel = true)
    public Object[] provide() throws Exception {
        return new Object[]{"firefox", "chrome"};
    }

 //   @Parameters({"browser"})
    @Test(dataProvider = "browser-provider", threadPoolSize = 2)
    public void testGoogleSearch(String browser){
        SelenideDriver browser1 = new SelenideDriver(new SelenideConfig().browser(browser).driverManagerEnabled(true));
        browser1.open("http://google.com");
        browser1.$(By.name("q")).setValue("Тестовое задание");
        browser1.$(By.xpath("//input[@value='Поиск в Google']")).click();
        browser1.$(By.id("resultStats")).shouldBe(Condition.visible);
        browser1.close();

    }

Не знаю, первый вариант можно было заставить работать адекватно?


(Funker) #19

да этот вариант работает но на практике в реальных условиях, я не верю чт так можно запускать test suites по больше чем 5 разных тестов, когда эта вся балалайка упадет, продебажить в какой тип браузера, что там случилось просто очень будет сложно.
К примеру, меня есть 50 тестов, я их запускаю как отдельные jenkins jobs by browser type (FireFox, Chrome) я хочу видеть 2 jobs а не одну с 100 тестами. Дебажить протсо не реально сложно


(Роман Румянцев) #20

Эм, а в чем проблема продебажить? Ну упал у тебя один тест, увидел это в отчете, дальше запустил 1 тест, хоть локально, хоть удаленно - все. Не вижу проблемы вообще.