Подтвердить что ты не робот

Как параллельно выполнять единичные тесты (MSTest)?

Я ищу способы запуска тестовых наборов параллельно.

Я знаю настройку .testrunconfig. Это позволяет мультиплексировать количество процессоров.

Я хочу запустить 1000 тестов параллельно. Это имеет смысл, потому что я тестирую веб-сервис, поэтому 90% времени, проведенного в тесте, ждут ответа службы.

Любые идеи о том, как это сделать? Тесты написаны для VS, но я открыт для запуска их вне VS.

Позднее отредактируйте: команда разработчиков Visual Studio добавила это в обновление VS 2015. 1. См. ниже ответьте на комментарий Sokol.

4b9b3361

Ответ 1

Большинство ответов на этой странице забывают упомянуть, что MSTest распараллеливает тесты в отдельных сборках. Вы должны разделить свои юнит-тесты на несколько .dll, чтобы парализовать их.

Но! Последняя версия - MSTest V2 - теперь МОЖЕТ распараллелить "в сборке" (ууу!), Вам просто нужно установить пару пакетов nuget в вашем тестовом проекте - TestFramework и TestAdapter - как описано здесь https://blogs.msdn.microsoft.com/devops/2018/01/30/mstest-v2-in-assembly-parallel-test-execution/

А затем просто добавьте это в свой тестовый проект

[assembly: Parallelize(Workers = 4, Scope = ExecutionScope.ClassLevel)]

ОБНОВЛЕНИЕ: Вы также можете отключить параллельное выполнение для конкретного теста, используя [DoNotParallelize] в методе теста.

Ответ 2

Вы можете получить до 5, используя метод из блога тестирования Visual Studio Team

Имейте в виду, что при этом могут возникать проблемы с параллелизмом, поскольку MSTest не полностью изолирует каждый тест (например, перенос статики делает интересным код, предназначенный для однократного выполнения).

(Не знаю, почему ограничение равно 5, но MSTest не будет запускать их параллельно, если для parallelTestCount установлено значение больше 5. Согласно комментариям ниже, это правило, очевидно, меняется в Visual Studio 2013)

Ответ 3

Visual Studio 2015 Обновление 1 добавляет это. https://docs.microsoft.com/visualstudio/releasenotes/vs2015-update1-vs#misc

Для обновления 2 есть кнопка переключения пользовательского интерфейса на панели инструментов в верхней части панели Test Explorer (между полями "группировка" и "поиск").

Для обновления 1 установите следующее в .runsettings

<?xml version="1.0" encoding="utf-8"?>
<RunSettings>
  <RunConfiguration>
    <MaxCpuCount>0</MaxCpuCount>
   </RunConfiguration>
</RunSettings>

Значение для MaxCpuCount имеет следующую семантику:

• ‘n (where 1 <= n <= number of cores): upto ‘n processes will be launched.

• любое другое значение: количество запущенных процессов будет равно числу доступных ядер на компьютере.

Ответ 4

Я обнаружил, что C:\Program Files (x86)\Microsoft Visual Studio 11.0\Common7\IDE\CommonExtensions\Microsoft\TestWindow\vstest.console.exe будет запускать параллельные тесты с помощью файла .testsettings, который выглядит следующим образом:

<?xml version="1.0" encoding="UTF-8"?>
<TestSettings name="TestSettings1" id="21859d0f-7bdc-4165-b9ad-05fc803c9ee9" xmlns="http://microsoft.com/schemas/VisualStudio/TeamTest/2010">
  <Description>These are default test settings for a local test run.</Description>
  <Deployment enabled="false" />
  <Execution parallelTestCount="8">
    <TestTypeSpecific>
      <UnitTestRunConfig testTypeId="13cdc9d9-ddb5-4fa4-a97d-d965ccfc6d4b">
        <AssemblyResolution>
          <TestDirectory useLoadContext="true" />
        </AssemblyResolution>
      </UnitTestRunConfig>
    </TestTypeSpecific>
    <AgentRule name="Execution Agents">
    </AgentRule>
  </Execution>
