Как применить «одно утверждение на тест» для условия отношения ИЛИ - PullRequest
4 голосов
/ 03 июня 2009

Признано, что "одно утверждение на тест" в утверждении. Нехорошо писать утверждение, как показано ниже:

  Assert((foo != null) && (bar != null));

Лучший выбор:

  Assert(foo != null);
  Assert(bar != null);

Вопрос в том, что если утверждение:

  Assert((foo == null) || (foo.length == 0));

Отношение ИЛИ вместо И.

Есть ли способ сделать "одно утверждение на тест", сохранив логику?

Ответы [ 3 ]

4 голосов
/ 03 июня 2009

Идея, лежащая в основе руководства, заключается в том, что в одном тесте вы можете протестировать только одну логическую вещь (которая может сводиться к нескольким утверждениям в некоторых случаях). Поэтому, если тест не пройден, вы знаете точную причину, по которой он не прошел и может быть привязан к конкретному блоку кода в оснастке. Если взять пример из этой страницы , если следующий тест не пройден, я знаю, что что-то не так с тем, как страна извлекается / определяется в типе адреса.

public void testCountry() throws Exception {
        assertEquals("COUNTRY",  anAddress.getCountry());
    }

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

Мне нужно увидеть ваш полный тест. Судя по тому, что вы видите, вы проверяете коллекцию на предмет сценария "что-то не найдено". В этом случае рекомендуется возвращать пустую коллекцию, чтобы клиентам не приходилось проверять наличие нуля. Поскольку ваш тест также является клиентом, его жизнь также упрощается: Assert.AreEqual (0, foo.length)

4 голосов
/ 03 июня 2009

Проблема не в утверждении, а в Arrange или Act части тестового примера: при модульном тестировании вы вызываете [маленький] кусок кода в контролируемой среде . То есть вы должны знать, как будет вести себя тестируемое программное обеспечение, и, следовательно, знать, будет ли оно возвращать нулевой указатель или пустую строку. Каждый тест должен иметь один ожидаемый результат .

... Если вы не используете свой тест для нескольких функций / методов, которые ведут себя по-разному, или какого-либо стороннего кода, который, кажется, ведет себя по-разному в разных ситуациях. Если это так, то «Одно утверждение на правило» - это просто руководство, и вы можете использовать утверждение, как показано на рисунке. Если этот тест не пройден, это будет означать, что возвращаемый foo является непустой строкой.

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

Assert(is_empty_string(foo));

Ваш языковой класс строки может предоставить этот метод.

1 голос
/ 03 июня 2009

Конечно: один тест гарантирует, что нулевой foo утверждает, другой гарантирует, что ненулевой foo с нулевой длиной также завершится неудачей (а другие проверяют случаи [s], когда foo не равен нулю и имеет длину! = 0). Что может быть сложнее, чем проверка AND?

Редактировать: псевдокод по запросу ...:

  should_assert(themethod(foo=null))
  fakefoo = fakewhatever(length=0)
  should_assert(themethod(foo=fakefoo))
  ...rest of tests w/foo not null, w/length != 0

например, в модульном тесте Python с псевдокодом mock это может быть:

  self.assertRaises(AssertionError, theobj.themethod, null)
  fakefoo = mock.makeObj(length=0)
  self.assertRaises(AssertionError, theobj.themethod, fakefoo))
  ...rest of tests w/foo not null, w/length != 0
...