Параллельный DataProvider TestNG во вкладках

Я новичок в использовании TestNG и программирования на Java в целом, и у меня есть вопрос относительно выполнения тестов с dataprovider в параллельном режиме,

чтобы запускать тестовые примеры поставщика данных на нескольких вкладках в одном хромированном окне вместо многих окон, я использовал селен 4, который позволяет открывать и переключаться на новую вкладку, используя следующий код

driver.switchTo().newWindow(WindowType.TAB);

Итак, я написал этот код, который успешно запускает тестовые случаи в последовательном режиме, но когда я запускаю его в параллельном режиме, он реализует каждую строку отдельно, прежде чем перейти к другой строке,

следовательно, он открывает 3 вкладки одновременно, затем он открывает ссылку на последней вкладке 3 раза и, наконец, пытается выполнить 3 поиска одновременно и, следовательно, не может их выполнить.

В результате я обнаружил, что testNG создает единый веб-драйвер для управления всеми вкладками, что логично привести к сбою тестов в параллельном режиме.

https://imgur.com/fWHY5pt

Это код:

package com.mycompany.app;

import org.openqa.selenium.By;
import org.openqa.selenium.Keys;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WindowType;
import org.openqa.selenium.chrome.ChromeDriver;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;

public class testTab {

    WebDriver driver;

    @BeforeTest
    public void beforeTest() {
        System.setProperty("webdriver.chrome.driver", "C:\\Browsers drivers\\chromedriver.exe");
        driver = new ChromeDriver();
    }

    @BeforeMethod
    public void newTab() {
        driver.switchTo().newWindow(WindowType.TAB);
    }

    @Test(dataProvider = "getData")
    public void testAmazon1(String search_word) {
        driver.get("https://www.google.com/");
        driver.findElement(By.xpath("//input[@name='q']")).sendKeys(search_word + (Keys.RETURN));
    }

    @DataProvider(parallel=true)
    public Object[][] getData() {
        Object[][] data = new Object[3][1];
        data[0][0] = "bihi";
        data[1][0] = "boutfounast";
        data[2][0] = "hmad l9rran";
        return data;
    }

}

Это XML-файл

<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="My Sample Suite" parallel="methods" thread-count="3">


<test name="Amazon test">
    <classes>
        <class name="com.mycompany.app.testTab"></class>  
    </classes>
</test>


</suite>

Есть ли способ создать веб-драйвер для каждого теста? Прошу прощения за неточность и спасибо за ответы.


person moad hamouch    schedule 19.01.2020    source источник


Ответы (2)


Есть несколько проблем с вашим тестовым кодом.

  • У вас есть элемент данных уровня класса WebDriver, который используется всеми методами @Test в одном и том же тестовом классе, а также во всех итерациях метода @Test, управляемого данными.
  • Вы используете метод @BeforeTest для инициализации своего экземпляра веб-драйвера, что означает, что он инициализируется ТОЛЬКО один раз для каждого тега <test>, и если есть какие-либо другие нижестоящие тестовые классы, которые расширяют этот тестовый класс, они столкнутся с NullPointerException.

Есть ли способ создать веб-драйвер для каждого теста?

Да вполне возможно. Вам нужно работать с ThreadLocal, где вы создаете экземпляр WebDriver либо в прослушивателе TestNG (или) в методе @BeforeMethod (поскольку @BeforeMethod гарантированно работает в том же потоке, что и @Test)

Вот как вы это делаете.

Сначала создайте фабрику драйверов, которая может производить для вас WebDriver экземпляров.

import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.ie.InternetExplorerDriver;

class LocalDriverFactory {
    static WebDriver createInstance(String browserName) {
        WebDriver driver = null;
        if (browserName.toLowerCase().contains("firefox")) {
            driver = new FirefoxDriver();
            return driver;
        }
        if (browserName.toLowerCase().contains("internet")) {
            driver = new InternetExplorerDriver();
            return driver;
        }
        if (browserName.toLowerCase().contains("chrome")) {
            driver = new ChromeDriver();
            return driver;
        }
        return driver;
    }
}

Теперь давайте создадим диспетчер драйверов, который действует как средство взаимодействия с созданным веб-драйвером.

import org.openqa.selenium.WebDriver;

public class LocalDriverManager {
  private static ThreadLocal<WebDriver> webDriver = new ThreadLocal<>();

  public static WebDriver getDriver() {
    return webDriver.get();
  }

  static void setWebDriver(WebDriver driver) {
    webDriver.set(driver);
  }

  public static void cleanupDriver() {
    webDriver.get().quit();
    webDriver.remove();
  }
}

Вот как теперь будет выглядеть ваш тестовый класс

import org.openqa.selenium.By;
import org.openqa.selenium.Keys;
import org.openqa.selenium.WebDriver;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;

public class TestTab {

  @BeforeMethod
  public void beforeMethod() {
    LocalDriverManager.setWebDriver(LocalDriverFactory.createInstance("chrome"));
  }

