Вы используете константы от реализации в Ваших тестовых сценариях?

Скажем, у Вас есть некоторый код как это (в искусственном langague, так как он не имеет значения для этого вопроса):

constant float PI = 3.14;
float getPi() 
{ 
   return PI;
}

Протестируйте его как это:

testPiIs3point14()
{
   // Test using literal in test case
   AssertEquals( getPi(), 3.14 );
}

Или как это:

testPiIs3Point14()
{
   // Test using constant from implementation in test case
   AssertEquals( getPi(), PI );
}

Другими словами, Вы используете константы от своей системы под тестом в Ваших тестовых сценариях? Или это считают деталью реализации?

30
задан WW. 29 July 2010 в 06:46
поделиться

5 ответов

Эти два теста служат разным целям.

Первый гарантирует, что getPi () всегда будет возвращать значение 3.14. Он охватывает как константу, так и функцию и завершится ошибкой, если кто-нибудь обнаружит, что значение PI, используемое в программном обеспечении, недостаточно точное, и заменит его, скажем, на 3,14159. Это может быть хорошо или плохо, в зависимости от контекста.

Хотя вторая форма охватывает только функцию. Он не потерпит неудачу, если кто-то изменит константу; он потерпит неудачу только в том случае, если функция будет изменена для возврата другой константы (с другим значением).

Выбор между двумя зависит от цели теста. Используйте литерал, если константа никогда не должна изменяться. Используйте константу, чтобы определить поведение функции: вернуть константу - независимо от ее значения. Во втором случае проверка может оказаться ненужной.

18
ответ дан 28 November 2019 в 00:18
поделиться

Я думаю, это вопрос о связи между тестами и производственным кодом. Когда я впервые запустил TDD, я подумал, что наличие константы в тестах делает тесты более тщательными. Однако теперь я думаю, что это просто приводит к более тесной связи между тестами и реализацией. Сделает ли это более безопасным, если вы скопируете и вставите константу в тест? Не совсем. Это только усложняет изменение константы, особенно если ее скопировать в несколько тестов. Эти тесты не проверяют, является ли это правильной константой, они просто проверяют, что эта константа возвращается из метода, поэтому теперь я определенно выберу тест номер два.

3
ответ дан 28 November 2019 в 00:18
поделиться

Определенно вторая форма, цель константы - не вводить «магическое число». В модульных тестах вы, как правило, довольно часто используете магические числа, и это нормально.

В этом случае вы ввели константу И использовали магическое число. Я бы либо везде использовал константу, либо вообще ее не использовал.

1
ответ дан 28 November 2019 в 00:18
поделиться

Я думаю, что здесь есть два разных случая:

  1. Если вы тестируете константу, которая имеет решающее значение для результата вычисления, как в вашем примере, я думаю, что лучше использовать независимый тест, чем повторно использовать та же константа из кода, который вы пытаетесь протестировать. Вместо того, чтобы напрямую проверять постоянное значение, я бы протестировал (например) функцию CalculateAreaOfCircle (), которая проверила бы правильность формулы Area и в то же время проверила бы значение PI.

  2. Я думаю, что имеет смысл повторно использовать перечисления и другие константы, которые не влияют напрямую на результат критических частей кода.

2
ответ дан 28 November 2019 в 00:18
поделиться

Я использую первую форму - даже если она дублирует значение (только дважды), она более читабельна.

[Test]
public void GetPIReturns3_14()
{
  Assert.AreEqual(3.14, testSubject.GetPI());
}

Дублирование необходимо, потому что, если вы повторно используете константу, как во втором тесте, вы на самом деле ничего не тестируете. Фактически, вы тестируете «Константа == Константа?». Этот тест никогда не подведет. например если я изменю PI на 1010.1010, второй тест не завершится ошибкой.

1
ответ дан 28 November 2019 в 00:18
поделиться
Другие вопросы по тегам:

Похожие вопросы: