Обновить
4
0
Fett Teufel@DasMeister

Кодерок

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

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

У всего приложения вы не поменяли поведение (возможно), а у компонента для которого был комплект малых тестов - да.

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

Да вы действительно правы, что R-G фаза набор экспериментов с кодом, не связанная с рефакторингом. Однако изначально Кент Бек вкладывал в неё свой личный подход и просил не возводить его опыт в догму.

Не для каждого кода нужно получить фазу red в начале. Она была нужна в 2000 году, т.к. у них не было инструментария который позволял работать иначе.

Например сейчас я могу задекларировать в IDE функцию/метод с сигнатурой и выбросить исключение "Not Implemented", нажать комбинацию клавиш и мне сгенерируется тест сьют, нажать пару раз tab и получить тест вызывающий нереализованную функцию.

Это всё ещё TDD или нет? Если нет - добро пожаловать в догматики и ваше дело проиграно. А если да, то вы нарушили свои же утверждения - пропустив ненужную фазу.

Часть кода вообще не имеет смысла тестировать описывая контракт до того как сформирован код. Существует проксируемый код. Например бизнес-сервис который вызывает единственный метод репозитория. Совершенно всё равно в какой последовательности вы это сделаете.

И все эти "исключения" существуют в рамках понимания того, что вы делаете. Если вы знаете какой код вы пишете, можете писать его до теста. Главное войти в цикл eventualy. Но если вы пишете код который не понимаете как должен работать, то в цикл надо входить до него.

Пример для объяснения предыдущего абзаца:

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

Иными словами TDD это про итерации в первую очередь, а не про то в какой последовательности они выполняются. Единственное что важно, что перед рефакторингом вы должны оказаться в зоне "GREEN".

Мне вот любопытно. А сколько вы проработали на одном месте, где потворствовали идее писать функциональные тесты. Лет 5-10 удалось хотя бы?

Вот прямо на месте написания кода, а не повышения в тимлиды, архитекоры, руководители групп и так далее?

Текст вашего комментария просто в каждом пункте демонстрирует не понимание проблем которые таким образом создаются.

 Простой, чистый и понятный код -- это и есть способ проектирования.

Не существует простого и чистого и понятного кода.

Код бывает или примитивный - т.е. многословный и монотонный, что приводит к пропуску ошибок - т.е. не бывает понятным (только создаёт такое впечатление). Либо бывает с когнитивной нагрузкой - библиотеками и/или DSL. Что сразу перестаёт быть "простым", зато становится понятным.

Чистый код, это сотни итераций рефакторинга, которые и создают в итоге элегантность и чистоту. Но хотелось бы посмотреть как вы отрефакторите какой-то компонент и воспользуетесь "функциональными тестами" и хотелось бы глянуть, сколько времени это займёт.

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

Тесты не обнаруживают ошибки. Тесты фиксируют поведение и ожидания - создают контракт. Они документируют то, что ожидается от кода. Это и есть контракт вашего компонента, а не "соблюдение API".

Потому что если вам репортирует клиент - он может уже быть мертвым в некоторых ситуациях. А в других - его бизнес будет мертв.

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

Я зарабатываю на рефакторинге. Каждый раз когда мне нужно что-то отрефакторить я беру это и делаю. А вот проекты у которых 0% покрытия и 5 лет разработки, после которой кодер стал архитектором - в них вот никогда ничего не рефакторят.

т.к. никому не уперлось возиться мегабайтами свалившихся тестов, при всем при том, что это лишь внутреннее архитектурное изменение, которое не трогает заявленный функционал

Всё верно. Именно поэтому существует Open Close Principe. Который говорит - создай новое поведение, а не меняй старое. Если комонент перестает работать в рамках контракта тест упадёт, т.к. функционал компонента - изменился. Создайте новый компонент и выведите старый из эксплуатации.

Изменение же поведения 1 компонента не приводит к развалу всего стека, только самого компонента и i9n теста. Ну. Если вы умеете конечно программировать и писать чистый код, о котором упоминали. Тот у которого всегда - Single Responsibility. Благо это не сложно, для тех кто в продуктовых командах то работает.

Вы не правы. Важна не последовательность код->тест->рефакторинг. А важна последовательность red-green-refactoring.

Кент Бек это много раз демонстрирует в своей книге. Получите красный тест, почините проведите рефакторинг снова получив красный тест.

