Как вы запускаете параллельное выполнение тестов? Что такое ThreadLocal?qa-54

Способы параллельного запуска тестов

1. Использование TestNG

Конфигурация через testng.xml:

<suite name="ParallelSuite" parallel="tests" thread-count="3">
    <test name="ChromeTest">
        <parameter name="browser" value="chrome"/>
        <classes>
            <class name="com.tests.LoginTest"/>
        </classes>
    </test>
    <test name="FirefoxTest">
        <parameter name="browser" value="firefox"/>
        <classes>
            <class name="com.tests.LoginTest"/>
        </classes>
    </test>
</suite>

Параметры parallel:

  • tests - параллельные тесты
  • classes - параллельные классы
  • methods - параллельные методы

2. Использование JUnit 5

Аннотация для параллельного выполнения:

import org.junit.jupiter.api.parallel.Execution;
import org.junit.jupiter.api.parallel.ExecutionMode;

@Execution(ExecutionMode.CONCURRENT)
public class ParallelTest {
    // тестовые методы
}

3. Selenium Grid

Запуск тестов на разных нодах:

DesiredCapabilities chromeCap = new DesiredCapabilities();
chromeCap.setBrowserName("chrome");
DesiredCapabilities firefoxCap = new DesiredCapabilities();
firefoxCap.setBrowserName("firefox");

// Параллельный запуск через Thread
new Thread(() -> {
    WebDriver driver = new RemoteWebDriver(new URL("http://grid-hub:4444"), chromeCap);
    // тесты для Chrome
}).start();

new Thread(() -> {
    WebDriver driver = new RemoteWebDriver(new URL("http://grid-hub:4444"), firefoxCap);
    // тесты для Firefox
}).start();

Что такое ThreadLocal?

ThreadLocal - это класс в Java, который позволяет создавать переменные, доступные только для текущего потока. Каждый поток имеет свою независимую копию переменной.

Применение в Selenium

Проблема: При параллельном выполнении общий WebDriver может вызвать конфликты.

Решение: ThreadLocal для изоляции драйвера между потоками.

Реализация:

public class DriverManager {
    private static ThreadLocal<WebDriver> driver = new ThreadLocal<>();

    public static WebDriver getDriver() {
        return driver.get();
    }

    public static void setDriver(WebDriver webDriver) {
        driver.set(webDriver);
    }

    public static void quitDriver() {
        if (driver.get() != null) {
            driver.get().quit();
            driver.remove();
        }
    }
}

Пример использования

Инициализация драйвера:

@BeforeMethod
public void setup(String browser) {
    WebDriver driver;
    if(browser.equals("chrome")) {
        driver = new ChromeDriver();
    } else {
        driver = new FirefoxDriver();
    }
    DriverManager.setDriver(driver);
}

В тестах:

@Test
public void testLogin() {
    WebDriver driver = DriverManager.getDriver();
    driver.get("https://example.com");
    // тестовые действия
}

Очистка:

@AfterMethod
public void tearDown() {
    DriverManager.quitDriver();
}

Преимущества ThreadLocal

  1. Потокобезопасность - каждый поток работает со своей копией
  2. Изоляция данных - нет конфликтов между потоками
  3. Гибкость - можно хранить любые объекты
  4. Простота очистки - автоматическое удаление при завершении потока

Проблемы параллельного выполнения

  1. Общие ресурсы:

    • Файлы
    • БД
    • Внешние сервисы
  2. Способы решения:

    • Использование ThreadLocal
    • Синхронизация доступа
    • Создание отдельных тестовых данных для каждого потока

Оптимизация параллельного выполнения

  1. Балансировка нагрузки:

    • Долгие тесты распределять равномерно
    • Учитывать требования к ресурсам
  2. Настройка thread-count:

    • Оптимальное число = количество ядер CPU × 1.5
    • Для UI-тестов лучше меньше потоков
  3. Логирование:

    • Добавлять идентификатор потока в логи
    System.out.println("Thread ID: " + Thread.currentThread().getId());
    

Резюмируем

  • Параллельное выполнение ускоряет прогон тестов через TestNG, JUnit 5 или Selenium Grid
  • ThreadLocal решает проблему разделяемых ресурсов между потоками
  • Для WebDriver рекомендуется использовать ThreadLocal для изоляции экземпляров
  • Важно правильно настраивать количество потоков и балансировать нагрузку
  • При работе с параллельными тестами учитывайте состояние общих ресурсов

Профессиональный совет: Для сложных сценариев комбинируйте параллельное выполнение методов/классов с распределенным запуском через Selenium Grid. Всегда проверяйте тесты на race condition при увеличении количества потоков.