Что тестировать при написании юнит-тестов? - PullRequest
7 голосов
/ 10 марта 2010

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

В настоящее время мы генерируем все наши базовые классы, используя Codesmith, которые полностью основаны на таблицах в базе данных. Мне интересно узнать о преимуществах генерации тестовых случаев с помощью этих базовых классов? Это плохая практика тестирования?

Это подводит меня к последнему вопросу моего поста. Что мы тестируем при использовании юнит-тестов?

Тестируем ли мы примеры, которые, как мы знаем, нам нужны? или мы тестируем примеры, которые нам не нужны?

Это могут быть методы, которые имеют несколько способов потерпеть неудачу и несколько способов успеха, как мы узнаем, когда остановиться?

Взять, к примеру, функцию суммирования. Дайте ему 1,2 и ожидайте 3 в единственном модульном тесте. Как мы узнаем, что 5,6 не вернется 35?

Перечень вопросов

  • Генерация юнит-тестов (хорошо / плохо)
  • Что / Сколько мы тестируем?

Ответы [ 7 ]

7 голосов
/ 10 марта 2010

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

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

6 голосов
/ 10 марта 2010

Суть модульных тестов заключается в том, чтобы дать вам уверенность (но только в особых случаях это дает вам уверенность), что фактическое поведение ваших открытых методов соответствует ожидаемому поведению. Таким образом, если у вас есть класс Adder

class Adder { public int Add(int x, int y) { return x + y; } }

и соответствующий юнит-тест

[Test]
public void Add_returns_that_one_plus_two_is_three() {
    Adder a = new Adder();
    int result = a.Add(1, 2);
    Assert.AreEqual(3, result);
}

тогда это дает некоторую (но не 100%) уверенность в том, что тестируемый метод ведет себя надлежащим образом. Это также дает вам некоторую защиту от взлома кода при рефакторинге.

Что мы тестируем при использовании модульных тестов?

Фактическое поведение ваших открытых методов относительно ожидаемого (или указанного) поведения.

Проверяем ли мы те примеры, которые нам нужны?

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

4 голосов
/ 10 марта 2010

Что проверить: все, что когда-либо пошло не так.

Когда вы найдете ошибку, напишите тест на поведение ошибки до того, как исправите код. Затем, когда код работает правильно, тест пройден, и в вашем арсенале будет еще один тест.

3 голосов
/ 10 марта 2010

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

2) Затем используйте инструмент покрытия кода в vs, чтобы увидеть, используется ли весь ваш код в тестах (все ветки условий if-else, case вызываются). Это своего рода ответ на ваш вопрос о тестировании 1 + 2 = 3, 5 + 6 = 35: когда код покрыт, вы можете чувствовать себя в безопасности в дальнейших экспериментах.

3) Хорошая практика - охватывать 80-90% кода: остальная часть работы обычно неэффективна: получатели-установщики, обработка исключений в одну строку и т. Д.

4) Узнайте о разделении интересов.

5) Генерация модульных тестов - попробуйте, вы увидите, что вы можете сохранить красивые строки кода, написав их вручную. Я предпочитаю генерировать файл с помощью vs, а потом сам пишу остальные TestMethods.

2 голосов
/ 10 марта 2010

Вы проверяете вещи там, где вы

  • хочу убедиться, что ваш алгоритм работает
  • хочу защитить от случайных изменений в будущем

Так что в вашем примере нет смысла тестировать сгенерированные классы. Вместо этого проверьте генератор.

Рекомендуется сначала протестировать основные варианты использования (для чего была разработана проверяемая функция). Затем вы проверяете основные случаи ошибок. Затем вы пишете тесты для угловых случаев (то есть нижних и верхних границ). Случаи необычных ошибок, как правило, настолько трудно воспроизвести, что нет смысла их модульное тестирование.

Если вам необходимо проверить большой диапазон наборов параметров, используйте управляемое данными тестирование.

Сколько тестируемых вами вещей зависит от усилий и отдачи, так что это действительно зависит от конкретного проекта. Обычно вы пытаетесь следовать правилу 80/20, но могут быть приложения, где вам нужно больше тестового покрытия, потому что сбой будет иметь очень серьезные последствия.

Вы можете значительно сократить время, необходимое для написания тестов, если вы используете подход, основанный на тестировании (TDD). Это связано с тем, что код, который написан не с точки зрения тестируемости, намного сложнее, иногда почти невозможно протестировать. Но поскольку ничто в жизни не является бесплатным, код, разработанный с использованием TDD, сам по себе более сложен.

1 голос
/ 10 марта 2010

Есть три основных события, которые я проверяю: мин, макс и где-то между мин и макс.

И, при необходимости, две крайности: ниже минимума и выше максимума

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

1 голос
/ 10 марта 2010

Я также начинаю процесс более последовательного использования модульных тестов, и я обнаружил, что самой большой задачей в модульном тестировании является структурирование моего кода для поддержки тестирования. Когда я начинаю думать о том, как писать тесты, становится ясно, где классы стали чрезмерно связанными, настолько, что сложность «модуля» затрудняет определение тестов. Я трачу столько же или больше времени на рефакторинг своего кода, как и на написание тестов. Как только границы между тестируемыми модулями становятся более четкими, вопрос о том, с чего начать тестирование, решается сам собой; начните со своих наименьших изолированных зависимостей (или, по крайней мере, тех, о которых вы беспокоитесь) и продолжайте свой путь вверх.

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