Рефакторинг это и не только классическое изменение формы, но и собственно написание кода, который в текущем окне контекста приведёт к красным тестам. После чего он сам идёт и уточняет тесты.

В TDD не важно, что предшествует тест или код, важно пойти в цикл Green-Red-Refactoring.

Без перебора не обойтись, мелкая тактика в игре присутствует. Сейчас с нейросетью скрещены уже счетные движки (тот же стокфиш уже гибридный движок). Но и без гибридизации нейросеть играла лучше алгоритмических счетчиков и лучше людей. А алгоритмические движки играют гораздо сильнее человека (ни один человек не может стокфиш 10 летней давности победить).

Конечно AZ и LCZ знают что они играют в шахматы. Я как шахматист, тоже в целом знаю, что играю в шахматы и правила и форма игры является частью нейросети моего мозга связанной с этой формой деятельности.

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

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

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

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

А авторитет нет. Может быть у фонда и есть чутьё на идеи, но вот каковы будут итоговые реализации - статистики нет. Может быть и крах инкубатора, а может быть и ещё более успешный взлёт.

Так и сколько из них уже сделали вайбкодингом?

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

Дети в 8-10 лет уже гроссмейстерами становятся. Те у кого 1300 в этом возрасте не имеют будущего в шахматах совершенно. Почему это вообще должно быть ориентиром для оценки, если LLM закончат партию (по турнирному кодексу) поражением против кого угодно, сделав 2-3 невозможных хода - решительно не понятно.

Нет, именно нейросеть: https://lczero.org/

Нейросетьдавно играет на несколько порядков сильнее любого человека в шахматы. Это решённая проблема и один из механизмов приведших к созданию LLM.

Задача LLM в целом понятна уже года полтора два и прозрачана. Создать интеллектуальный поисковые алгоритм по общим и специфическим знаниям, для того, чтобы после подборки короткой и (местами) галлюционирующей выборки уточнить сведения.

Весь этот шум вокруг одного кольца чтобы заменить их всех не стоит и выеденного яйца. До создания AGI программный код не сможет рассуждать. Т.к. в конечном итоге мозг как совокупность принимающая решения и рассуждающая это в первую очередь множественная совокупность нейронных сетей которые могут взаимодействовать.

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

В нашем примере один интеграционный тест покрывает код всех компонентов, тестирует их взаимодействие, а также код middlewares, ORM и реальные sql-запросы в реальной базе данных. Такую глубину тестирования невозможно было бы достичь, если бы мы использовали тесты с моками.

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

А одна из ваших целей - иметь быстрые тесты. Правда под их "скоростью" вы подразумеваете:

  • Быстрыми — чтобы их удобно было запускать локально и в CI.

А уже в комментариях со мной утверждаете, что 5 секунд это быстро, потому что где-то ещё дольше.

Количество i9n тестов зависит не от эндпоинтов, а от комбинаторной сложности входных параметров и числа поведенческих сценариев тестируемой системы.

Вообще главный критерий числа тестов - это цикломатическая сложность тестируемой системы. Это вообще минимальный набор тестов который у вас должен быть.

 Вот у меня есть проект где около 70 интеграционных тестов и они прогоняются за 16 секунд. Если бы я захотел их улучшить, то в первую очередь я бы сократил их количество, а не скорость выполнения.

И как же вам поможет это сокращение? Вот их ускорение до 2 секунд очевидно что даст - скорость итерации процесса Green-Red-Refactoring.

P.S. Джим Коплинг не может быть аппеляцией к авторитету. У него нет авторитета в обсуждаемой области никакого, кроме работы в консалтинге. Ну и для меня ни он, ни его книги не авторитетны.

Это ограничит всё же возможности использования отладчика, а это неоспоримый плюс TDD. Особенно в го.

Т.к. написав статью с развенчанием одного из подходов и рекомендацией другого, вы выступили экспертом, мне было любопытно, как вы решаете обозначенную мной проблему - т.к. она влияет на time to market непосредственно.

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

Негипотетический финтех сервис, поддерживаемый 3 разработчиками за полгода оброс 1200 тестами. Вы предложили этой команде убрать все моки и заменить их - интеграционными тестами. Каждый из которых будет линейно исполняться 5 секунд (суммарно 100 минут - 3 часа+).

Часовая авария обойдется компании в 2 миллиона долларов неполученной прибыли. Вы предложили. потратить 6 миллионов долларов на деплой quick fix'a. Лучшие решения, что я видел в исполнении других пропогандистов i9n-only тестирования работали примерно такое же количество времени.

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

