Практика TDD/BDD на примере JavaScript: Введение

в 4:44, , рубрики: bdd, tdd, Блог компании «Evil Martians», Программирование, метки: ,

Введение

В своей прошлой статье "Readme-driven development" я немного затронул тему разработки через тестирование. Комментарии продемонстрировали, что немало людей неверно понимают истинную роль тестов в процессе написания кода.

Этой статьей я начну цикл в котором раскрою тему test- (TDD) и behaviour- (BDD) driven development и покажу на практике как разработка через тестирование может помочь писать качественный и надежный код. Познакомлю со всеми основными терминами и подходами.

Цикл будет полезен и интересен всем, кто интересуется темой TDD/BDD, тем кто еще сомневается в необходимости тратить свое время на написание тестов, тем кто пишет, но не уверен что делает это правильно. И даже тем кто уверен. А так же JavaScript разработчикам желающим сделать свой код лучше и надежнее.

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

План

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

Следующая статья будет о популярных методологиях TDD и BDD, основных положениях, плюсах и минусах этих подходов.

После чего я расскажу вам об инструментарии который мы будем использовать (Mocha, Chai, Sinon.JS), покажу простые примеры их использования.

Дальше — практика. Мы научимся писать тесты по TDD/BDD методологии, настроим окружение, возьмем на вооружение spies, stubs и mocks.

Об авторе

Я — front-end разработчик в Evil Martians, работал над Групоном, мобильным Групоном, сайтом РЕН ТВ и Wannafun. Сейчас занимаюсь платформой для музыкальных коллективов, Amplifr. Open source активист, GTD-энтузиаст. В свободное время пытаюсь постичь дзен функционального программирования. Живу в Азии.

Я давно интересуюсь темой тестирования кода, и прекрасно знаю, что такое неверное понимание роли тестов в написании кода.

Роль тестов

2:1 — отношение строк тестов к строкам кода это нормальная ситуация и может показаться что код покрытый тестами это в три раза больше работы. А значит время разработки увеличивается в три раза.

Но конечно это не так.

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

Но это того стоит. Почему?

Представьте что вы венчурный инвестор, на дворе 70-е и вы раздумываете, вложить ли свои $$$ в Apple. Если бы вы могли заглянуть, хотя бы одним глазком в 21 век, вы бы не думали бы и секунды. Но вы знать не знаете станет ли компания со странным фруктовым названием хоть немного прибыльной.

Решение писать тесты, очень похоже на решение инвестировать в компанию которая неминуемо станет флагманом в мире компьтеров. Это правильное решение. Тем более вы легко можете заглянуть в будущее, в огромный опыт программистов, например прочесть легендарную книгу Кента Бека, «Экстремальное программирование».

Тесты это правильная инвестиция времени. Своего и команды.

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

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

Код покрытый тестами легко переживет нового разработчика или даже полную смену команды.

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

Отличная сделка?

О важности опыта

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

У вас нет опыта в написании тестов, а вы сразу пытаетесь интегрировать автоматическое Selenium тестирование? Плохой мальчик! С тем же успехом вы могли попросить бабушку написать систему биллинга.

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

Очень важно — четко понимать, зачем вы тестируете ту или иную часть. Помните, 100% покрытие не означает 100% работоспособность.

Многие вещи вообще не стоит тестировать. Не нужно тестировать приватные методы. Работоспособность библиотек и фреймворков тоже не нужно проверять, они же уже протестированы, верно?

Бывают разные ситуации, иногда достаточно протестировать лишь критические участки кода.

Чтобы эффективно писать тесты, нужен опыт. Естественно его нужно где-то получить. Если вы учитесь на живом проекте, правильно задайте себе рамки и не забудьте рассказать об этом тому, кто платит вам деньги.

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

Злой заказчик

Заказчику не душе увеличение срока на неделю?

Ваша задача объяснить почему это важно и что это позитивно скажется на качестве продукта. Расскажите все плюсы и минусы разработки через тестирование. Будьте убедительны.

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

А если вы такого повстречаете, постарайтесь как можно быстрее с ним распрощаться, мой вам совет.

Автор: kossnocorp

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js