Фон : теперь используется java JUnit4, желающий перейти на JUnit5 или TestNG.
Текущее состояние : Наличие более 100 тестов Selenium.Большинство из них повторяются через @RunWith (Parameterized.class) в Junit4.(Т.е. создание нескольких экземпляров тестового класса на основе предоставленного набора параметров, как правило, комбинаций типа браузера и идентификатора пользователя.) Совместное использование ограниченного набора примерно из 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 ().Это создает много потоков, и большинство из них продолжают ждать друг друга.Я бы предпочел выстроить все тесты с использованием одного и того же пользователя в одном потоке и минимизировать время ожидания.