【发布时间】:2019-06-06 09:31:49
【问题描述】:
背景:现在使用java JUnit4,愿意迁移到JUnit5或者TestNG。
当前状态:拥有 100 多个 Selenium 测试。其中大部分是通过 Junit4 中的@RunWith(Parameterized.class) 重复的。 (即根据提供的参数集创建测试类的多个实例,通常是浏览器类型 + 用户身份的组合。)共享大约 12 个用户的有限集合。
限制:被测试的应用程序可以防止同一用户同时登录多个地方。因此,如果用户在一个线程中运行的某个测试中登录应用程序,则会导致同一用户在同一时刻在另一个线程中运行的另一个测试中立即注销。
问题:当并行执行的测试无法共享某些资源时,有什么推荐的方法来管理线程安全吗? 或者如何强制那些使用相同资源的测试在同一个线程中执行?
感谢您的想法。
这是迄今为止我使用 TestNG 找到的一些解决方案的简化示例...:
public abstract class BaseTestCase {
protected static ThreadLocal<WebDriver> threadLocalDriver = new ThreadLocal<>();
protected String testUserName;
private static final Set<String> inUse = new HashSet<>();
public BaseTestCase(WebDriver driver, String testUserName) {
threadLocalDriver.set(driver);
this.testUserName = testUserName;
}
private boolean syncedAddUse(@NotNull String key){
synchronized (inUse){
return inUse.add(key);
}
}
private boolean syncedRemoveUse(@NotNull String key){
synchronized (inUse) {
return inUse.remove(key);
}
}
@DataProvider(parallel = true)
public static Object[][] provideTestData() {
//load pairs WebDriver+user from config file. E.g.:
//Chrome + chromeUser
//Chrome + chromeAdmin
//Firefox + firefoxUser
//etc...
}
@BeforeMethod
public void syncPoint() throws InterruptedException {
while( !syncedAddUse(testUserName) ){
//Waiting due the testUserName is already in use at the moment.
Thread.sleep(1000);
}
}
@AfterMethod
public void leaveSyncPoint(){
syncedRemoveUse(testUserName);
}
}
所以我可以有很多测试类,比如:
public class TestA extends BaseTestCase {
@Factory(dataProvider = "provideTestData")
public TestA(WebDriver webDriver, String testUserName) {
super(webDriver, testUserName);
}
public void someTest() {
WebDriver driver = threadLocalDriver.get();
threadLocalDriver.get().navigate().to("http://myPage.example.com");
logintoMyPageWithUser(driver, testUserName);
doSomeStuffOnPage(driver);
logoutUserFromPage(driver);
}
...
}
所有测试都是通过 testNG.xml 启动的,如下所示:
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="sample suite" verbose="1" parallel="instances" thread-count="20" data-provider-thread-count="10">
<test name="sample test" >
<packages>
<package name="com.path_to_package_with_example" />
</packages>
</test>
</suite>
这个解决方案很有效。但是,我讨厌那里的 Thread.sleep() 。 它创建了许多线程,其中大多数线程一直在相互等待。 我更愿意将使用同一用户的所有测试排列到同一线程并最大限度地减少等待时间。
【问题讨论】:
-
您有可以帮助分享并添加到您的问题中的示例,可以更清楚地解释您的问题吗?
标签: java multithreading testng junit5 parallel-testing