Автоматизированное тестирование похоже на дублирование тестируемой логики. Я правильно делаю? - PullRequest
3 голосов
/ 20 октября 2011

Я внедряю автоматизированное тестирование с CppUTest в C ++.
Я понимаю, что в итоге я почти копирую и вставляю логику, которая будет тестироваться в самих тестах, чтобы я мог проверить ожидаемые результаты.
Я делаюэто правильно?должно ли быть иначе?

edit: я попытаюсь объяснить лучше:
Тестируемая единица принимает входные данные A , выполняет некоторую обработку и возвращает выходные данные B
ТакПомимо некоторых проверок черного ящика, таких как проверка того, что выходные данные находятся в ожидаемом диапазоне, я также хотел бы видеть, является ли полученный мной вывод B правильным для ввода A IE, если логика работает, как ожидалось.
Так, например, если единица просто делает A умножить на 2, чтобы выдать B , то в тесте у меня нет другого способапроверка, а затем повторное вычисление A умножить на 2, чтобы сравнить с B , чтобы убедиться, что все прошло хорошо.
Это дублирование, о котором я говорю.

// Actual function being tested:  
int times2( int a )
{
  return a * 2;
}

.

// Test:
int test_a;
int expected_b = test_a * 2; // here I'm duplicating times2()'s logic
int actual_b = times2( test_a );
CHECK( actual_b == expected_b );

.

PS: Я думаю, я переформулирую это в другом вопросе с моим фактическим исходным кодом.

Ответы [ 4 ]

5 голосов
/ 20 октября 2011

Так, например, если единица просто делает A раз 2, чтобы получить B, то в тест у меня нет другого способа проверки, чем сделать снова расчет A раз 2, чтобы проверить против B, чтобы убедиться, что он пошел хорошо.

Да, вы делаете! Вы знаете, как рассчитать A раз два, поэтому вам не нужно делать это в коде. если A равно 4, то вы знаете , ответ равен 8. Таким образом, вы можете просто использовать его в качестве ожидаемого значения.

CHECK( actual_b == 8 )

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

CHECK( times_2(4) == 8 )

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

5 голосов
/ 20 октября 2011

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

Если вы пытаетесь сделать тестовую разработку, вы определенно делаете это неправильно.TDD состоит из множества быстрых циклов:

  1. Написание теста
  2. Наблюдение за его неудачей
  3. Прохождение теста
  4. Рефакторинг при необходимостиОбщий дизайн

Шаг 1 - написание теста first - это неотъемлемая часть TDD.Из вашего вопроса я делаю вывод, что сначала вы пишете код, а потом тесты.

2 голосов
/ 20 октября 2011

Я думаю, что это хотя и взломать, потому что это по сути сдвиг менталитета.Для меня это было несколько сложно.

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

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

1 голос
/ 20 октября 2011

Язык программирования не должен иметь значения.

 var ANY_NUMBER = 4;
 Assert.That(times_2(ANY_NUMBER), Is.EqualTo(ANY_NUMBER*2)

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

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

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