unit-testing
Общие правила модульного тестирования для всех языков
Поиск…
Вступление
При запуске с модульным тестированием возникают всевозможные вопросы:
Что такое модульное тестирование? Что такое SetUp и TearDown? Как я могу работать с зависимостями? Зачем вообще тестировать единицы измерения? Как сделать хорошие модульные тесты?
Эта статья ответит на все эти вопросы, поэтому вы можете начать модульное тестирование на любом желаемом языке.
замечания
Что такое модульное тестирование?
Единичное тестирование - это проверка кода, чтобы гарантировать выполнение задачи, которую она должна выполнять. Он проверяет код на самом низком уровне - индивидуальные методы ваших классов.
Что такое единица?
Любой дискретный модуль кода, который может быть протестирован изолированно. Большинство классов времени и их методы. Этот класс обычно называют «тест класса» (CUT) или «тест системы» (SUT)
Разница между тестированием модулей и интеграционным тестированием
Единичное тестирование - это испытание отдельного класса, полностью отличное от любых его зависимостей. Интеграционное тестирование - это испытание одного класса вместе с одной или несколькими его фактическими зависимостями.
SetUp и TearDown
Когда метод SetUp запускается перед каждым тестированием устройства и TearDown после каждого теста.
В общем случае вы добавляете все необходимые шаги в SetUp и все этапы очистки в TearDown. Но вы только делаете этот метод, если эти шаги необходимы для каждого теста. Если нет, то эти шаги будут предприняты в рамках конкретных тестов в разделе «Оформить».
Как работать с зависимостями
Много раз у класса была зависимость других классов от выполнения его методов. Чтобы быть в состоянии не зависеть от этих других классов, вы должны подделывать их. Вы можете сами создавать эти классы или использовать среду изоляции или макета. Рамка изоляции представляет собой набор кода, который позволяет легко создавать поддельные классы.
Поддельные классы
Любой класс, предоставляющий функциональность, достаточную для того, чтобы притворяться, что это зависимость, необходимая CUT. Есть два типа подделок: Stubs и Mocks.
- Штук: подделка, которая не влияет на прохождение или неудачу теста и что существует только для того, чтобы позволить запустить тест.
- Макет: подделка, которая отслеживает поведение CUT и передает или не проходит тест на основе этого поведения.
Почему модульное тестирование?
1. В модульном тестировании будут найдены ошибки
Когда вы пишете полный набор тестов, которые определяют, каково ожидаемое поведение для данного класса, раскрывается все, что не ведет себя так, как ожидалось.
2. Тестирование модулей будет содержать ошибки
Внесите изменения, которые вводят ошибку, и ваши тесты могут выявить ее в следующий раз, когда вы запустите свои тесты.
3. Тестирование устройства экономит время
Написание модульных тестов помогает гарантировать, что ваш код работает с самого начала. Единичные тесты определяют, что должен делать ваш код, и поэтому вы не будете тратить время на написание кода, который делает то, чего он не должен делать. Никто не проверяет код, который они не считают, и вы должны что-то сделать, чтобы заставить себя думать, что он работает. Проведите это время, чтобы написать модульные тесты.
4. Модульное тестирование дает покой
Вы можете запустить все эти тесты и знать, что ваш код работает так, как предполагается. Зная состояние вашего кода, что он работает, и что вы можете обновлять и улучшать его без страха, это очень хорошо.
5. Удостоверяющие документы проверяют правильное использование класса
Модульные тесты становятся простыми примерами того, как работает ваш код, что он должен делать и как правильно использовать тестируемый код.
Общие правила модульного тестирования
1. Для структуры единичного теста следуйте правилу AAA
Упорядочить:
Настройте предмет для тестирования. Как переменные, поля и свойства, позволяющие запустить тест, а также ожидаемый результат.
Действие: На самом деле вызовите метод, который вы тестируете
Утверждают:
Вызовите структуру тестирования, чтобы убедиться, что результат вашего «действия» - это то, что ожидалось.
2. Проверяйте одно в то время в изоляции
Все классы должны тестироваться изолированно. Они не должны зависеть от чего-либо другого, кроме как насмешек и окурков. Они не должны зависеть от результатов других тестов.
3. Сначала напишите простые тесты «прямо вниз по середине»
Первые тесты, которые вы пишете, должны быть простейшими. Они должны быть теми, которые в основном и легко иллюстрируют функциональность, которую вы пытаетесь написать. Затем, как только эти тесты пройдут, вы должны начать писать более сложные тесты, которые проверяют границы и границы вашего кода.
4. Напишите тесты, проверяющие края
После того, как основы будут протестированы, и вы знаете, что ваша базовая функциональность работает, вы должны проверить края. Хороший набор тестов будет исследовать внешние границы того, что может случиться с данным методом.
Например:
- Что произойдет, если произойдет переполнение?
- Что делать, если значения равны нулю или ниже?
- Что делать, если они идут в MaxInt или MinInt?
- Что делать, если вы создаете дугу 361 градуса?
- Что произойдет, если вы пройдете пустую строку?
- Что произойдет, если строка имеет размер 2 ГБ?
5. Испытание через границы
Единичные тесты должны проверять обе стороны заданной границы. Перемещение через границы - это места, где ваш код может выйти из строя или выполнить непредсказуемым образом.
6. Если вы можете, проверьте весь спектр
Если это практично, проверьте весь набор возможностей для своей функциональности. Если он включает перечисляемый тип, проверьте функциональность с каждым из элементов в перечислении. Это может быть нецелесообразно проверять каждую возможность, но если вы можете проверить все возможности, сделайте это.
7. Если возможно, покройте каждый путь кода
Это тоже сложно, но если ваш код предназначен для тестирования, и вы используете инструмент покрытия кода, вы можете убедиться, что каждая строка вашего кода покрывается модульными тестами хотя бы один раз. Покрытие каждого пути кода не гарантирует, что ошибок нет, но он, безусловно, дает вам ценную информацию о состоянии каждой строки кода.
8. Напишите тесты, которые показывают ошибку, затем исправьте ее
Если вы обнаружите ошибку, напишите тест, который показывает это. Затем, вы легко можете исправить ошибку, отлаживая тест. Затем у вас есть хороший регрессионный тест, чтобы убедиться, что если ошибка вернется по какой-либо причине, вы сразу узнаете. Очень легко исправить ошибку, когда у вас есть простой, прямой тест для запуска в отладчике.
Боковое преимущество здесь в том, что вы протестировали свой тест. Поскольку вы видели, что тест терпит неудачу, а затем, когда вы видели его, вы знаете, что тест действительно в том смысле, что было доказано, что он работает правильно. Это делает его еще лучшим регрессионным тестом.
9. Сделайте каждый тест независимым друг от друга
Тесты никогда не должны зависеть друг от друга. Если ваши тесты должны выполняться в определенном порядке, вам нужно изменить тесты.
10. Напишите одно утверждение за тест
Вы должны написать одно утверждение за тест. Если вы не можете этого сделать, то преломляйте свой код, чтобы ваши события SetUp и TearDown использовались для правильного создания среды, чтобы каждый тест можно запускать индивидуально.
11. Назовите свои тесты четко. Не бойтесь длинных имен
Поскольку вы делаете одно утверждение за каждый тест, каждый тест может оказаться очень специфичным. Таким образом, не бойтесь использовать длинные полные имена тестов.
Длинное полное имя позволяет сразу узнать, какой тест не удалось и что именно пытался выполнить этот тест.
Длинные, четко названные тесты также могут документировать ваши тесты. Тест под названием «DividedByZeroShouldThrowException» документирует то, что делает код, когда вы пытаетесь разделить на ноль.
12. Испытайте, что каждое поднятое исключение действительно поднято
Если ваш код вызывает исключение, тогда напишите тест, чтобы убедиться, что каждое исключение, которое вы поднимаете, фактически поднимается, когда оно предполагается.
13. Избегайте использования CheckTrue или Assert.IsTrue
Избегайте проверки булевского состояния. Например, вместо проверки, если две вещи равны с CheckTrue или Assert.IsTrue, вместо этого используйте CheckEquals или Assert.IsEqual. Зачем? Из-за этого:
CheckTrue (Ожидаемый, Фактический). Это будет сообщать о чем-то вроде: «Некоторое испытание не выполнено: ожидалось, что True, но фактический результат был False».
Это ничего не говорит.
CheckEquals (ожидается, актуально)
Это скажет вам что-то вроде: «Некоторое испытание не выполнено: ожидалось 7, но фактический результат был 3.»
Используйте только CheckTrue или Assert.IsTrue, когда ваше ожидаемое значение на самом деле является булевым.
14. Постоянно проводите тесты
Запускайте свои тесты во время написания кода. Ваши тесты должны выполняться быстро, позволяя запускать их после незначительных изменений. Если вы не можете запускать свои тесты как часть вашего обычного процесса разработки, тогда что-то идет не так. Модульные тесты должны запускаться почти мгновенно. Если это не так, вероятно, потому, что вы не используете их изолированно.
15. Запустите свои тесты как часть каждой автоматической сборки
Так же, как вы должны проходить тест во время разработки, они также должны быть неотъемлемой частью непрерывного процесса интеграции. Сбой теста должен означать, что ваша сборка нарушена. Не позволяйте провальным испытаниям задерживаться. Считайте это сбоем сборки и исправьте его немедленно.
Пример простого модульного теста в C #
В этом примере мы проверим метод суммирования простого калькулятора.
В этом примере мы протестируем приложение: ApplicationToTest. У этого есть класс под названием Calc. Этот класс имеет метод Sum ().
Метод Sum () выглядит так:
public void Sum(int a, int b)
{
return a + b;
}
Единичный тест для проверки этого метода выглядит следующим образом:
[Testclass]
public class UnitTest1
{
[TestMethod]
public void TestMethod1()
{
//Arrange
ApplicationToTest.Calc ClassCalc = new ApplicationToTest.Calc();
int expectedResult = 5;
//Act
int result = ClassCalc.Sum(2,3);
//Assert
Assert.AreEqual(expectedResult, result);
}
}