C#+NUnit + Selenium Grid - параллельный запуск на нескольких нодах

Текущий проект пишется на C# и естественно лидер команды разработки, обозревая ситуацию со своей колокольни считает очень важным чтобы автоматизированные тесты тоже писались на C#. “Единая экосистема”, “разработчики смогут помогать” - такого рода аргументация. Заказчик в принципе поддерживает мнение лида девелопмента. При этом все хотят чуть ли не полного покрытия тестами и максимальной скорости их выполнения. Желание вполне нормальное и предсказуемое, но, конечно, не учитывает некоторые “нюансы”. Самый толстый из них как я вижу это параллельный запуск тестов. При этом он совсем не очевиден поначалу пока тестов мало, но может стать весьма критическим через год, когда тестов будет 100 или 200. Как работает Java+TestNG+Selenium Grid это понятно. А вот как работает C#+NUnit(другое?)+Selenium Grid ? Насколько я понял параллельный запуск тестов в NUnit фича совсем новая и те примеры, что я видел относятся к параллельному запуску локально. Это так - побаловаться. “Ух ты - работает!” Вопросы:

  1. Может ли кто-нибудь поделиться опытом C#+NUnit(другое?)+Selenium Grid ?
  2. C# + Selenium - есть ли способы распараллелить по-другому?

Привет!
Успешно использую C# + NUnit + Selenium grid. Никаких проблем не вижу, если честно.
Начиная с версии 3.0 Nunit начал поддерживать параллельное выполнение тестов. Сначала была возможность запускать в параллель только TestFixtures( классы с тестами). С версии 3.7 реализовали возможность запускать сами тесты в параллель.

Небольшой пример:

[Parallelizable(ParallelScope.Fixtures)]
    public class Sample1
    {     
        [Test]
        public void Foo1()
        {
            var capabilities = DesiredCapabilities.Chrome();
            var drv = new RemoteWebDriver("http://huburl:port1", capabilities, TimeSpan.FromMinutes(30));
        }

        [Test]
        public void Foo2()
        {
            var capabilities = DesiredCapabilities.Chrome();
            var drv = new RemoteWebDriver("http://huburl:port2", capabilities, TimeSpan.FromMinutes(30));
        }
}

[Parallelizable(ParallelScope.Fixtures)]
    public class Sample2
    {     
        [Test]
        public void Foo3()
        {
            var capabilities = DesiredCapabilities.Chrome();
            var drv = new RemoteWebDriver("http://huburl:port3", capabilities, TimeSpan.FromMinutes(30));
        }

        [Test]
        public void Foo4()
        {
            var capabilities = DesiredCapabilities.Chrome();
            var drv = new RemoteWebDriver("http://huburl:port4", capabilities, TimeSpan.FromMinutes(30));
        }
}

Тесты все тесты будут выполнятся в 2 потока. В первом потоке (Foo1 и Foo2) , а во втором - (Foo3 и Foo4).
Если нужно, чтобы выполнялись все 4 теста в 4 потока, то нужно повесить аттирбут [Parallelizable(ParallelScope.Self)] на каждый из тестовых методов и убрать аттрибут [Parallelizable(ParallelScope.Fixtures)] из тестовых классов.

Нужно также отметить, что по-дефолту количество потоков будет равно количеству ядер на исполняемой машине. То есть, если у вас 2-х ядерная машина и вы на ней захотите выполнить 15 тестов с аттрибутом Parallelizable, то у вас все тесты будут выполнятся в 2 потока.
Чтобы обойти данное ограничение, нужно запускать тесты через Nunit console. Можно скачать тут.
Нужно всего-лишь указать параметр --workers = n, где n - желаемое количество потоков.

3 лайка

Спасибо! Это обнадёживает. Попробую разобраться попозже.
А в NUnit есть аналог тест сьютов из testNG? Я имею в виду xml файл, в котором перечисляются параметры запуска и тесты?
А ещё они должны на разных портах запускаться?

Тест сьютов через xml файл нет. Вместо этого используют запуск через Nunit console с test selection. Больше информации можно получить тут.

Всё же зависит от того как вы будете запускать тесты. Если вы хотите тесты выполнять все на одном хабе, то тогда на один порт слать реквесты. Если же вы хотите тестировать на разных хабах, то тогда и разные порты.

Я понял. В данном случае Selenium Grid не используется.

SeleniumGrid вообще никак не помогает параллелить тесты. Он позволяет через один селениум сервер открывать несколько независимых браузерных сессий. В том числе, этим могут пользоваться тесты из разных потоков.

TestNG параллелит по потокам, а Grid - по нодам. А в данном случае NUnit параллелит по потокам и программно идёт параллелизация по нодам.

Вместо или как надстройку над NUnit можно использовать Specflow(BDD)
Параллельное выполнение поддерживается - есть режим, когда можно обмениваться информацией между тестовыми потоками
Количество потоков настраивается очень просто в файле Default.srprofile(для настроек Specflow):

  <Execution
    stopAfterFailures="-1"
    retryFor="None"
    testThreadCount="15" //задает количество параллельных потоков
    testSchedulingMode="Random"
    />

Сами тесты ничего не знают о том будут они выполняться паралельно или нет(нет специальных атрибутов). Если необходимо какие-то тесты распараллеливать, а другие нет можно разбить их на отдельные тест сьюты.
Распараллеливание по разным гридам настраиваю через app.config:

    <!-- Grids -->
    <add key="gridip_1"          value="http://example.com:4444" />
    <add key="gridip_2"          value="http://example.com:4445" />
    <add key="gridip_3"          value="http://example.com:4446" />

когда строчки закоментированы, программа запускает браузеры локально
В процессе выполнения тестов можно менять браузеры Default.srprofile:

<ConfigFileTransformation configFile="App.config" >
        <Transformation>
          <![CDATA[<?xml version="1.0" encoding="utf-8"?>
		<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
                              <appSettings>
                                <add key="BrowserType" value="InternetExplorer" 
                                 xdt:Locator="Match(key)" xdt:Transform="SetAttributes(value)" />
                              </appSettings>
		</configuration>
	]]>
      </Transformation>
</ConfigFileTransformation>

Может использовать NUnit, MSTest и много других C# фреймворков для “исполнения” тестов.
Максимально коротко описал несколько возможностей:slightly_smiling_face: