Познал дзен написания автотестов в c#. Тесты я пишу уже довольно давно и помногу, но во основном функциональные/интеграционные, закрывающие функционал проекта в целом. При этом зависел я обычно только от объектов инфраструктуры: баз данных, брокеров сообщений и т.д. Модульные тесты тоже писал, но только на места с неочевидной сложной логикой, которая не помещается в голове.
Перенесемся в мир кровавого энтерпрайза. Представим ситуацию, когда наш сервис ходит по сети более чем в 10 других микросервисов. Куда ходят эти 10 микросервисов чтобы собрать информацию - представить страшно.
Поднимать все это добро каждый раз, когда приспичит проверить бизнес логику - не очень удобно даже в светлую эпоху контейнеризации. Тут на помощь нам приходят моки: обносим источник данных интерфейсом, а дальше в тестах в тестируемый класс с бизнес логикой подсовываем фейковую реализацию интерфейса.
До недавнего времени я пилил эту реализацию сам, но тут проникся двумя инструментами - NSubstitute и Autofixture. Первый позволяет создавать фейковые реализации, второй - инициализировать инстансы классов для возвратов с заполненными полями.
У NSubstitute понравилась возможность легко задавать конкретные кейсы из пар запрос - ответ, очень удобно и никакой логики внутри фейка самому писать (и потом поддерживать) не надо.
Autofixture мне не казалось чем-то нужным, до тех пор, пока мне не пришлось тестировать проброс информации из глубинных слоев наверх, с возвращаемой моделью (в сумме с вложенными классами) в пару тысяч строк. Говоришь: мне нужен объект, поля id, name, userid должны иметь заданные значения. Остальные - заполнятся по усмотрению библиотеки чем-то не-дефолтным. Раз - и объект для теста готов, без бесконечной лапши с инициализацией полей руками.
#csharp
#tests
Перенесемся в мир кровавого энтерпрайза. Представим ситуацию, когда наш сервис ходит по сети более чем в 10 других микросервисов. Куда ходят эти 10 микросервисов чтобы собрать информацию - представить страшно.
Поднимать все это добро каждый раз, когда приспичит проверить бизнес логику - не очень удобно даже в светлую эпоху контейнеризации. Тут на помощь нам приходят моки: обносим источник данных интерфейсом, а дальше в тестах в тестируемый класс с бизнес логикой подсовываем фейковую реализацию интерфейса.
До недавнего времени я пилил эту реализацию сам, но тут проникся двумя инструментами - NSubstitute и Autofixture. Первый позволяет создавать фейковые реализации, второй - инициализировать инстансы классов для возвратов с заполненными полями.
У NSubstitute понравилась возможность легко задавать конкретные кейсы из пар запрос - ответ, очень удобно и никакой логики внутри фейка самому писать (и потом поддерживать) не надо.
Autofixture мне не казалось чем-то нужным, до тех пор, пока мне не пришлось тестировать проброс информации из глубинных слоев наверх, с возвращаемой моделью (в сумме с вложенными классами) в пару тысяч строк. Говоришь: мне нужен объект, поля id, name, userid должны иметь заданные значения. Остальные - заполнятся по усмотрению библиотеки чем-то не-дефолтным. Раз - и объект для теста готов, без бесконечной лапши с инициализацией полей руками.
#csharp
#tests
Продолжая тему модульных тестов в c#. Вляпался в занятную ситуацию с Autofixture. Строки и числа Autofixture заполняет случайными значениями, меняющимися от запуска тестов к запуску. А вот тот момент, что значения булевых полей меняются по другим законам я как-то упустил.
Удаляю я неиспользуемое поле в одном из классов, экземпляры которых я создаю с помощью Autofixture - и тут у меня перестает проходить несколько тестов, при том покрывающих вообще случайные места в проекте. А переименование поля (неиспользуемого) такого эффекта не оказывает.
Первое на что я подумал - что-то где-то закешировалось у меня на компе и тесты заглючили, так иногда бывает. Следующий час прошел в попытках провести экзорцизм над проектом. Не помогло, зато я выяснил что проблема воспроизводится и в пайплайне CI/CD на серверах. Приплыли.
В итоге, оказалось, что генерируемые с помощью Autofixture значения булевых полей не меняются от запуска к запуску тестов, но являются функцией от набора полей в классе. Убрали или добавили поле - значения поехали.
А ошибки полезли из-за того, что я их допустил при написании тестов. Сочетание сгенерированных булевых флагов делало их незаметными, но минус на минус перестал давать плюс и тайное стало явным.
#csharp
#tests
#Autofixture
Удаляю я неиспользуемое поле в одном из классов, экземпляры которых я создаю с помощью Autofixture - и тут у меня перестает проходить несколько тестов, при том покрывающих вообще случайные места в проекте. А переименование поля (неиспользуемого) такого эффекта не оказывает.
Первое на что я подумал - что-то где-то закешировалось у меня на компе и тесты заглючили, так иногда бывает. Следующий час прошел в попытках провести экзорцизм над проектом. Не помогло, зато я выяснил что проблема воспроизводится и в пайплайне CI/CD на серверах. Приплыли.
В итоге, оказалось, что генерируемые с помощью Autofixture значения булевых полей не меняются от запуска к запуску тестов, но являются функцией от набора полей в классе. Убрали или добавили поле - значения поехали.
А ошибки полезли из-за того, что я их допустил при написании тестов. Сочетание сгенерированных булевых флагов делало их незаметными, но минус на минус перестал давать плюс и тайное стало явным.
#csharp
#tests
#Autofixture
🔥3
Небольшое наблюдение. Сейчас идёт седьмой крупный (от шести месяцев полной моей занятости) проект за мою карьеру в IT. Из них на трех у меня была полная свобода в плане написания тестов и возможности тянуть резину двигать сроки релиза.
Что характерно - именно эти три проекта, когда пришло время, просто запустились с минимальным предрелизным безумием. А все, где тестов не было - запускались с нервотрепкой и вычерпыванием бесконечного числа багов. При этом, основательный подход к разработке удлинял время от старта проекта до первого запуска в препрод процентов на 50-60. Вроде бы много.
Но если вспомнить, сколько времени проходило на оставшихся четырех проектах от первого запуска до состояния "работает приемлимо", то получается что на авральную пусконаладку уходило за 30% времени разработки. При том к концу её код обрастал костылями, затыкающими дыры, а я выдыхался до состояния выжатого лимона и терял в производительности на пару тройку месяцев или вообще менял работу.
#csharp
#tests
Что характерно - именно эти три проекта, когда пришло время, просто запустились с минимальным предрелизным безумием. А все, где тестов не было - запускались с нервотрепкой и вычерпыванием бесконечного числа багов. При этом, основательный подход к разработке удлинял время от старта проекта до первого запуска в препрод процентов на 50-60. Вроде бы много.
Но если вспомнить, сколько времени проходило на оставшихся четырех проектах от первого запуска до состояния "работает приемлимо", то получается что на авральную пусконаладку уходило за 30% времени разработки. При том к концу её код обрастал костылями, затыкающими дыры, а я выдыхался до состояния выжатого лимона и терял в производительности на пару тройку месяцев или вообще менял работу.
#csharp
#tests
❤7🔥4👎1😁1