как правильнее тест сделать
От: Аноним  
Дата: 01.01.14 08:34
Оценка:
Nunit
Есть вот такой метод для теста
Как лучше, оставить как есть или сделать через параметры и указывать все значения init1, do1, 0, 1 — через аттрибуты
Насколько это удобно будет отлаживать во 2м случае ?



const string init1 = "init1";
const string init2 = "init2";

const string do1   = "do1";
const string do2   = "do2";

[Test]
public void Test()
{
   var a = new A();
   a.Init(init1);
   Assert.IsEqual( a.Do(do1), 0 );

   a = new A();
   a.Init(init2);
   Assert.IsEqual( a.Do(do2), 1 );
}
Re: как правильнее тест сделать
От: Artem Korneev США https://www.linkedin.com/in/artemkorneev/
Дата: 01.01.14 09:23
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Как лучше,

А>public void Test()

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

А> Assert.IsEqual( a.Do(do1), 0 );


Я навскидку не помню сигнатуру IsEqual (м.б. AreEqual?), но сдаётся мне что ожидаемое значение там идёт первым параметром, а не вторым.
И что такое 0? Magic number? Если 0 это дефолтное значение или какой-то код возврата, то лучше сказать об этом явно:

private const DefaultValue = 0;
....
Assert.IsEqual( DefaultValue, a.Do(do1) );

А> Assert.IsEqual( a.Do(do2), 1 );


Две разные проверки в одном тесте — тоже странно. Возможно, есть смысл разделить код на два теста.

А>оставить как есть или сделать через параметры и указывать все значения init1, do1, 0, 1 — через аттрибуты


Зачем через атрибуты? Оставьте как есть.
С уважением, Artem Korneev.
Re: как правильнее тест сделать
От: SergeyT. США http://sergeyteplyakov.blogspot.com/
Дата: 01.01.14 10:44
Оценка: 59 (4) +1
Здравствуйте, Аноним, Вы писали:


А>Nunit

А>Есть вот такой метод для теста
А>Как лучше, оставить как есть или сделать через параметры и указывать все значения init1, do1, 0, 1 — через аттрибуты
А>Насколько это удобно будет отлаживать во 2м случае ?

Конечно здесь явно напрашиваются параметризованные тесты, ведь по сути, здесь не один тест, а два.

[TestCase("init1", "do1", Result = 0)]
[TestCase("init2", "do2", Result = 1)]
public int Test_That_Do_Produces_Expected_Result(string initData, string doData)
{
  // У нас же тут ООП, как никак, а раз так, то инварианты класса А
  // должны устанавливаться в конструкторе
  var a = new A(initData);

  return a.Do(doData);
}


Основной плюс параметризованных тестов в том, что это четко показывает, что у нас не один тест, а два. Ведь существуют правила написания юнит-тестов, один из вариантов которых называется F.I.R.S.T.. Одним из самых важных принципов является I — isolated, это значит, что если один из тестов падает, то другие должны продолжаться исполняться с чистого листа.

В исходном примере, если тест упадет при init1, то второй тест вообще не будет выполнен. Тем более, предложенный вариант очень плохо расширяем. А что если нам понадобиться покрыть десяток кейсов? Так и будем плодить константы и плодить один и тот же код внутри теста? Как-то это кажется не самым удачным подходом.

Параметризованные тесты — это отличный инструмент, который позволяет добиться хорошего покрытия тестов с минимумом усилий. В этом случае добавление еще одно тест-кейса в существующий код — это дело буквально нескольких секунд. К тому же, можно воспользоваться чудо паттерном "Object Mother" и выделить отдельные методы, создающие тестовые данные:

class CustomObjectMother
{
  public static IEnumerable GetTestCasesForYouSpecificCase()
  {
     yield return new TestCaseData("init1", "do1").Returns(0);
     yield return new TestCaseData("init2", "do2").Returns(1);
  }
}


Теперь, если у нас будет несколько тестов, которым подходят эти данные, то можно будет их использовать несколько раз:

[TestCaseSource("CustomObjectMother.GetTestCasesForYouSpecificCase")]
public int Test_That_Do_Produces_Expected_Result(string initData, string doData)
{}

[TestCaseSource("CustomObjectMother.GetTestCasesForYouSpecificCase")]
public int Another_Test_With_The_Same_Arguments(string initData, string doData)
{}


> Насколько будет удобно отлаживать во втором случа?

Если у вас есть решарпер, то это сделать очень просто:


В случае VS2012+, отлаживать тесты тоже просто. Ставим NUnit Test Adapter, в результате можно будет использовать для отладки встроенный Test Explorer:



С Новым Годом
Re[2]: как правильнее тест сделать
От: Аноним  
Дата: 03.01.14 08:49
Оценка:
Здравствуйте, SergeyT., Вы писали:

ST>Здравствуйте, Аноним, Вы писали:



А>>Nunit

А>>Есть вот такой метод для теста
А>>Как лучше, оставить как есть или сделать через параметры и указывать все значения init1, do1, 0, 1 — через аттрибуты
А>>Насколько это удобно будет отлаживать во 2м случае ?

ST>Конечно здесь явно напрашиваются параметризованные тесты, ведь по сути, здесь не один тест, а два.


ST>С Новым Годом



Спасибо, а такой момент еще возник.

Например в тесте делается


public void TestA(string init)
{
   var a = new A(init);
   
   Assert.AreEquals( A.Property1, 1 );
   Assert.AreEquals( A.Property2, "2" );

}



Можно ли сделать


public A TestA( string init )
{
   return new A(init);
}


А проверку полей и property у A указать также в new TestCaseData("init1").Returns(???);
Только вот не совсем понятно что нужно будет в Returns описать.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.