Unit Test (MSTest). C#
Прошу помочь на начальных порах изучения модульных тестов. Пишу их первый раз.
Есть вот такой метод:
public static uint GCDByEuclid(uint num1, uint num2)
{
while (num2 != 0)
{
uint temp = num2;
num2 = num1 % num2;
num1 = temp;
}
return num1;
}
для которого хочу написать модульный тест. Создал проект тестов(MSTest) в MSVS 2019. Написал там следующее:
[TestClass]
public class FindGCDTests
{
[TestMethod]
public void GCDByEuclidTest()
{
(uint, uint) firstPair = (10, 50);
uint expectedFirstPair = 10;
(uint, uint) secondPair = (20, 21);
uint expectedSecondPair = 1;
(uint, uint) thirdPair = (1500, 3000);
uint expectedThirdPair = 1500;
(uint, uint) fourthPair = (22, 15);
uint expectedfourthPair = 1;
Assert.AreEqual(expectedFirstPair, FindGCD.GCDByEuclid(firstPair.Item1, firstPair.Item2));
Assert.AreEqual(expectedSecondPair, FindGCD.GCDByEuclid(secondPair.Item1, secondPair.Item2));
Assert.AreEqual(expectedThirdPair, FindGCD.GCDByEuclid(thirdPair.Item1, thirdPair.Item2));
Assert.AreEqual(expectedfourthPair, FindGCD.GCDByEuclid(fourthPair.Item1, fourthPair.Item2));
}
}
Подскажите где что нужно убрать/добавить/поменять.
Ответы (2 шт):
Сам принцип тестирования вы усвоили правильно - нужно провести многократные испытания вашего метода. Единственная странность, на которую я пытался указать в комментариях - применение кортежа.
В вашем случае кортеж (или анонимный тип, который отличается от кортежа тем, что содержит содержит больше информации о членах) можно более эффективно использовать следующим образом:
// этот список содержит все тест кейсы
// первые два члена кортежа - аргументы, передаваемые в тестируемый метод
// третий член кортежа - известное возвращаемое значение, с которым сравнивается фактический результат
List<(uint, uint, uint)> cases = new List<(uint, uint, uint)>()
{
(10, 50, 10),
(20, 21, 1),
(1500, 3000, 1500),
(22, 15, 1)
};
foreach (var test in cases)
Assert.AreEqual(test.Item3, FindGCD.GCDByEuclid(test.Item1, test.Item2));
Когда вы пишете несколько ассёртов в одном тесте, то при падении одного из них выполнение теста прервётся и вы не узнаете, сработают ли остальные. Это плохо, так как может понадобиться множество лишних прогонов тестов.
Использование цикла сути не меняет.
Специально для такого случая используются параметризованные тесты. В MSTest они реализуются с помощью атрибутов DataTestMethod и DataRow.
[DataTestMethod]
[DataRow(10u, 50u, 10u)]
[DataRow(20u, 21u, 1u)]
[DataRow(1500u, 3000u, 1500u)]
[DataRow(22u, 15u, 1u)]
public void GCDByEuclidTest(uint num1, uint num2, uint expected)
{
Assert.AreEqual(expected, FindGCD.GCDByEuclid(num1, num2));
}
В этом случае, если один из ассёртов упадёт, остальные выполнятся.
Есть и другие способы, но они более сложные и нужны, соответственно, для сложных случаев тестирования.
Документация MSTest страдает отсутствием примеров использования DataSource и DynamicData. Я нашёл лаконичные примеры здесь. И, вероятно, стоит смотреть доки на гитхабе: 1, 2.