Это отрывок из электронной книги «Единичное тестирование » Марка Клифтона, любезно предоставленный Syncfusion.
Модульное тестирование также полезно для других целей.
В качестве примеров использования
Одним из побочных преимуществ модульного тестирования является то, что оно создает большую кодовую базу, иллюстрирующую, как использовать код. Например, код, который мы видели ранее:
[Тестовое задание] public void FilenameParsingTest () { Словарь <string, string> options = CommandLineParser.Parse ("- f foobar"); Assert.That (options.Count == 1, «Ожидается, что счет будет 1»); Assert.That (options.ContainsKey ("- f"), "Ожидаемая опция '-f'"); Assert.That (options ["- f"] == "foobar"); }
документирует ожидаемый допустимый вариант использования анализатора командной строки. Также подумайте о написании модульных тестов — не только для вашего собственного кода, но и для предоставления примеров для сторонних библиотек. (См. Последующие примеры и интересные вещи, раскрытые о структуре Rectangle.)
Тестирование черного ящика
Тестирование черного ящика предполагает, что вы ничего не знаете о внутренностях класса или сервиса и проверяете его поведение строго из открытых интерфейсов. Это часто необходимо, когда у вас нет кода. Например, при работе с компанией по управлению записями нам было необходимо использовать веб-сервис, предоставляемый государственным учреждением, для обновления записей. Написав модульные тесты для веб-службы, мы смогли доказать, что предоставленная нам документация не привела к ожидаемому поведению веб-службы.
Вы также можете использовать эту технику при работе с кодом, предоставленным различными отделами. Например, группа базы данных может иметь свое собственное модульное тестирование белого ящика; однако вам также следует убедиться, что с точки зрения «черного ящика» триггеры и ограничения были правильно запрограммированы, проверяя результат транзакций на основе предоставленной вам функциональности.
Проверьте свои предположения
Модульное тестирование может быть простым способом собрать некоторые тесты относительно наших предположений об API. Давайте возьмем структуру System.Drawing.Rectangle
и протестируем некоторые, казалось бы, разумные предположения о реализации.
Предположения тестового конструктора
Существует два конструктора Rectangle
: один с параметрами Point
и Size
, другой с параметрами x, y, width и height. В документации не указывается, должен ли размер (ширина или высота) быть положительным, поэтому давайте напишем тест, чтобы убедиться, что мы можем построить прямоугольник с отрицательной шириной или высотой:
[Метод испытания] public void RectangleNegativeSizeConstructorTest () { Прямоугольник r = новый прямоугольник (0, 0, -4, -6); }
Все, что мы делаем здесь в этом тесте, это проверка того, что при создании прямоугольника не выдается никаких исключений, и это действительно так:
Тестовые предположения относительно значений свойств
Теперь давайте проверим наши предположения об определенных свойствах. Свойства Top
, Left
, Bottom
и Right
описаны как (см.
http://msdn.microsoft.com/en-us/library/system.drawing.rectangle.aspx ):
Top: Получает Y-координату верхнего края этой структуры Rectangle.
Слева: получает x-координату левого края этой структуры Rectangle.
Внизу: получает координату Y, которая является суммой значений свойств Y и Высота этой структуры Rectangle.
Справа: получает x-координату, которая является суммой значений свойств X и Width этой структуры Rectangle.
Итак, с предыдущим прямоугольником с отрицательной шириной и высотой и, следовательно, с координатами [(-4, -6), (0, 0)], мы бы сделали следующие предположения:
[Метод испытания] public void TestLeft () { Прямоугольник r = новый прямоугольник (0, 0, -4, -6); Assert.IsTrue (r.Left == -4, "Ожидается слева == -4, но было" + r.Left); } [Метод испытания] public void TestTop () { Прямоугольник r = новый прямоугольник (0, 0, -4, -6); Assert.IsTrue (r.Top == 0, "Ожидаемая вершина == 0, но была" + r.Top); } [Метод испытания] public void TestRight () { Прямоугольник r = новый прямоугольник (0, 0, -4, -6); Assert.IsTrue (r.Right == 0, "Ожидаемое право == 0, но было" + r.Right); } [Метод испытания] public void TestBottom () { Прямоугольник r = новый прямоугольник (0, 0, -4, -6); Assert.IsTrue (r.Bottom == -6, "Ожидаемый Bottom == -6, но был" + r.Bottom); }
Однако, это не так:
На самом деле, определение вершины и низа также представляется совершенно произвольным, так как я проводил тесты с одинаковыми размерами прямоугольника и наблюдал разные результаты в значениях свойств Top
и Bottom
.
Тестовые предположения о результатах метода
В документации MSDN говорится, что метод Rectangle.Intersect
:
- Возвращает третью структуру Rectangle, которая представляет пересечение двух других структур Rectangle.
- Если пересечения нет, возвращается пустой прямоугольник.
Поэтому мы можем построить простой тест:
[Метод испытания] public void TestIntersection () { Прямоугольник r1 = новый прямоугольник (0, 0, 10, 10); Rectangle r2 = новый прямоугольник (10, 10, 5, 5); Assert.IsFalse (r1.IntersectsWith (r2), «Ожидаемые пересечения R1 и R2.»); Assert.IsTrue (Rectangle.Intersect (r1, r2) == Rectangle.Empty, "Ожидается пустой прямоугольник пересечения."); }
с результатом:
Это сообщает нам, что наши ожидания, основанные на документации, неверны.
В заключение
Модульное тестирование является важным инструментом в процессе тестирования. В то время как интеграция и юзабилити-тестирование часто более ориентированы на клиента (отчетность, основные этапы, проверка требований высокого уровня), модульное тестирование является первой линией защиты для программиста, его команды и ее руководителей. При разумном использовании (помните, вы не ставите целью создать тысячи довольно зеленых огней), это может быть экономически эффективным способом проверки правильности вычислений кода и повторного создания ошибок и проверки их исправления.
Тем не менее, хорошие практики модульного тестирования требуют дисциплинированного подхода, приверженности времени и усилиям, необходимым для реализации и сопровождения тестов, и, с точки зрения программиста, это также требует хороших методов программирования и часто обеспечивает выполнение архитектурных решений. Последние могут столкнуться с ограничениями «просто сделай это» (которые могут быть вполне законными) и потенциально могут повлиять на производительность. С другой стороны, методы и архитектуры программирования, которые вынуждает использовать модульное тестирование, часто приносят большую пользу всему процессу разработки приложений, что снижает затраты и повышает удобство обслуживания не потому, что код тестируется модулем, а потому, что код написан лучше. так что это может быть проверено модулем.