How to ? Parallel DataProvider + WebDriver instance

Привет всем. Столкнулся с проблемой след. характера, хочу услышать Ваши подсказки или мнения по поводу этой задачи.

Значит есть классический тест фреймворк Java+TestNG+ Maven.
Есть BaseTest в котором определена инициализация драйвера + капабилитиз, и который собственно содержит не статическое поле ВебДрайвера.
От BaseTest наследуется еще один AppTest, в котором зашиты все @Before + @After методы и те, которые могут использоваться во всех тестах.
Каждый тест наследуется от AppTest. При запуске - дергае.ся @BeforeMethod + @AfteMethod супер класса и все отлично работает.

Приложение работает так, что в нем есть Клиенты и наборы тестов для каждого клиента практически идентичны, но все же их нужно тестировать все, так как бекенд местами общий, а местами нет. Для того чтоб можно было запускать тесты на 1ом/нескольких/всех клиентах - я реализовал класс Provider, который возвращает Object[][] (как все TestNG дата провайдеры) и по сути возвращает в зависимости от параметризации с которой запущены тесты - только тот набор провайдеров , который мне нужен.

При запуске в 1н поток все отлично работает, в зависимости от параметров - (скажем я указал 3 клиента) - класс провайдер возвращает Object[3][sizeOfparams] , а значит 3жды прогоняется - на каждом клиенте со своим набором тестовых данных.

Проблема возникла при параллельном запуске тестов на многих дата провайдерах.
Суть в чем: Перед каждым Дата Провайдером должен прогнаться @BeforeMethod который инициализирует драйвер - это работает. Но так как Обьект AppTest класса для всех этих провайдеров только один - значит они все ссылаются на один обьект драйвера и соответственно ничего не работает (5 потоков управляет 1ним драйвером одновременно, все валятся, что логично). + открывается еще 4 инстанса драйвера ( = 4 браузера), которыми никто не управляет вообще.

Проблема в принципе ясна, для наглядности вот коротенький пример:

MAIN CONSTRUCTOR
before14
before13
before15
test14   param 2
test15   param 3
test13   param 1
after14
after13
after15

Отсюда видно, что @BeforeMethod и @AfterMethod ранятся перед/после каждого теста, что ОК, но супер класс имеет 1н инстанс для этого класса, а значит 1н обьект драйвера на все потоки.

Подскажите, как можно решить эту проблему? Думаю попытаться сделать какой-то пул драйверов (тем более, что уже есть такая реализация для пользователей), тоестьбудет храниться в базовом классе не 1н драйвер, а обьект. в котором будет несколько драйверов и потоки будут по очереди брать свободные драйвера, если слетит - перезапускать их.

В C# есть такая штука как ThreadLocal. Она позволяет для каждого потока хранить свой уникальный инстанс драйвера.

Посмотрите что-то похожее для Java. Уверен, что должно быть такое же.

Я бы создал что-то вроде менеджера для Драйвера:

internal class DriverManager
  {
    private static readonly ThreadLocal<IWebDriver> _driver;

    static DriverManager()
    {
      _driver = new ThreadLocal<IWebDriver>();
    }

    public static IWebDriver Driver
    {
      get
      {
        return _driver.Value;
      }
      set
      {
        _driver.Value = value;
      }
    }
  }

И потом в BeforeMethod сетить значение драйвера.

      [OneTimeSetUp]
      public void Setup()
      {
        DriverManager.Driver = new FirefoxDriver();
      }

А дальше уже можно использовать в тестах его:

DriverManager.Driver.Navigate().GoToUrl("http://someurl.com");

Извиняюсь за примеры на C#, но они с Java похожи и, думаю, не составит труда реализовать что-то похожее.

1 лайк

Спасибо, нашел такое , буду разбираться)

Вся эта простыня текста ничего не стоит без кода. Если хотите, чтобы вам действительно помогли, кидайте куски инициализации / убиения драйвера, xml config, DataProvider, AppTest с Before / After.

1 лайк