У нас крайне странный диалог выходит.

Я задал вам параметризированный вопрос. Ответ и решение которого у меня есть (в виде специализированной библиотеки: https://github.com/godepo/pgrx).

Вы же не предлагаете никакого рецепта и лишь общение с чатгпт.

Если бы я хотел поговорить с низкоквалифицированным специалистом, вместо эксперта с креативным мышлением. Я бы с этим справился без комментариев на хабре :)

Но пить чай за счёт работодетля, конечно удобно. Спорить не буду.

Ваша статья имеет два контекста.

Первый, это декомпозиция кода в предметные языки (у вас билдер запросов, как я понимаю SQL - что иронично само по себе т.к. SQL предметный язык) и функции трансформации (маппинга). Этот контекст результат того, что вы воообще видимо пытаетесь тестировать хоть что-то. Посыл в целом верный, т.к. вынесение сложности с уровня кода в слой библиотек и предметных яызков - признак формирования в целом взрослого понимания того, что значит писать код.

Второй контекст, это отрицание смысла в мок-объектах, т.к. дескать поведение проверять не нужно. И это демонстрация инфантильности (детского взгляда на проблему), т.к. вы пытаетесь подменить назначение кода тестов неверным полагание их назначения, как и самого кода.

Тестирование на моках, позволяет создать контракт и описание того, как работает тестируемая система (функция, компонент, всё приложение) с точки зрения автора. Мок превращает функцию, которую невозможно превратить в чистую, в таковую.

Однако это не убирает смысла в i9n тестах против постгреса (почему я вас и просил продемонстрировать вашу способность как автора монументальных картинок в статье) на уровне юнита (модуля репозитория). Т.к. это позволит разработчику написать код на языке, который невозможно верифицировать (SQL) без языка приложения (go) в момент написания собственно модуля.

Здесь они смысл имеют и значимый. Т.к. позволяют верифицировать чистую функцию на предметном языке ( SQL). Эту функцию невозможно проверить штатными средствами её языка, а отложить её верификацию до сборки приложения целиком, может обернуться неверными эстимейтами и провалами сроков.

И вот тут важным становится мой вопрос вам в треде ниже - как запускать группы таких тестов за критически малое время с идемпотентным результатом и у разработчика и в CI.

Если верификационная группа будет у вас 5 минут работать только на уровне 1 юнита, то на уровне всего приложения 500-700 тестов у вас будут выполняться половину дня. И такого рода тесты становятся БЕСПОЛЕЗНЫМИ для разработчика.

Ну и напоследок. Го (особенно в контексте ваших же диаграмм в статье), это язык про поведение и побочные эффекты. Тестирование данных бессмысленно как таково. Любая функция с побочным эффектом, это всегда - поведение.

Именно поэтому данные (и их декларации в виде описаний структур) это существительные. А методы (или функции) это глаголы. Поэтому тестируя любой действующий юнит - вы тестируете в первую очередь поведение. А верифицируете его через результат ЕГО жизнедеятельности - в виде side effect.

Поэтому финальная часть вашей статьи - это бессмыслица.

Ну т.е. 100 регулярных тестов (модульных) с интеграцией на 30-40 методов репозитория вы будете натурально выполнять 5 минут и считаете это нормальным.

Правильно ли я понимаю, что вы не знаете как сделать такию группу тестов работающей за обозримое время в пормежутке до 4 секунд (максимально комфортное время исполнения любой группы тестов. после которого они начинают вредить вредить и замедлять работу)?

А ваши замечательные тесты могут работать все одновременно?

Мок в первую очередь и верифицирует данные, а не поведение. Устраняя побочные эффекты и превращая функцию в определенном смысле в чистую.

Код вашего GPTChat линейно скалируется по времени от числа тестов. У меня есть пакеты с постгресом где 100 тестов отрабатывают примерно 0.6 секунды. В вашем случае с вашим примером эти замечательные тесты отработают за 300 секунд. Выглядит как антиреклама тестированию.

Я бы не задавал вопрос, если бы не знал ответ. Но вот в статье где РЕКОМЕДНУЮТ не использовать моки им уделено много времени, а вот демонстрации силы интеграции - нет.

Информация

В рейтинге
Не участвует
Откуда
Москва, Москва и Московская обл., Россия
Дата рождения
Зарегистрирован
Активность