Обновить
0

Java backend developer

Отправить сообщение

Еще на тему стабильных тестов, которые не ломаются от каждого чиха:

https://www.youtube.com/watch?v=URSWYvyc42M&ab_channel=Confreaks

Да, и если вам не особенно интересна тема TDD, то скорее всего действительно не стоит тратить время и деньги.

James Shore очень толковый чел, +1.

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

Тут нужно показывать не самый простой проект, написанный по TDD с тестами, которые ничего не знают про имплементацию проверяемой функциональности, то, как написаны тесты и то, как они при этом помогают рефакторингу. Из того, что на эту тему есть в сети, мне JBrains с лету приходит в голову вышеупомянутый (у него есть курс The World's Best Intro to TDD, действительно очень качественное введение в TDD), хотя наверняка есть и другие примеры. Но они вряд ли будут маленькими.

Я чтобы этому научиться уже не первый месяц в свободное время пишу код в паре с людьми, которые давно (некоторые по 20 лет и больше) в этой тусовке и участвую вместе с ними в mob programming сессиях.

Поэтому я тут наверно только могу порекомендовать, куда копать, если дальше интересно. Копать в сторону decoupling тестов от имплеметации. Про это есть целая школа TDD (Chicago, classicist). Можно про них почитать, можно посмотреть курс JBrains, у которого хорошо показаны тесты на фукнциональность которые не завязаны на конкретную имплементацию, есть хорошая статья про это у Martin Fowler "Mocks Aren't Stubs" (https://martinfowler.com/articles/mocksArentStubs.html), и еще вот тут есть отличный ответ на ту же тему от perfectionist https://softwareengineering.stackexchange.com/questions/5898/how-do-you-keep-your-unit-tests-working-when-refactoring (начинается "Contrary to the other answers...").

Еще из людей, у которых скорее всего это можно увидеть на видео, вроде бы у Uncle Bob были примеры, он тоже классицист TDD-шный, хотя я не особый его фанат. У Geepaw Hill есть хорошие видео. Еще приходит на ум James Shore, у которого тоже много хороших видео в свободном доступе и можно найти примеры хорошего кода на JS с TDD.

Упс, только я тоже ежа с апельсином спутал выше. Про mockist vs classicist TDD школу, мокисты - это Лондонская школа. : ) Чикаго - classicist и как раз они тестируют все через state и избегают знания имлементации. Сорри!

Я люблю тесты, пишу их сам и заставляю других по возможности, у меня проблема только с TDD

Я тоже в общем-то большую часть жизни так работал. Пишешь код, потом несколько дней на тесты. И это обычно очень унылые несколько дней; я очень ответственный человек, поэтому пишу несмотря на то, что мне при этом скучно и уныло.

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

Так вот самым сильным аргументом для того, чтобы попробовать TDD еще раз, на этот раз с наставником, стало то, что TDD is more fun. Писать тесты вместе с кодом - занятие гораздо более веселое и интересное. И для меня это реально оказалось так.

Плюс в работе сильно помогает быстрый фидбек от тестов; я раньше постоянно запускал программу, чтобы проверить, что все работает. Фидбек от тестов в разы быстрее и более того, автоматический -- не нужно переживать, что ты что-то сломал во время рефакторинга и перепроверять снова и снова то, что ты уже раньше протестировал ручками.

У меня на практике обычно вот эта часть, что вы назвали "через добавление 10 ифчиков, а потом заменяете это на нормальный алгоритм" вызывала трудности, т.к. "нормальная" реализация всегда приводила к переименованию\удалению интерфейсов\классов\методов\аргументов, перестройке всей структуктуры кода. После чего все ранее написанные тесты грубо говоря проще выкинуть и написать заново. Как вы с этим боролись?

Декаплингом тестов от имлементации (тест не должен знать, как именно тестируемая фукциональность имлементирована, т.е. не должно быть verify (проверок вызова метода зависимого класса внутри тестируемой функции) и очень помогает сильно ограничить использование автомокеров). При этом подход к тестам довольно сильно меняется. Вместо того, чтобы писать тестовый класс на конкретный класс реализации (например, Multiplier -> MultiplierTest, 1:1), тест пишется на конкретную функциональность ("умножение чисел").

Функциональность - это как раз то, что скорее всего будет оставаться гораздо более стабильным, чем реализация; ведь вы эту фичу не просто так добавили, а потому что бизнес/пользователи попросили. Вы можете и скорее всего дальше будете её усложнять, но нечасто просто выкините саму фичу из того, что делает ваша программа.

Я в общем только очень недавно увидел, что такое бывает, и это офигительно. Рефакторишь код так, что уже давно прошел все пределы того, когда тесты, написанные по-старому, уже бы тысячу раз сломались "не по делу", а тесты тебе вместо того, чтобы мешать, помогают и подскзаывают, если ты действительно чего-то сломал. Но если не сломал, а просто поменял структуру кода - они не ломаются. Для меня это был полный снос башки.

Хороший пример того, как это делается, можно посмотреть в TDD курсе у J.B. Rainsberger (JBrains).

Конечно тут же встает вопрос, что такое юнит и что такое юнит тест, и в этот холивар я точно лезть не хочу : )

