Поведение драйвера при выполнении параллельных тестов селена TestNG с поставщиком данных

Я хочу запустить тесты селена в TestNg параллельно, которые используют @dataprovider. В идеале тесты параллельны по методу (один тест = один метод), а не простой набор параллелизма в браузере. Я где-то читал, что одновременно можно управлять примерно 5 экземплярами ChromeDriver, поэтому я подумал, что это возможно. Позже планирую перейти на grid2. Для разработки я запускаю тестирование с помощью IntelliJ Idea, выполняя тест по правому клику + запуск файла конфигурации XML.

У меня были проблемы с выполнением моих тестов параллельно (на grid2 и локально), поэтому я создал пример более или менее того, что я хочу сделать.

Вот мой тестовый класс

package tests;

import org.openqa.selenium.By;
import org.openqa.selenium.Keys;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.interactions.Actions;
import org.testng.annotations.*;
import java.util.concurrent.TimeUnit;
import static org.testng.Assert.assertNotNull;

public class ParallelTest {
    public static final String SEARCH_TERMS = "search-terms";
    private WebDriver driver;

    @BeforeMethod
    @Parameters({"browser"})
    public void beforeMethod(@Optional("chrome") String browser){
        driver = getBrowser(browser);
        driver.manage().deleteAllCookies();
        driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
    }

    private WebDriver getBrowser(String browser) {
        if(browser.equals("chrome")){
            System.setProperty("webdriver.chrome.driver", "webdrivers\\chromedriver.exe");
            return new ChromeDriver();
        }
        return new FirefoxDriver();
    }

    @AfterMethod
    public void afterMethod(){
        driver.quit();
    }

    @Test(description = "Check parallel selenium works.",
          dataProvider = SEARCH_TERMS)
    public void parallelSeleniumTest(String searchTerm){
        driver.get("http://google.com");
        WebElement search = driver.findElement(By.id("gbqfq"));
        new Actions(driver)
                .sendKeys(search, searchTerm)
                .sendKeys(search, Keys.ENTER)
                .perform();
        String firstResult = driver.findElements(By.className("r")).get(0).getText();
        assertNotNull(firstResult);
        System.out.println(firstResult);
    }

    @DataProvider(name = SEARCH_TERMS, parallel = true)
    public Object[][] getSearchTerms(){
        return new Object[][]{
                {"google"},
                {"microsoft"},
                {"facebook"},
                {"amazon"},
                {"apple"},
                {"oracle"},
                {"yahoo"},
                {"jetbrains"},
                {"intellij idea"},
                {"selenium"},
                {"java"},
                {"testng"},
                {"code"}
        };
    }
}

Я добавил некоторые нативные события, так как я интенсивно использую их в своем тестовом наборе.

А вот и файл конфигурации TestNg xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite thread-count="4" name="vfr6-ui-tests" parallel="methods">
    <test name="parallel-test-firefox">
        <parameter name="browser" value="firefox"/>
        <classes>
            <class name="tests.ParallelTest"/>
        </classes>
    </test>
    <test name="parallel-test-chrome">
        <parameter name="browser" value="chrome"/>
        <classes>
            <class name="tests.ParallelTest"/>
        </classes>
    </test>
</suite>

Я читал, что создание экземпляра одного драйвера в каждом тесте является наиболее приемлемым. Проблема заключается в том, что тест Firefox запускается последовательно, в то время как тест Chrome выплевывает все точки данных в качестве тестовых случаев, пытается открыть множество экземпляров браузера, а затем все заканчивается неудачей. Мои тесты будут иметь 10-25 или 300-500 точек данных (циклический переход между клиентами или клиентами х продуктов).

Каков наилучший способ настройки драйвера, поставщика данных и тестового прогона для достижения наилучшего параллелизма в выполнении тестов?

2 ответа

Решение

У меня был такой же опыт с dataProvider. В моем случае я использовал атрибут dataProvider (parallel=true). Есть два решения вашей проблемы.

  1. Используйте dataProvider и в тестовом классе и используйте фабричную аннотацию для вашего конструктора. В атрибуте фабричной аннотации используйте dataProvider="Имя вашего dataProvider". В testng.xml вместо параллельных = методов используйте параллельные = экземпляры.

    Недостаток вышеуказанного подхода заключается в том, что при получении отчета; может быть, это пожарная безопасность, тестовый отчет Eclipse или reportNG, вы не видите параметры, переданные заранее. Чтобы преодолеть это, вы можете использовать следующий подход.

  2. Создайте класс фабрики и создайте экземпляр своего тестового класса в методе фабрики, используя цикл for. (Начните цикл с 0.) В тестовом классе определите конструктор, который получает параметр из фабричного класса. Определите dataProvider в этом тестовом классе, который может использовать параметр (точку данных), полученный в конструкторе. Определите BeforeMethod или BeforeClass, которые могут использовать этот параметр или точку данных, и ваши методы тестирования должны иметь атрибут "dataProvider", указывающий на желаемый dataProvider. Опять же, в testng.xml используйте параллельные = "экземпляры".

    Также используйте блок try/catch для создания экземпляра объекта драйвера и закрытия браузера. Это поможет вам избежать пропусков из-за сбоя setUp метода tearDown.

Вам не нужно использовать Фабрику. На вашем месте я бы вызвал этот код в методе dataprovider:

driver = getBrowser(browser);

Затем верните экземпляры драйвера в виде 2-го столбца аргументов в метод теста. Это позволяет поставщику данных создавать экземпляры браузера. Чтобы улучшить это, вы могли бы вместо этого использовать шаблон проектирования компоновщика в форме класса DriverHelper, который мог бы заменить метод getBrowser способом генерации гораздо более конкретной конфигурации драйвера перед передачей экземпляра драйвера в тестовый метод.

ПРИМЕЧАНИЕ. Имейте в виду, что если вы когда-нибудь захотите использовать Spring для загрузки драйверов в будущем, этот метод не будет работать вообще. На самом деле вы вообще не сможете использовать DataProvider. Но если вы не используете Spring, я бы сказал, что это самый элегантный способ сделать это.

Другие вопросы по тегам