Понял, что слишком абстрактный получился вопрос.
Вот полная детализация проблемы.
Бекграунд
Занимаюсь параллелизацией тестов. В тестах активно использую TestNG DataProvider/DataSupplier. Параллельность тестов настроена на уровне методов. Тесты, для которых указан DataSupplier тоже параллелятся с помощью атрибута runInParallel=true. Браузеры для потоков храню в переменной ThreadLocal<>. Билды запускаются на TeamCity. Одним из параметров билда является опция запуска параллельно или нет. Эта опция передаётся в Maven как System property.
Проблематика
Зависимо от упомянутой выше опции в @BeforeSuite выполняется следующий код
if(isParallel()) {
testContext.getSuite().getXmlSuite().setParallel(XmlSuite.ParallelMode.METHODS);
testContext.getSuite().getXmlSuite().setThreadCount(TestConfig.getThreadCount());
testContext.getSuite().getXmlSuite().setDataProviderThreadCount(TestConfig.getThreadCount());
}
else {
testContext.getSuite().getXmlSuite().setParallel(XmlSuite.ParallelMode.NONE);
testContext.getSuite().getXmlSuite().setThreadCount(1);
testContext.getSuite().getXmlSuite().setDataProviderThreadCount(1);
}
Браузеры запускаю в @BeforeMethod
public void beforeTestMethod() {
WebBrowserManager.startWebBrowser();
}
Класс, отвечающий за управление браузерами (PS. WebBrowser - это врапер над WebDriver для удобства работы)
public class WebBrowserManager {
private final static ThreadLocal<WebBrowser> webBrowser = new ThreadLocal<>();
public static WebBrowser getWebBrowser() {
return webBrowser.get();
}
public static void startWebBrowser() {
if (getWebBrowser() == null) {
final WebBrowser instance = WebBrowserFactory.createInstance(TestConfig.getBrowser());
webBrowser.set(instance);
}
}
public static void closeWebBrowser() {
final WebBrowser webBrowser = getWebBrowser();
if(webBrowser != null) {
webBrowser.close();
}
webBrowser.remove();
}
}
Теперь собственно о проблеме.
Если с TeamCity приходит команда запускать тесты НЕ параллельно, то целесообразно не открывать для каждого теста новый браузер, а открыть его в первом тесте и переиспользовать в остальных.
Предполагалось, что это решится использование ThreadLocal переменной, которая для потока будет хранить браузер и отдавать его по требованию. Но вот, что обнаружилось.
Если Suite.ParallelMode = NONE (т.е. не параллелить тесты), то все @Test и @Before и @After выполняются в одном потоке. Исключением из этого стало использование runInParallel=true для DataSupplier. В этом случае для такого теста используется отдельный поток, что приводит к запуску нового браузера. При runInParallel=false всё ок и тесты с DataSupplier выполняются в том же потоке и в том же браузере, что и остальные.
DataSupplier -ров использую много по всему коду тестов. Как им всем в @BeforeSuite проставить runInParallel=false не нашёл.
Предположительные пути решения проблемы
Вариант 1:
В классе WebBrowserManager вводить дополнительную переменную, в которой будет хранится и отдаваться браузер в случае НЕ параллельного запуска тестов. Переменная будет одна для всех потоков. Как по мне выглядит немного кастыльно
Вариант 2:
Искать пути переопределения runInParallel.
Остановился пока на 2-ом, но решения не нашёл.