Рано или поздно перед вами как перед программистом встанет вопрос:«Как писать юнит-тесты?». Это связано с простой целью — удостовериться, что множество компонентов вашего сложного приложения работают как единое целое и самое главное — правильно.
Unit-тесты — это первый этап при выявлении багов в приложении, за ними идут более «тонкие» тесты:
-
интеграционные;
-
приемочные;
-
тесты «руками».
Поэтому к написанию unit-тестов нужно подойти со всей ответственностью.
Как писать юнит-тесты
Прежде чем писать unit-тесты, нужно для начала определиться, а нужны ли они вашей разработке? Потому что не всем проектам необходимо подобное тестирование. К примеру, не нужно знать, как писать unit-тесты, если:
-
Ваш проект — это небольшой html-сайт из 2-5 страниц и с 1-2-мя формами отправки заявки или письма с обратной связью. В таком проекте не присутствует сложная логика, для которой нужно писать юнит-тесты. Все проверяется «руками» и очень быстро.
-
Ваш проект — это проект «представления», когда, опять же, отсутствует сложная логика: лендинг, рекламный сайт, флеш-игра, несложная верста или анимация и др.
-
Вы делаете презентационный софт для выставки и очень сильно ограничены во времени.
-
Вы создаете идеальный код и всегда вообще без ошибок. А сам код может мгновенно изменяться под требования заказчика, и более того, код способен объяснить заказчику, что его требования — это полная нелепость и непонимание сути заказываемой разработки.
В общем, первые 3 пункта подсказывают, что когда у вас сжаты сроки, сжат бюджет, простая разработка и просто нет смысла тратить время на дополнительное тестирование, потому что софт будет жить 1-3 дня, — в таких случаях проводить юнит-тестирование необязательно.
Последний пункт — это шутка, потому что программистов, пишущих идеальный код, пока нет, но, возможно, вы будете первым. А пока даже разработчики с большим стажем допускают ошибки и постоянно оптимизируют свой код, поэтому в итоге они проводят свои разработки через все этапы тестирования, через юнит-тесты в том числе. Потому что любой сложный и долгосрочный проект в отсутствии качественного тестирования рано или поздно обречен на провал и, скорее всего, будет переписан с нуля.
Написание unit-тестов
Написание unit-тестов — дело ответственное, поэтому перед написанием теста нужно знать несколько правил:
-
Тест должен быть достоверным.
-
Он не должен зависеть от окружения.
-
Написанный тест должен легко обслуживаться.
-
Тест должен быть максимально простым и понятным.
-
Должен присутствовать автоматический режим запуска тестов.
-
Тест пишется для того кода, в котором нет уверенности.
-
Когда пишется тест для классов, то писать его нужно, двигаясь от простого метода к сложному.
-
Если стоит выбор, что проверять: результат или поведение, то всегда сначала нужно проверять результат.
-
Если к коду невозможно написать тест, то это, скорее всего, «говнокод», и его нужно переписывать.
-
У любого теста должна быть возможна фальсификация, то есть должно быть такое входное значение, чтобы тест провалился.
-
Тест должен провалиться только тогда, когда тестируемый код меняется. И никогда не должен проваливаться просто так.
-
Плохой тест всегда лучше, чем полное отсутствие юнит-теста.
Итак, чтобы реализовать все вышеперечисленные правила и знать наверняка, как писать эффективные юнит-тесты, нужно:
-
Правильно выбирать логическое размещение unit-тестов в вашей VCS. К примеру, если ваша разработка монолитная, то тесты расположить в папку Tests. Если приложение состоит из нескольких элементов, то имеет смысл хранить тесты в папке каждого элемента.
-
Правильно выбирать способ называть проект с тестом. Лучше всего добавлять к отдельному проекту его личный тестовый проект, например: когда у вас проект называется <Имя_проекта>.Core, то имеет смысл просто добавить <Имя_проекта>.Core.tests.
-
При тестировании классов использовать такой же способ называть тест. Должен быть такой же подход, как описано выше, например: когда у вас есть класс FindProblem, то его тестовый проект должен быть FindProblemTests.
-
Выбирать фреймворк для теста, который лучше всего подойдет. Не нужно изобретать колесо, когда уже придумали велосипед. Можно воспользоваться некоторыми популярными фреймворками для теста: MsTest, NUnit, xUnit и др.
-
Писать тело теста в едином стиле, чтобы было проще читать и поддерживать код.
-
Тестировать одну вещь за раз. Нужно упрощать процесс тестирования. Если вам нужно протестировать сложный процесс (например, процесс покупки в интернет-магазине), то разбивайте его на более мелкие части и тестируйте их отдельно.
-
Не относиться к юнит-тестам как к второстепенному коду. Все принципы и технологии при разработке основного кода должны использоваться и при написании тестов.
Несколько книг, которые отлично раскрывают ответ на вопрос о том, как писать юнит-тесты:
-
«The Art of Unit Testing» от Roy Osherove;
-
«xUnit Test Patterns: Refactoring Test Code» от Gerard Meszaros;
-
«Working Effectively with Legacy Code» от Michael Feathers;
-
«Pragmatic Unit Testing in C# with NUnit, 2nd Edition» от Andy Hunt и Dave Thomas.
Заключение
Прежде чем искать, как написать юнит-тест, нужно определиться, а нужен ли он вашему приложению? Ведь написание unit-тестов — это дополнительные работа и время, поэтому это не всегда эффективно в небольших разработках.
С другой стороны, есть мнение, что сложные разработки лучше начинать с написания тестов, а не с самой программы. И в этом есть свои преимущества, к примеру, в таком случае у вас будет уже готовая структура будущего приложения и вы точно не сделаете спагетти-код в своей будущей разработке.
Если вы определили, что вам необходимо написание unit-тестов, то относитесь к этому процессу так же серьезно, как и к самой разработке — это сэкономит вам в дальнейшем кучу времени.