</TestSettings>

Ссылка можно найти здесь http://msdn.microsoft.com/en-us/library/vstudio/jj155796.aspx

Ответ 5

Вышеприведенные ответы определенно помогли мне прояснить ситуацию, но этот момент из блога Джона Кернера: https://johnkoerner.com/vs2015/parallel-test-execution-in-visual-studio-2015-update-1-might-not-be-what-you-expect/ - это то, чего нам не хватало.

"Параллельное выполнение теста использует доступные ядра на машине и реализуется путем запуска механизма выполнения теста на каждом доступном ядре как отдельного процесса и передачи ему контейнера (сборка, DLL или соответствующий артефакт, содержащий тесты для выполнения), стоит тестов для выполнения. "

-> "Отдельный бит контейнера - это то, чего мне не хватало. Чтобы мои тесты работали параллельно, мне нужно было разделить мои тесты на отдельные тестовые сборки. После этого я увидел, что тесты в разных сборках работали параллельно. "

Так что да, тесты выполнялись параллельно в VSTS с помощью удобного флага "параллельный запуск", но этого было недостаточно, нам пришлось разделить наши тесты на отдельные тестовые проекты. Разумеется, логически сгруппированный, а не проект за тест, который был бы нелепым

Ответ 6

  1. Убедитесь, что первый столбец в вашей DataTable является уникальным идентификатором.
  2. Создайте делегат AsyncExecutionTask, который принимает DataRow и ничего не возвращает.
  3. Создайте статический класс (ParallelTesting) с помощью метода AsyncExecutionContext, который принимает делегат DataRow и AsyncExecutionTask.
  4. В статическом классе добавьте статическое свойство BatchStarted.
  5. В статическом классе добавьте статическое свойство словаря AsyncExecutionTests.
  6. В метод AsyncExecutionContext добавьте следующее:

    public static void AsyncExecutionContext(DataRow currentRow, AsyncExecutionTask test) 
    {
        if(!BatchStarted)
        {
            foreach(DataRow row in currentRow.Table)
            {
                Task testTask = new Task(()=> { test.Invoke(row); });
                AsyncExecutionTests.Add(row[0].ToString(), testTask);
                testTask.Start();
            }
            BatchStarted = true;
        }
        Task currentTestTask = AsyncExecutionTests[row[0].ToString()];
        currentTestTask.Wait();
        if(currentTestTask.Exception != null) throw currentTestTask.Exception;
    }
    
  7. Теперь используйте класс так:

    [TestMethod]
    public void TestMethod1()
    {
        ParallelTesting.AsyncExecutionContext(TestContext.DataRow, (row)=>
            {
                //Test Logic goes here.
            }
        );
    }
    

Примечание: Вам нужно будет немного поработать с исключениями, чтобы заставить их правильно всплыть (здесь у вас может быть агрегатное исключение, вам понадобится первое исключение из него). Количество времени, отображаемое для выполнения каждого теста, больше не будет точным. Вы также захотите очистить класс ParallelTesting после завершения последней строки.

Как это работает: Тестовая логика заключена в лямбду и передается статическому классу, который будет выполнять логику один раз для каждой строки тестовых данных при первом вызове (первая строка выполняется). Последовательные вызовы статического класса просто ждут, пока завершится тестовое задание.

Таким образом, каждый вызов тестовой среды, выполненной для TestMethod, просто собирает результаты теста соответствующего теста, который уже был выполнен.

Возможные улучшения:

  • Заставьте AsyncExecutionContext принять параметр maxSynchronousTasks.
  • Посмотрите, как инфраструктура перемещает полные трассировки стека по неуправляемому коду, чтобы увидеть, можно ли передать Task.Exception в среду тестирования Visual Studio без перебрасывания и уничтожения трассировки стека.