  @Test(dataProvider = "dp")
  public void testMethod(String searchWord) {
    WebDriver driver = LocalDriverManager.getDriver();
    driver.get("https://www.google.com/");
    driver.findElement(By.xpath("//input[@name='q']")).sendKeys(searchWord + (Keys.RETURN));
  }

  @DataProvider(name = "dp", parallel = true)
  public Object[][] getData() {
    return new Object[][] {{"bihi"}, {"boutfounast"}, {"hmad l9rran"}};
  }

  @AfterMethod
  public void afterMethod() {
    LocalDriverManager.cleanupDriver();
  }
}

Я создал подробный блог, который объясняет все это. Подробнее об этом можно прочитать здесь

В качестве импровизации я также создал простую библиотеку maven под названием autospawn, которая абстрагирует все эти экземпляры браузера и очищает от вас логику и позволяет вам работать с веб-драйвером, используя пользовательскую аннотацию.

Вы можете получить больше информации об этом здесь: https://github.com/RationaleEmotions/autospawn

person Krishnan Mahadevan    schedule 22.01.2020
comment
большое спасибо, это очень эффективный способ выполнить параллельный тест, он действительно работает. но мне все еще нужно сгруппировать все тесты на нескольких вкладках в 1 окне Chrome, я попытался добавить этот метод в LocalDriverManager, public static WebDriver getTab() { return webDriver.get().switchTo().newWindow(WindowType.TAB); }, но он открывает новое окно и создает новую вкладку в каждом окне, а затем выполняется тест. если вы можете помочь, я был бы очень благодарен. - person moad hamouch; 23.01.2020
comment
@moadhamouch - Насколько мне известно, операции, которые вы выполняете в экземпляре WebDriver, НЕ являются ThreadSafe. Таким образом, вы не можете иметь 3 потока, пытающихся открыть 3 вкладки в одном и том же экземпляре Webdriver и одновременно выполнять разные действия. Вам нужно будет использовать 3 разных экземпляра Webdriver, а затем работать с ними. Технически это эквивалентно работе с тремя вкладками в одном браузере вручную. Вкладка или новое окно — это просто пользовательский опыт, который дает браузер. С точки зрения автоматизации это всегда равно 3 новым окнам. - person Krishnan Mahadevan; 24.01.2020
comment
@moadhamouch - Пожалуйста, примите мой ответ, если он решит ваш вопрос. - person Krishnan Mahadevan; 24.01.2020
comment
Я хочу автоматизировать веб-страницу Amazon, поэтому мне нужно оставаться в одном окне, чтобы избежать повторного входа в систему для каждого набора данных, на самом деле он уже существует, пожалуйста, посмотрите это видео; youtu.be/TTnrUkQhuFo?t=1833, возможно, они использовали селеновую сетку или какие-то другие продвинутые фреймворки. - person moad hamouch; 24.01.2020

Вам нужно использовать dataproviderthreadcount. Значения thread-count не требуются. Подробнее см. здесь.

Вы можете использовать Tesng.xml, как указано ниже:

<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="My Sample Suite" parallel="methods" data-provider-thread-count="3">


<test name="Amazon test">
    <classes>
        <class name="com.mycompany.app.testTab"></class>  
    </classes>
</test>


</suite>
person Muzzamil    schedule 19.01.2020
comment
К сожалению, это не решает проблему, выдает сообщение об ошибке org.openqa.selenium.StaleElementReferenceException: ссылка на устаревший элемент: элемент не прикреплен к документу страницы - person moad hamouch; 19.01.2020
comment
Эта ошибка не связана с этой проблемой. Это была проблема, основанная на конфигурации, которая была решена. Эта проблема связана с тем, что элемент не привязан к DOM, поэтому вам нужно использовать явное ожидание загрузки элемента. - person Muzzamil; 19.01.2020
comment
Вы можете увидеть решение здесь для устаревшего элемента. stackoverflow.com/questions/12967541/ - person Muzzamil; 19.01.2020
comment
Если ваша старая проблема решена, не забудьте принять ее как ответ и проголосовать, чтобы помочь сообществу SO. Это поможет людям с подобной проблемой в будущем - person Muzzamil; 19.01.2020
comment
Привет, может быть, я был недостаточно точен в своем вопросе, я просто изменил его и переописал проблему, пожалуйста, пересмотрите его и дайте мне свое мнение, если вы можете мне помочь, большое спасибо. - person moad hamouch; 20.01.2020
comment
Как вы упоминали ранее, вы получали пустую вкладку и неподвижное изображение для старой проблемы. Для нового номера вы поднимаете новый вопрос. - person Muzzamil; 20.01.2020
comment
Речь не идет об одном драйвере, если в нем вы не сможете запустить 4 вкладки. Количество потоков = 3 справится с этой задачей - person Muzzamil; 20.01.2020