+1 к "Вот только все эти абсолюты к самому TDD имеют мало отношения, разве нет".

Владимир, вас, похоже, сильно травмировали, возможно не очень адекватные коллеги. Бывает.

Но у вас реально очень превратные представления о TDD, которые к реально практике отношения имеют очень мало от слова совсем.

  1. 100% покрытие вообще не является целью TDD. Это глупо и никому не нужно, потому что вот именно в этом случае придется писать совершенно нелепые тесты на сеттеры и геттеры и прочую ерунду. См. ссылку на то, как пишет тесты Кент Бек, которую давали выше. Никто из тех, кто работает по TDD из тех, с кем я лично общаюсь, не считает 100% покытие полезным, более того, в целом тестовое покрытие - метрика неоднозначная и проверяет только то, что бранч был вызван. Ничего про качество теста, вплоть тупо до наличия ассерта, оно не говорит.

  2. Тесты как документация не является целью TDD! Совсем. Вы не с BDD перепутали?

  3. Насчет того, что все примеры, которые приводят сторонники TDD, простые. Есть стримеры, которые показывают, как они работают над серьезными проектами и следуют TDD, есть видео, которые эти люди записывают и показывают. Из известных людей Uncle Bob, менее известных можно легко нагуглить при желании.

  4. "Да, и что бы 2 раза не вставать замечу, что когда тесты покрывают код целиком и полностью, не оставляя живого места, любая попытка изменения функции или ее интерфейса приводит к дикому баттхёрту." - а вот это очень интересная тема. Дело вообще не в тестах, дело в моках. Есть две школы TDD, Чикагская и Лондонская. Чикаго - "мокисты", которые изолируют каждый класс и мокируют все зависимости. Лондонская школа избегает того, чтобы тесты знали, КАК метод делает то, что он делает - они проверяют только результат! И при таком подходе тесты - первейший инструмент рефакторинга, который помогает менять код, не ломая его. В этом собственно и основной смысл тестов.

  5. "TDD позволяет сформировать хорошую архитектуру на ранних этапах, которую потом почти не придется менять (как и код), ибо TDD заставляет подумать до написания кода". TDD помогает писать код, который легко тестировать (юнит тестами, да). Задачи не менять её не стоит вообще! Совсем наоборот, при добавлении любой фичи - смотришь на то, а не поменялось ли чего более глобально, как эту фичу встроить; рефакторишь всегда! И тесты, если ты их сохранил гибкими и не знающими имлеметации того, что они тестируют, очень в этом помогают.

  6. "Юнит тесты хорошо, а другие – плохо". Ну блин. Откуда вы это взяли? То, что есть тестовая пирамида, не означает, что не нужно ничего, кроме юнитов. И опять же, TDD тут мало при чем.

  7. "Вот только легко тестируемый код не дает никаких гарантий качества получившегося приложения." - какие-то дает, но конечно не панацея. Если сначала не поговорили с клиентом или поговорили криво и сделали не то, то все в помойку.

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

    TDD очень обманчиво кажется простым и поэтому многие считают, что уже все про TDD поняли. На практике начиная пробовать TDD натыкаешься на кучу вопросов и проблем. Поэтому самый лучший вариант реально научиться и попрбовать - это поработать с кем-то, кто уже в этом реальный профи. Тогда и вопросы можно задать.

    Одна из интересных неупомянутых проблем, например, это что делать, чтобы не писать в помойку. Обычная тема новичка - написать отличный класс, который потом окажется вообще не нужным, и его придется целиком выкинуть. Существуют возможности делать наброски даже по TDD, нащупывать первоначальную архетектуру - которую потом тридцать раз может быть поменяешь - которые помогают этого избежать.

Информация

В рейтинге
Не участвует
Откуда
Seattle, Washington, США
Зарегистрирован