Параллельное выполнение теста выдает исключение, когда для параметра Параллельное установлено значение true в DataProvider - TestNG - PullRequest
0 голосов
/ 20 января 2020

Параллельное выполнение теста выдает следующее исключение, когда параллельный = true для DataProvider. Два экземпляра браузера будут запущены в разных потоках, но только один экземпляр браузера будет успешно выполнен, а другой застревает при попытке найти элемент и генерировать исключение. Пожалуйста, как я могу заставить тест успешно выполняться, когда параллельный = true в поставщике данных. Я что-то упустил, может быть, экземпляр WebDriver в BasePage. Пожалуйста помоги. Спасибо.

[PoolService-1] 15:44:06,447 INFO  [Default test] Close driver
PASSED: loginTest("unresticteduser@gmail.com", "123456")
FAILED: loginTest("resticteduser@gmail.com", "123456")

WARNING: WebDriverException thrown by findElement(By.xpath: //button[contains(text(), 'NO THANKS')])
org.openqa.selenium.WebDriverException: org.apache.http.conn.HttpHostConnectException: Connect to 
localhost:8478 [localhost/127.0.0.1, localhost/0:0:0:0:0:0:0:1] failed: Connection refused: connect

Когда параметр параллелизма = false для поставщика данных, тест будет открывать один экземпляр браузера за раз, когда данные передаются в тест и успешно выполняются.

PASSED: loginTest("unresticteduser@gmail.com", "123456")
PASSED: loginTest("resticteduser@gmail.com", "123456")

Вот код, который я написал:

1) BrowserFactory

public class BrowserDriverFactory {

private ThreadLocal<WebDriver> driver = new ThreadLocal<WebDriver>();
private String browser;
private Logger log;

public BrowserDriverFactory(String browser, Logger log) {
    this.browser = browser.toLowerCase();
    this.log = log;
}

public WebDriver createDriver() {
    // Create driver
    log.info("Create driver: " + browser);

    if(browser.equals("chrome")) {
        System.setProperty("webdriver.chrome.driver", "src/main/resources/chromedriver.exe");
        driver.set(new ChromeDriver());
    }
    else if(browser.equals("firefox")) {
        System.setProperty("webdriver.gecko.driver", "src/main/resources/geckodriver.exe");
        driver.set(new FirefoxDriver());
    }
    else {
        System.out.println("Do not know how to start: " + browser + ", starting chrome.");
        System.setProperty("webdriver.chrome.driver", "src/main/resources/chromedriver.exe");
        driver.set(new ChromeDriver());
    }

    return driver.get();
 }

}

2) BaseTest

public class BaseTest {

protected WebDriver driver;
public WebDriverWait wait;
protected Logger log;
protected FirefoxProfile profile;
protected String url = "http://www.qaclickacademy.com/";

protected String testSuiteName;
protected String testName;
protected String testMethodName;

@BeforeMethod(alwaysRun = false)
public void setUp(Method method, ITestContext ctx) {
    String testName = ctx.getCurrentXmlTest().getName();
    log = LogManager.getLogger(testName);

    BrowserDriverFactory factory = new BrowserDriverFactory(config.getBrowser(), log);
    driver = factory.createDriver();
    driver.get(url);

    profile=new FirefoxProfile();
    // Set preferences for file type 
    profile.setPreference("browser.helperApps.neverAsk.openFile", "application/octet-stream");

    driver.manage().window().maximize();
    wait = new WebDriverWait(driver, 5);

    this.testSuiteName = ctx.getSuite().getName();
    this.testName = testName;
    this.testMethodName = method.getName();
}

    @AfterMethod(alwaysRun = true)
    public void tearDown(ITestResult result) {

        if(result.getStatus()==ITestResult.FAILURE) {
        //capture screenshot
        }

        log.info("Close driver");
        // Close browser
        driver.quit();
    }
}

3) DataProvider

 @DataProvider(name="SearchProvider", parallel=true)
    public Object[][] getDataFromDataprovider(){
    return new Object[][] 
        {
            { "unresticteduser@gmail.com", "123456" },
            { "resticteduser@gmail.com", "123456" }
        };

    }

4) BasePage

 public class BasePage { 
    protected WebDriver driver;
    public WebDriverWait wait;
    protected Logger log;

    public BasePage(WebDriver driver, Logger log) {
        this.driver = driver;
        this.log = log;
        wait = new WebDriverWait(driver, 5);
    }

    protected void sleep(long millis) {
            try {
                Thread.sleep(millis);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
    }

     protected void clickStallElement(By locator) {

     try {
        waitForVisibilityOf(locator, 30);
        findElement(locator).click();
     }
     catch(org.openqa.selenium.StaleElementReferenceException ex)
     {
        waitForVisibilityOf(locator, 30);
        findElement(locator).click();
      }
    }


    /** Open page with given URL */
    protected void openUrl(String url) {
        driver.get(url);
    }

    /** Find element using given locator */
    protected WebElement findElement(By locator) {
        return driver.findElement(locator);
    }

    /** Find all elements using given locator */
    protected List<WebElement> findAllElements(By locator) {
        return driver.findElements(locator);
    }

    /** Click on element with given locator when its visible */
    protected void click(By locator) {
        waitForVisibilityOf(locator, 30);
        findElement(locator).click();
        log.info("Clicked WebElement");
    }

    ...

}

5) BaseTest

