Как распараллеливать управляемый данными unit test в Visual Studio 2010?
Я знаю, что обычные тестовые тесты на основе ms-тестов можно распараллелить на многоядерной машине (с оговорками, конечно), указав атрибут parallelTestCount в файле .testresults в тестовом решении. Как это,
<Execution parallelTestCount="1">
<TestTypeSpecific />
<AgentRule name="Execution Agents"></AgentRule>
</Execution>
Подробнее: http://blogs.msdn.com/b/vstsqualitytools/archive/2009/12/01/executing-unit-tests-in-parallel-on-a-multi-cpu-core-machine.aspx
Тем не менее, у меня есть проверочный тест, что-то вроде этого, это всего лишь один тест, но вход поступает из csv и работает 1000s записей через тег тот же.
[DeploymentItem("InputDataRows.csv"), Timeout(37800000), DataSource("Microsoft.VisualStudio.TestTools.DataSource.CSV", "|DataDirectory|\\InputDataRow.csv", "InputDataRow#csv", DataAccessMethod.Sequential)]
[TestMethod]
public void RunProcessing()
{
int userId = Convert.ToInt32(TestContext.DataRow[0].ToString());
int connId = Convert.ToInt32(TestContext.DataRow[1].ToString());
string xml = TestHelper.GetDataFromDb(userId, connId);
a = doStuffA(xml);
b = doStuffB(xml);
Assert.IsTrue(a == b);
}
Поскольку это медленный процесс, я рассматриваю распараллеливание этого unit test.
Последовательное перечисление в атрибуте - это способ доступа к данным, другой вариант - Random, который по-прежнему является серийным и не параллельным.
Ответы
Ответ 1
Чтобы распараллелить этот unit test, вам понадобится doStuffA()
и doStuffB()
, чтобы иметь возможность работать с подмножеством данных (например, куском или даже одной строкой вашего csv за раз), Если вы можете реорганизовать свои методы таким образом, вы можете использовать задачи или параллельный цикл foreach, чтобы этот тест выполнялся параллельно. Предположим, что ваши методы были реорганизованы для обработки строки вашего csv, вы могли бы сделать что-то вроде этого:
int userId = Convert.ToInt32(TestContext.DataRow[0].ToString());
int connId = Convert.ToInt32(TestContext.DataRow[1].ToString());
string xml = TestHelper.GetDataFromDb(userId, connId);
var rows = xml.Split('\n');
Parallel.ForEach(rows, (row) =>
{
var a = doStuffOnRowA(row);
var b = doStuffOnRowB(row);
Assert.AreEqual(a, b);
});
Ответ 2
Это может показаться немного сложным, но выслушайте меня.
В MSTest существует ограничение на то, что вы не можете выполнять параллельные тесты, управляемые данными.
То, что я делал в прошлом, чтобы обойти это, - это создать "пользовательский инструмент" в визуальной студии.
https://msdn.microsoft.com/en-us/library/bb166508.aspx
ИЛИ
https://msdn.microsoft.com/en-us/library/bb166817.aspx
Пользовательский инструмент, который мы создали, сделал следующее:
- Разделите csv на несколько файлов csv только с одной строкой.
- Создайте индивидуальный тест для каждого из вновь созданных csvs.
Когда эти тесты были сгенерированы, мы наносим на них определенные тестовые атрибуты, поэтому мы могли указывать только на запуск тестов с этим атрибутом.
Это звучит по-верхнему, но если вы хорошо справляетесь с созданием настраиваемого инструмента, на самом деле это очень плавный процесс.
Ответ 3
Если в xml данные не изменяются (или методы не изменяют одни и те же части xml), вы можете сделать это..
var numCompleted = 0;
var a = Task.Run(() => { doStuffOnRowA(xml); });
var b = Task.Run(() => { doStuffOnRowB(xml); });
Task.WaitAll(new Task[2] { a, b });
Это может не работать, если вы копируете и вставляете, вроде псевдокода. Не совсем Параллельно, но по крайней мере будет бегать в то же время!
Ответ 4
Параллельное выполнение управляемых данными тестов не поддерживается. Смотрите здесь: RFC 004 - Параллельное выполнение в сборке
Ответ 5
Как я знаю: отдельные строки данных в тесте НЕ запускаются параллельно. Но если у вас есть несколько модульных тестов, они выполняются параллельно.