How to create a correct parallel selenium execution using @BeforeSuite and each @Test are in a separate class with TestNG?

眉间皱痕 提交于 2020-05-17 07:31:49

问题


I trying to make a test design using Selenium and TestNG, I put each @Test in a separate class, and using once @BeforeSuite & @AfterSuite for all classes, the reason is:

  1. The code is easy to maintain
  2. Data Driven, in order to be able to choose which classes to run through the xml file.

Then what I think is how I only login once and the session can be used by all subsequent tests, what I've done so far is:

Base class:

public class Base {
    protected static WebDriver driver;

    @BeforeSuite
    public void setup() {
        System.setProperty("webdriver.chrome.driver", "/Users/.../chromedriver");
        driver = new ChromeDriver();
    }

    @AfterSuite
    public void tearDown() {
        driver.quit();
    }
}

LoginApps class:

public class LoginApps extends Base{
    @Test(groups= {"logintest"})
    @Parameters({"data"})
    public void loginApps(String data) {
        driver.get("https://TheUrl.com/");
        //some code here
    }
}

Case1 class:

public class Case1 extends Base{
    @Test(dependsOnGroups= {"logintest"})
    @Parameters({"data"})
    public void case1(String data) {
        driver.get("https://TheUrl.com/");
        //some code here
    }
}

Note : The above code fine work if it is run with single <test> in suite.

The problem is if it is run parallel like the following xml configuration.

testng.xml:

<suite name="SuiteTest" parallel="tests" thread-count="2">
    <test name="Test1">
        <parameter name="data" value="data1"></parameter>
        <classes>  
            <class name="com.main.LoginApps"/>
            <class name="com.main.Case1"/>
            .....
            More class
        </classes>
    </test>
    <test name="Test2">
        <parameter name="data" value="data2"></parameter>
        <classes>
            <class name="com.main.LoginApps"/>
            <class name="com.main.Case1"/>
            .....
            More class
        </classes>
    </test>
</suite>

The code runs by creating driver instance just once, and the both <test> runs overlapping in the same session. I think this is because of the way I declare driver as static in the Base class. But if I remove the static, it will make matters worse, still creating driver instance just once and the code only run the first @Test (in this case only LoginApps), all subsequent tests will get a NullPointerException exception.

I use TestNG v7.0.0 with Maven :

<dependency>
    <groupId>org.testng</groupId>
    <artifactId>testng</artifactId>
    <version>7.0.0</version>
    <scope>compile</scope>
</dependency>

To run the design that I imagined in parallel, how I can fix it?


回答1:


Create driver with thread safety to ensure both times driver session is unique.

public class ThreadLocalDriver {

    private static ThreadLocal<WebDriver> threadLocalDriver = new ThreadLocal<>();

    public synchronized static void setTLDriver(WebDriver driver) {
        threadLocalDriver.set(driver);
    }

    public synchronized static WebDriver getTLDriver() {
        return threadLocalDriver.get();
    }
}

public class BaseClass {
    @BeforeMethod
    public void setup (String deviceName, String platformVersion) throws IOException {
        DesiredCapabilities caps = new DesiredCapabilities();
        // Add caps here    
        ThreadLocalDriver.setTLDriver(new ChromeDriver(caps));
    }

    @AfterMethod
    public synchronized void teardown(){
        ThreadLocalDriver.getTLDriver().quit();
    }
}


来源:https://stackoverflow.com/questions/61409468/how-to-create-a-correct-parallel-selenium-execution-using-beforesuite-and-each

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!