Как запустить модульные тесты (MSTest) параллельно? - PullRequest
54 голосов
/ 12 октября 2010

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

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

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

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

Позднее редактирование : команда тестирования Visual Studio добавила это в VS 2015 Update 1. См. Ответ Марка Совула ниже.

Ответы [ 6 ]

29 голосов
/ 01 ноября 2010

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

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

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

23 голосов
/ 18 августа 2018

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

Но! Последняя версия - MSTest V2 - теперь CAN распараллеливает "в сборке" (ууу!), Вам просто нужно установить пару пакетов 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)]
21 голосов
/ 01 декабря 2015

Обновление 1 для Visual Studio 2015 добавляет это. 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’ (где 1 <= n <= количество ядер): будет запущено до ‘n’ процессов. </p>

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

8 голосов
/ 24 июля 2013

Я обнаружил, что 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 голосов
/ 20 декабря 2016

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

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

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

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

1 голос
/ 12 января 2018
  1. Убедитесь, что первый столбец вашей таблицы данных является уникальным идентификатором.
  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, не перебрасывая и не уничтожая трассировку стека.
...