public class SignInPageTest extends BaseTest {


    @Test(dataProvider = "SearchProvider", dataProviderClass = DBDataProvider.class)
    public void loginTest(String username, String password) {

        System.err.println("Running Test=> " + this + " -> on thread [" + Thread.currentThread().getId() + "]");

        log.info("Starting LogInTest #  for " + username);

        ClickAcadamyLandingPage home = new ClickAcadamyLandingPage(driver, log);
        home.openPage();

        home.closeNewsLetterPopup();

        // click login
        ClickAcadamyLoginPage loginPage = new ClickAcadamyLoginPage(driver, log);
        loginPage = home.clickLoginBtn();

        loginPage.enterEmailAddress(username);

        loginPage.enterPassword(password);

        ClickAcadamyDashboard dashboard = loginPage.clickLogin();
        dashboard.clickLogout();

    }


 }

6) testng. xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="Suite" data-provider-thread-count = "2" thread-count="2" verbose="1" parallel="tests">

   <listeners>
     <listener class-name="com.paralleltest.basetest.TestListener"/>
   </listeners>

   <test name="loginTest">
    <classes>
      <class name="com.paralleltest.SignInPageTest"/>  
    </classes>
   </test> 

 </suite> 

1 Ответ

1 голос
/ 21 января 2020

Проблема заключается в вашем тестовом коде. Ваши экземпляры веб-драйвера становятся общими для всех методов тестирования, когда вы выполняете тесты параллельно и работают от поставщика данных.

Вот фиксированная версия ваших BaseTest и BrowserDriverFactory для обеспечения безопасности потоков.

import java.lang.reflect.Method;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxProfile;
import org.openqa.selenium.support.ui.WebDriverWait;
import org.testng.ITestContext;
import org.testng.ITestResult;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;

public class BaseTest {
  private static final ThreadLocal<WebDriver> drivers = new ThreadLocal<>();
  public WebDriverWait wait;
  protected FirefoxProfile profile;
  protected String url = "http://www.qaclickacademy.com/";

  protected String testSuiteName;
  protected String testName;
  protected String testMethodName;

  public WebDriver getDriver() {
    return drivers.get();
  }

  @BeforeMethod()
  public void setUp(Method method, ITestContext ctx) {
    String testName = ctx.getCurrentXmlTest().getName();

    WebDriver driver = BrowserDriverFactory.createDriver("firefox");
    drivers.set(driver);
    driver.get(url);

    driver.manage().window().maximize();
    wait = new WebDriverWait(driver, 5);

    this.testSuiteName = ctx.getSuite().getName();
    this.testName = testName;
    this.testMethodName = method.getName();
  }

  @AfterMethod(alwaysRun = true)
  public void tearDown(ITestResult result) {
    getDriver().quit();
    drivers.remove();
  }
}

BrowserDriverFactory. java

import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.firefox.FirefoxOptions;
import org.openqa.selenium.firefox.FirefoxProfile;

public class BrowserDriverFactory {

  public static WebDriver createDriver(String browser) {
    System.err.println("Create driver: " + browser);

    if (browser.equals("chrome")) {
      System.setProperty("webdriver.chrome.driver", "src/main/resources/chromedriver.exe");
      return new ChromeDriver();
    } else if (browser.equals("firefox")) {
      System.setProperty("webdriver.gecko.driver", "src/main/resources/geckodriver.exe");
      FirefoxOptions options = new FirefoxOptions();
      FirefoxProfile profile = new FirefoxProfile();
      profile.setPreference("browser.helperApps.neverAsk.openFile", "application/octet-stream");
      options.setProfile(profile);
      return new FirefoxDriver(options);
    }
    System.out.println("Do not know how to start: " + browser + ", starting chrome.");
    System.setProperty("webdriver.chrome.driver", "src/main/resources/chromedriver.exe");
    return new ChromeDriver();
  }
}

Теперь во всех методах тестирования классов тестирования, которые расширяют BaseTest всякий раз, когда вам необходим доступ к объекту драйвера, вы бы получите его, вызвав метод getDriver().

Вы можете найти полное объяснение пределов и еще несколько объяснений по этому поводу в этом моем блоге: https://rationaleemotions.com/parallel_webdriver_executions_using_testng/

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

Взгляните на https://github.com/rationaleEmotions/autospawn

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...