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 шт):

Автор решения: Stanislav Pechezerov

Сам принцип тестирования вы усвоили правильно - нужно провести многократные испытания вашего метода. Единственная странность, на которую я пытался указать в комментариях - применение кортежа.

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

// этот список содержит все тест кейсы
// первые два члена кортежа - аргументы, передаваемые в тестируемый метод
// третий член кортежа - известное возвращаемое значение, с которым сравнивается фактический результат

 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));
→ Ссылка
Автор решения: Alexander Petrov

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

Использование цикла сути не меняет.

Специально для такого случая используются параметризованные тесты. В 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.

→ Ссылка