Comments 32
Как вот это пояснить?
Вы пишете ровно такой объем кода модульного теста, какой необходим для того, чтобы этот тест не проходил (если код теста не компилируется, считается, что он не проходит).
Если Вася написал тестовый метод, где забыл точку с запятой, разве можно говорить, что тест не проходит?
Конечно, можно. Ведь код не компилируется.
Так чтобы тесту пройти (или не пройти), ему нужно запуститься сначала. А так у нас просто нет информации, проходит он или нет.
(если код теста не компилируется, считается, что он не проходит).
Так это же бессмысленно так считать. Падающий тест и некомпилирующийся тест — разные ситуации, первая позволяет с большой вероятностью говорить о какой-то ошибке в коде (особенно если тест не падал ранее, хотя изменений в нем не было), вторая вообще ни о чем не говорит.
Тут речь идёт о впервые написанном тесте. Который обязан падать. И в случае теста на новый метод или класс он БУДЕТ падать на компиляции, тк сущность на которую он ссылается отсутствует. Тут бессмысленно спорить, тдд просто устроен именно так. Следующий шаг всё равно - устранение поичины падения. Если вы хотите выстрелить себе в ногу, саботировав процесс - ну, вот, тест падал, вот я вставил точку с запятой - я молодец - ну, да, и этот инструмент можно использовать неправильным образом, соблюдя все формальные критерии. Но какой в этом смысл?
Так если имеется в виду, что тест может некомпилироваться по причине отсутствия нужных методов — это стоит с самого начала пояснить, это совершенно не то же самое, что и ошибки компиляции из-за синтаксиса. В общем случае все же некомпилирующийся код — это не есть нормально. Поэтому я и спрашивал пояснений, что тут имелось в виду.
Так обо всех этих приседаниях и расписано подробно в книге со всем тем занудством на которое только способен автор :). Тут же только тезисы.
Я согласен с shark14, что этот пункт стоило немного детализировать. А то, действительно, возникает ощущение, будто нормальная ситуация - не когда тест не компилится из-за отсутствия реализации тестируемой логики, а когда тест не компилится из-за криво написанного теста)
Да нет же! С точки зрения тдд тут нет разницы. Постулируется, что ошибки - это нормально. То, что вы слелали ошибку в тесте - это нормальная ситуация. Ничем не отличающаяся от того, что у вас нет реализации. Просто у вас будет на одну итерацию больше - ну, и что? Ошибки ведь всё равно нужно исправлять. В тдд они исправляются тем же алгоритмом, что пишется новая функциональность. Можно усложнить алгоритм и сделать развилку, но какое дополнительное преимущество это даст?
Тдд используют для того, чтобы упорядочить собственную работу и получить определённые преимущества от методологии. Если исходить из этого станет понятно, что выделять ошибки тестов отдельно не имеет смысла. Вот если использовать тдд доя того, чтобы пустить пыль в глаза начальству, тогда, да. Такие ошибки "удобны". Ну, рассматривайте это как дополнительное преимущество метода :)
Да. Но чинить придется Васю тест, а не код
Конечно же, речь идёт не о синтаксических ошибках в самих тестах. Здесь лучше пример. Допустим, у нас есть объект Customer, где уже реализована вся логика работы с клиентами. Разработчику дали заявку: доработать объект так, чтобы было ясно, что клиент - должник.
Разработчик решил, что для этого он добавит в Customer новый метод isDebtor(), возвращающий true для клиентов-должников. Соответственно, перед тем, как добавлять метод, пишется примерно такой тест:
public function testCustomerIsDebtor()
{
$customer = new Customer;
$customer->isDebtor();
}
Тест при запуске выдаст ошибку в стиле: "Вызов неизвестного метода isDebtor()". После этого разработчик его когда-нибудь реализует и тест перестанет сообщать об ошибке.
P. S. Пример, конечно, на грани искусственного :-)
Вы немного не поняли: там рассматривался случай, когда код в принципе не компилируется (значит, и запустить тест невозможно). Соответственно, подразумеваются компилируемые языки. В вашем примере, наверное, JS (на самом деле я не знаю). Но интерпретируемые языки — это совсем другая история.
Это больше похоже на неточность перевода, поэтому я и уточнил.
Да, правильно - пример на интерпретируемом языке (PHP).
А с компилируемым языком разве будет другая история? Возьмём - абстрактно - старичка паскаля. Есть модуль Customer.pas, куда планируем добавить функцию isDebtor(). Пишем отдельный тест, где будет такая функция (за точность синтаксиса не ручаюсь, конечно, не мой стек):
unit Customer;
function testIsDebtor()
var customer: Customer;
begin
customer := new Customer;
customer.isDebtor();
end;
Сохраняем файл с тестом, пробуем его - а он не компилируется. И с той же ошибкой: несуществующий метод isDebtor(). А как только функцию isDebtor() реализуем, то тест будет нормально компилироваться и запускаться. Или я тут ошибаюсь?
У вас не скомпилируется не только файл, но и весь проект, что делает бессмысленным пытаться вкоммитить куда-то это промежуточное состояние. Так что придется сразу реализовывать эту функцию хотя бы в виде заглушки, что уже несколько больше, чем "написать тот объем теста, который нужен, чтобы тест падал, включая ошибки компиляции".
Спасибо, интересно.
А в компилируемых языках это ещё как-то обходят, кроме как функцией-заглушкой? Можно тесты отдельным проектом сделать, но при этом как-то подключать тестируемые модули из другого проекта?
P. S. Не могу избавиться от дурной привычки спрашивать о том, что можно самостоятельно найти в первых строчках поисковика. Вопрос риторический, забейте :-)
Почему бессмысленно-то? Да, не скомпилится проект, а что это меняет? Ошибка будет та же самая. Ну, и современные компиляторы инкрементальны, так что в этом смысле "нескомпилится" именно файл. Про вкоммитить речь вообще не идёт. Хотя, никто не мешает, конечно, коммитить в локальную ветку и сломаные тесты. Тест, падающий из-за отсутствия функции - это в данной парадигме нормально. Написание заглушки - это уже следующий шаг итерации. Да, с современными иде этот шаг может быть неявным - несуществующие методы будут подсвечены, но это просто потому, что иде проделала часть работы по компиляции в фоне, а на самом деле он формально никуда не делся.
Потому что отказываясь от компилируемости тестов в процессе их написания, вы по сути лишаете себя многих плюсов, которые дают компилируемые языки — проверка синтаксиса, контроль типов и так далее. И связанные с этим ошибки придется чинить уже после написания теста, в процессе написания уже настоящего кода (заглушек или реального кода — уже не важно). Технически это делать можно, но зачем — загадка.
Более логично, на мой взгляд, так: сначала пишете интерфейс ваших классов, потом пишете тесты на этот интерфейс, а потом уже реализацию интерфейса. И на каждом этапе все будет компилироваться и это можно спокойно вкоммитить и условно уйти в отпуск, чтобы задачу мог доделать кто-то другой.
Потому что отказываясь от компилируемости тестов в процессе их написания, вы по сути лишаете себя многих плюсов, которые дают компилируемые языки — проверка синтаксиса, контроль типов и так далее.
И что из этого вы не сможете проверить? Кроме вашей пропущенной точки с запятой, всё остальное тоже будет проверено.
Более логично, на мой взгляд, так: сначала пишете интерфейс ваших классов, потом пишете тесты на этот интерфейс, а потом уже реализацию интерфейса.
Нет, и если прочтёте книжку, там наверняка про это рассказано подробнее.
Коммитить тесты на заглушки совешенно бессмысленно. Заглушки - это промежуточный этап, а не конечный.
И на каждом этапе все будет компилироваться и это можно спокойно вкоммитить и условно уйти в отпуск, чтобы задачу мог доделать кто-то другой.
А зачем этому другому что-то реализовывать, если и так всё хорошо - всё компилится, тесты зелёные - делать ничего не надо. :)
Ps конечно, так тоже можно и большинство делают именно так, но тогда вы не получите плюшек ТДД. А они есть. И книжка именно про тдд, а не про то, как просто писать тесты. Про это есть другие книжки.
Если в голове есть чёткий план как что делать, то часто удобно описать это в виде тестов, относясь к ним как к документации. Вот если плана нет, то, наверное, тоже можно, но сложнее.
Недавно на комьюните общались на эту тему.
Краткий вывод: в команде нужны разного уровня программистов, как идеальные, так и неидеальные. Они уровновешивают процессы друг друга и сохраняют баланс.
Конечно, если в команде 1 или 2 человека, то лучше, чтобы они были идеальными)
Согласен. Даже профессионал расслабляется, если нет давления снизу. Наличие в команде непрофессиональных коллег заставляет профессионала прилагать усилия, чтобы заставить их быть профессиональнее. А, как сказано в книге, больше всего пользы от обучения получает педагог.
Постоянное сопротивление непрофессиональных коллег держит профессионала в тонусе.
У меня есть гипотеза, что если собрать в одну команду достаточное количество идеальных, то они либо сами расслоятся на идеальных/не идеальных, либо команда сломается каким-то другим образом (например, все передерутся, или все перестанут работать)
Парочка идеальных, наверное, может ужиться между собой. Но это не точно
Вы пишете ровно такой объем рабочего кода, какой необходим для прохождения модульного теста, который в данный момент не проходит.
Я не уверен.
Профессионал чувствителен к нюансам. Программа A и программа B могут решать поставленную задачу (в смысле, соответствовать спецификации, проходить тесты, укладываться в разумные нормы производительности) но между ними может быть трудноуловимая разница, которая существенно влияет на качество программ
Сформулировать эту разницу формально бывает очень сложно. А значит, сложно написать тест, который ее выявляет. А это значит, что если следовать процитированному правилу, между двумя вариантами всегда будет выбираться не тот, что лучше, а тот, что содержит меньше кода. Что не одно и то же.
Поэтому нет, я не уверен в универсальной справедливости процитированного правила (хотя писать лишнее, конечно, тоже не стоит)
К Роберту Мартину отношусь с уважением, но конкретно эта книга - типичный корпоративный скам, предназначенный для бесплатной раскладки на рабочих местах, вроде "Семи навыков высокоэффективных людей" Кови; по моему, сейчас на серьезных щах эту философию "работник должен .<длинный список долгов>" не продать даже первокурснику.
Когда ваш рабочий день заканчивается, пожалуйста, не изучайте альтернативные фреймворки или какую-нибудь, упаси Ктулху, функциональщину. Идите в парк, играйте с детьми, читайте художественную литературу, встречайтесь с друзьями. Отдыхайте. Переключайтесь.
А изучать Хаскель или опенсорсить стоит тогда, когда батарейки уже перезаряжены и познавательный интерес перевешивает желание поваляться с книжкой. И естественно, изучайте то, что интересно вам, а не вашему работодателю.
От таких книг, вроде "идеального программиста" или "семи навыков", может быть польза, если не воспринимать их как святое писание, которому надо слепо следовать. Они могут помочь задуматься о каких-то вещах, которые не факт, что придут в голову сами по себе. Взвешивание утверждаемых в книгах тезисов, их переоценка, исходя из личного опыта, может помочь уложить и систематизировать какую-то информацию в голове. По крайней мере, мне в свое время помогло.
Книжка - артефакт давно погибшей вселенной, где "идеальный" программист после работы в личное время лихорадочно шел изучать больше и больше технологий, читать IT-twitter , коммитить в опен-сорс, мечтая взять на себя больше Ответственности с большой буквы О. Потому что вдруг какой-нибудь дядя из интернета не назовет его Профессионалом. Как это можно пережить?
В той странной вселенной "покрытие тестирования" в строчках считалось разумной метрикой качества кода, за ним следила Служба Контроля Качества и если оно падало ниже 100%, то программиста наказывали. Программист должен был постоянно спрашивать себя "А искренне ли я верю в TDD или готов его предать в первом же аврале?". Вопросы типа "А какие есть аргументы и исследования, которые подтверждают или опровергают тезисы Пророка" считались еретическими. Хуже была только просьба показать успешный проект, созданный Пророком в соответствии с его проповедуемыми принципами. За такое сразу четвертование.
А может этой вселенной никогда и не существовало кроме как в воображении дяди Боба. В любом случае я рад, что не живу в такой вселенной.
> А может этой вселенной никогда и не существовало кроме как в воображении дяди Боба. В любом случае я рад, что не живу в такой вселенной.
насколько знаю он достаточно долго в 70-80х работал в Teradyne, большая компания хорошего уровня и закрытой тематики, вероятно работа была организована на уровне, многому научился, человек умный, дальше решил делать самостоятельную карьеру, типа писать книги и консультировать, все интересней чем на работу каждый день, но это давно уже было, C++, agile, и пр., последние лет 20 типа пропагандист для начинающих, чем и кормится, для общего знакомства по диагонали его книги прочитать не вредно, но это не человек уровня Dijkstra
А можно тоже самое без пафоса и без слишком широких и слишком радикальных заявлений?
Вот про это 100% покрытие всего кода тестами, например. Оно не имеет смысла и существует только в голове автора. Ну и может в каких-то помойках где точно не следует работать.
Может кто-то сюда привести список софта в разработке которого участвовал Роберт Мартин? Желательно посвежее - хотя бы этого десятилетия. Теоретическая теория и измышления это, конечно, хорошо и полезно, но без практики, как мы все знаем, это могут быть единороги в вакууме.
Вот недавно читал книжку, состоящую из статей Джоэла Спольски. В одной из них он упоминал, что фактически программированию в течении дня он посвящает 3 часа. Что мне очень понравилось. Я решил в это безоговорочно верить и следовать (шучу). В любом случае, здесь меня зацепила фраза:
Обязательно следите за сном, здоровьем и образом жизни, чтобы вы могли ежедневно посвятить работе восемь хороших часов.
Я например точно знаю, что не смогу ни 8, ни 7 часов в день заниматься написанием/продумыванием кода, тестов. И у меня возник беспокоящий вопрос: а реально ли вообще 8 часов в день заниматься работой в фактическом смысле, будь то кодирование, разработка архитектуры, управление базой данных?
P.S. Я честно надеюсь, что нет. Я никогда раньше к этому не стремился и сейчас не стремлюсь, тк не считаю это "признаком профессионализма".
Идеальный программист: тезисы