如何通过并行执行隔离 Cucumber 场景的 Webdriver 会话?
How to isolate Webdriver sessions for Cucumber scenarios with parallel execution?
当前设置是 maven 并行执行 cucumber,执行 webdriver,执行 chromedriver 来测试我的软件:
专家:
<project>
...
<build>
...
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0-M3</version>
<configuration>
<parallel>both</parallel>
<threadCount>3</threadCount>
<runOrder>random</runOrder>
</configuration>
</plugin>
</plugins>
</build>
</project>
小黄瓜:
Function: Example
Scenario: Example 1
When I do something
Then I expect something
Scenario: Example 2
When I do some other thing
Then I expect some other thing
Cucumber-JVM / Webdriver-JVM / Chromedriver:
@Before
public void setUp() {
WebDriverManager.chromedriver().setup();
ChromeOptions options = new ChromeOptions();
options.addArguments("--window-size=1920,1080");
driver = new ChromeDriver(options);
driver.navigate().to(baseUrl);
}
@After
public void tearDown() {
if (driver != null) {
driver.quit();
}
}
原则上,这可以正常工作。测试以随机顺序并行执行,如 maven pom 中所述,setUp()
在每个场景之前调用,tearDown()
在每个场景之后调用。
然而,ChromeDriver 显然在一个浏览器会话中运行多个测试,因此 Cookie 等在功能和场景之间共享,导致它们无法正确地相互隔离,从而导致 cookie、会话等进一步出现问题。
如何通过 Cucumber-JVM 并行 运行 Webdriver 时正确隔离每个测试用例(ChromeDriver 会话)?
根据 Parallel Tests Execution 文章:
We also need to ensure that to develop tests which can be executed simultaneously, we need to develop tests adhering to some best practices.
They are,
Independent Tests Methods: Tests should be independent of each other.
Usage of thread safe references : Tests should use thread safe variables. For example avoid usage of static references in the tests.
Repeatable : Tests should return always same results for same version of application and test inputs.
您似乎在使用 WebDriverManager and when you call chromedriver()
function it returns the relevant WebDriver instance from the instanceMap which is static and it seems to be the root cause of your problem. It is better to stick to ThreadLocal pattern,这样您就可以确信每个 WebDriver 实例都绝对独立于其他实例。
如果您的资源允许,您可以将 <forkMode>always</forkMode>
行添加到您的 surefire 插件配置中,这样 Maven 将为每个线程创建一个新的 JVM 实例,因此您将不再遭受竞争条件的困扰,但您的测试将开始消耗更多的内存。
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0-M3</version>
<configuration>
<parallel>both</parallel>
<threadCount>3</threadCount>
<runOrder>random</runOrder>
<forkMode>always</forkMode> <!--this should help-->
</configuration>
</plugin>
</plugins>
</build>
当前设置是 maven 并行执行 cucumber,执行 webdriver,执行 chromedriver 来测试我的软件:
专家:
<project>
...
<build>
...
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0-M3</version>
<configuration>
<parallel>both</parallel>
<threadCount>3</threadCount>
<runOrder>random</runOrder>
</configuration>
</plugin>
</plugins>
</build>
</project>
小黄瓜:
Function: Example
Scenario: Example 1
When I do something
Then I expect something
Scenario: Example 2
When I do some other thing
Then I expect some other thing
Cucumber-JVM / Webdriver-JVM / Chromedriver:
@Before
public void setUp() {
WebDriverManager.chromedriver().setup();
ChromeOptions options = new ChromeOptions();
options.addArguments("--window-size=1920,1080");
driver = new ChromeDriver(options);
driver.navigate().to(baseUrl);
}
@After
public void tearDown() {
if (driver != null) {
driver.quit();
}
}
原则上,这可以正常工作。测试以随机顺序并行执行,如 maven pom 中所述,setUp()
在每个场景之前调用,tearDown()
在每个场景之后调用。
然而,ChromeDriver 显然在一个浏览器会话中运行多个测试,因此 Cookie 等在功能和场景之间共享,导致它们无法正确地相互隔离,从而导致 cookie、会话等进一步出现问题。
如何通过 Cucumber-JVM 并行 运行 Webdriver 时正确隔离每个测试用例(ChromeDriver 会话)?
根据 Parallel Tests Execution 文章:
We also need to ensure that to develop tests which can be executed simultaneously, we need to develop tests adhering to some best practices.
They are,
Independent Tests Methods: Tests should be independent of each other.
Usage of thread safe references : Tests should use thread safe variables. For example avoid usage of static references in the tests.
Repeatable : Tests should return always same results for same version of application and test inputs.
您似乎在使用 WebDriverManager and when you call chromedriver()
function it returns the relevant WebDriver instance from the instanceMap which is static and it seems to be the root cause of your problem. It is better to stick to ThreadLocal pattern,这样您就可以确信每个 WebDriver 实例都绝对独立于其他实例。
如果您的资源允许,您可以将 <forkMode>always</forkMode>
行添加到您的 surefire 插件配置中,这样 Maven 将为每个线程创建一个新的 JVM 实例,因此您将不再遭受竞争条件的困扰,但您的测试将开始消耗更多的内存。
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0-M3</version>
<configuration>
<parallel>both</parallel>
<threadCount>3</threadCount>
<runOrder>random</runOrder>
<forkMode>always</forkMode> <!--this should help-->
</configuration>
</plugin>
</plugins>
</build>