Лучшие практики для утверждений в модульном тестировании - PullRequest
3 голосов
/ 05 января 2012

Я пытаюсь протестировать приложение, которое принимает три аргумента в качестве входных данных (сторона A, сторона B, сторона C) и вычисляет треугольник равнобедренный (две стороны равны), разносторонний (ни одна из сторон не равны) или равносторонний (все стороны равны).

Ниже приведен код из модульного тестирования, над которым я работаю. В этом случае я проверяю, что приложение сообщает пользователю, что треугольник равнобедренный, и мой вопрос здесь, что я должен иметь после Assert в этом случае? AreNotSame работает для разносторонних, AreSame работает для равносторонних, но что здесь работает? Заранее спасибо.

    public void isIsoscelesTest()
    {
        Triangle target = new Triangle(5.0, 5.0, 2.0); // TODO: Initialize to an appropriate value
        bool expected = true; // TODO: Initialize to an appropriate value
        bool actual;
        actual = target.isIsosceles();
        Assert.AreNotSame(expected, actual);
    }

// Из приложения ...

    public bool isIsosceles() {
      if(uniqueSides()==2)
        return true;
      return false;
    }

1 Ответ

5 голосов
/ 05 января 2012

В идеале вы должны создать один тест для каждого тестового случая, поэтому в вашем примере я бы, вероятно, имел

[Test]
public void isIsoscelesTest()     
{ 
    var triangle = new Triangle(5.0, 5.0, 2.0); 
    Assert.That(triangle.isIsoceles(), Is.True);
    Assert.That(triangle.isEquilateral(), Is.False);
    Assert.That(triangle.isScalene(), Is.False);
}

, а также

[Test]
public void isScaleneTest()     
{ 
    var triangle = new Triangle(3.9, 5.0, 2.0); 
    Assert.That(triangle.isIsoceles(), Is.False);
    Assert.That(triangle.isEquilateral(), Is.False);
    Assert.That(triangle.isScalene(), Is.True);
}

и

[Test]
public void isEquilateralTest()     
{ 
    var triangle = new Triangle(3.9, 3.9, 3.9); 
    Assert.That(triangle.isIsoceles(), Is.False);
    Assert.That(triangle.isEquilateral(), Is.True);
    Assert.That(triangle.isScalene(), Is.False);
}

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

В приведенном выше примере мы имеем некоторый (почти) дублированный код, который может быть преобразован во вспомогательный метод, если это необходимо.Кроме того, мы тестируем только три отдельные комбинации переменных (длины сторон).Что если вы добавите туда другие значения?Хорошо, хорошо, мы не можем проверить все, но это дает вам общее представление о недостатках модульных тестов с числовыми значениями.

Наконец, имейте в виду, что оператор == при использовании двойной или плавающей точности не всегда выдает true.Например, попробуйте этот код:

[Test]
public void DoublePrecisionRoundingTest()
{
   double aValue = 1.2345678;
   Assert.That(aValue + double.Epsilon, Is.EqualTo(aValue)); // passes! Should fail
}

Причина этого заключается в том, что при двойной точности ошибка округления может привести к аннулированию некоторых числовых операций.В качестве обходного пути (и это влияет на ваш код треугольника), вы всегда должны проверять «достаточно ли» с переменными типа double или float.

Например, вместо этого в вашем методе Triangle.uniqueSides:

if (aDouble == otherDouble) 

рекомендуется (но не всегда необходимо) использовать

if(Math.Abs(aDouble - otherDouble) < EPSILON)

, где EPSILON находитсядействительно небольшое значение.

С уважением,

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...