2016-08-10 7 views
2

Я создал один модуль для разных входов, чтобы убедиться, что выходы правильные.Как написать аналогичные тестовые примеры, не нарушая принцип единой ответственности?

[TestMethod] 
    public void CountInversionTest() 
    { 
     #region Arrange 
     int[] sourceArray = {4, 3, 2, 1}; 
     int correctInversionCount = 6; 
     int[] sourceArray2 = { 1, 3, 5, 2, 4, 6}; 
     int correctInversionCount2 = 3; 
     int[] sourceArray3 = { 5, 6, 2, 3, 1, 4, 7 }; 
     int correctInversionCount3 = 10; 
     #endregion 

     #region Act 
     Sorter sorter = new Sorter(); 
     int inversionCount = sorter.CountInversion(sourceArray); 
     int inversionCount2 = sorter.CountInversion(sourceArray2); 
     int inversionCount3 = sorter.CountInversion(sourceArray3); 
     #endregion 

     #region Assert 
     Assert.AreEqual(correctInversionCount, inversionCount); 
     Assert.AreEqual(correctInversionCount2, inversionCount2); 
     Assert.AreEqual(correctInversionCount3, inversionCount3); 
     #endregion 
    } 

Поскольку случаи очень похожи, я помещаю их в один метод испытаний. Это поведение в порядке или это нарушает принцип единой ответственности? Если это сломает SRP, то лучшее решение?

+2

Обычно вы хотите иметь их в отдельных тестах, чтобы было легче узнать, какой тест не прошел. – itsme86

+0

@ itsme86 Должен ли я создать другой TestMethod для каждого случая из них? if so Что должно быть надлежащим соглашением об именах для этих TestMethods? И не будет ли это повторяться? – Baso

+1

Почему вы хотите протестировать 3 случая? Есть ли какой-либо специальный кейс, проверенный одним из них? Если это так, укажите цель в отдельном тестовом файле. –

ответ

1

я решил ответить на мой собственный вопрос

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

[TestMethod] 
    public void CountInversionTestCase1() 
    { 
     CountInversionTest(new int[] { 4, 3, 2, 1 }, 6); 
    } 
    [TestMethod] 
    public void CountInversionTestCase2() 
    { 
     CountInversionTest(new int[] { 1, 3, 5, 2, 4, 6 }, 3); 
    } 
    [TestMethod] 
    public void CountInversionTestCase3() 
    { 
     CountInversionTest(new int[] { 5, 6, 2, 3, 1, 4, 7 }, 10); 
    } 

    public void CountInversionTest(int[] sourceArray, int expectedInversionCount) 
    { 
     #region Act 
     Sorter sorter = new Sorter(); 
     long actualInversionCount = sorter.CountInversion(sourceArray); 
     #endregion 

     #region Assert 
     Assert.AreEqual(expectedInversionCount, actualInversionCount); 
     #endregion 
    } 

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

+2

Было бы лучше чтобы дать осмысленные имена методам тестирования, а не «Case1», «Case2», «Case3». Дайте им имена, указывающие _why_, три случая необходимы, т. Е. Какая часть метода CountInversion() 'делает каждый случай, который не покрывается другими случаями. – jaco0646

1

Принцип единой ответственности говорит нам, что этот метод должен иметь только одну причину изменения. Поэтому единичный тест должен проверять один метод и должен изменяться только при изменении метода-теста. Здесь это будет метод CountInversion(). Может ли метод CountInversion() изменяться таким образом, что один из входов sourceArray должен был бы измениться, а не другие? В этом случае входы должны быть разделены на отдельные тесты для размещения SRP.

Как правило, для одного модульного теста вполне нормально многократно вызывать метод-испытание, используя разные входы. Как отмечалось в @ itsme86, тестовые среды обычно облегчают такое поведение, передавая аргументы модульного теста.

5

При правильной рамках модульного тестирования, как xUnit.net, вы могли бы написать Parameterized Test вместо:

[Theory] 
[InlineData(new[] { 4, 3, 2, 1 }, 6)] 
[InlineData(new[] { 1, 3, 5, 2, 4, 6 }, 3)] 
[InlineData(new[] { 5, 6, 2, 3, 1, 4, 7 }, 10)] 
public void ParameterizedCountInversionTest(int[] input, int expected) 
{ 
    Sorter sut = new Sorter(); 
    var actual = sut.CountInversion(input); 
    Assert.Equal(expected, actual); 
} 

Это будет работать три теста, вместо одного, что дает вам лучшую видимость, в которую не удалось особенно тест (если таковые имеются терпит неудачу).

Тест также более читабельен следующим образом.

NUnit также имеет эту функцию, но MSTest не делает (в прошлый раз я смотрел).