All streams
Search
Write a publication
Pull to refresh

Comments 7

Спасибо за статью! Но так и не понял, в чём плюс использования msw в тестах :)

В Вашем примере тест зависит от написанного хендлера в msw, о котором из теста явно не известно вообще ничего

Да и к тому же, зачем поднимать «сервер» для тестов

Моё мнение: каждый тест должен быть самодостаточным. Это значит, что в каждом тесте должен быть мок запроса (конкретно реализация мока зависит от того, что вы используете, будь то fetch, axios или какой-нибудь gql-клиент). Ну или в каждой группе (дескрайбе), если тест-кейсов несколько на один и тот же набор данных

В общем так: есть фикстуры для тестов (наборы различных данных или функции для генерации нужных наборов данных); есть тест, в котором используются эти фикстуры в имплементации мока запроса; если практикуете параллельное программирование, то можно использовать ранее подготовленные для тестов фикстуры уже в хендлерах msw (ну или наоборот, если вы сначала реализуете компонент с моками на msw, а потом уже пишете тесты)

А вот сам по себе msw хорош, особенно для тех, кто практикует tdd и контрактное программирование (tdd тут не потому, что в тестах надо использовать msw, а потому, что на этапе подготовки тестов уже будут подготовлены фикстуры, которые можно использовать в хендлерах msw)

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

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

Пока такая схема работает, продолжаю вести наблюдение =)

Независимая от бекенда разработка и написание тестов почти никак между собой не связаны. Msw используется в development-режиме только для удобства разработки (либо пока бекенд не готов, но есть контракт, либо даже если бекенд готов, но просто надо подставлять определённые наборы данных, например, чтоб не идти по реальным юзкейсам и не заводить что-то там у своего пользака). Завязывать тесты на моки msw, как по мне, идея сомнительная.

Попробую ещё раз объяснить, почему же:

  1. В рамках теста не мокается внешнее API. В рамках теста выполняется реальный запрос. А вот этот реальный запрос ловит «локальный сервер». Это значит, что для запуска тестов необходимо поднять тестовый сервер, который имеет необходимые замоканные роуты. Да и зачем для каждого теста поднимать весь этот сервер со всеми моками роутов (а исходя из статьи вы запускаете сервер именно в сетап-файле, который выполняется перед запуском каждого тест-файла)..? Не имеете ли вы случайно проблем со времени выполнения тестов? Тут ещё, конечно, важно было бы подметить, какое количество тестов у вас имеется (так как если их условно 200, то, конечно, вы особо не заметите просадок из-за этого). Из этого всего пункта имеем: повышенное потребление ресурсов и увеличение времени выполнения тестов. А этого нам уж точно не хочется видеть, так как тесты уж явно хочется гонять не только локально, но ещё и на ci

  2. Проблема неявности. Тут просто повторюсь, так как разжёвывать особо нечего: в ваших тестах при таком подходе не описана имплементация мока запросов, что усложняет координацию во время добавления/изменения/удаления/рефакторинга/любойдругоймодификации тестов и повышает связанность — тест зависит от вендора (в данном случае msw) и, более того, от реализации обработчика запросов в конкретном обработчике msw (как будто бы не очень хотелось получить связанность между msw, который используется для dev-режима и тестами, не так ли?)

Как мне показалось писать мок в msw, а потом еще и в тесте - расточительно и было принято решение все мокирование вынести в отдельный модуль

А вот по этому поводу я как раз и писал про переиспользование фикстур между реализацией msw-обработчиков и тестами. Либо вы не дочитали, либо не так поняли :)

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

А вот тут, извините, но совсем не понял этот поинт. Каким образом ваш подход овер мока запроса в тесте позволяет тесту стать «чище»? Ведь даже при вашем подходе, если проверять несколько юзкейсов, так или иначе вы будете описывать имплементацию мока в тесте (ну да, в вашем примере вы просто опишете ответ для эндпоинта сервера, но разницы между этим абсолютно никакой со стороны количества кода)

Подчеркну: я не пытаюсь вас переубедить не делать так, как вы делаете. В каждой системе свои правила и удобства выстраиваются в зависимости от тех, кто над этой системой работает. У меня посыл такой: если вы видите решения описанных мной проблем (или не видите проблем в этом вовсе) — настаиваю на том, чтобы вы конструктивно описали это (либо решения, либо почему это не является проблемами). И, да, тут «конструктивно» будет даже с точки зрения вашей системы, что может не совпадать со всеми остальными. И это не будет означать, что у вас (или у нас) что-то не так, просто к каждой системе свой подход :)

Надеюсь, я правильно донёс свои мысли. Спасибо за ответы!

Независимая от бекенда разработка и написание тестов почти никак между собой не >связаны.

Согласен.

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

Нет, сервер запускается 1 раз. На текущий момент у меня всего около 400 тестов ~ 1 минуты, и пока просадка не замечена (что может объясняется малым количеством тестов). Тут надо провести тесты, мокирование внутри теста - то же не бесплатное.

в ваших тестах при таком подходе не описана имплементация мока запросов, что усложняет координацию во время добавления/изменения/удаления/рефакторинга/

...

Каким образом ваш подход овер мока запроса в тесте позволяет тесту стать «чище»

Хм, я имел ввиду, что мы производим действие (клик по кнопке поиска) и проверяем, корректность рендера ответа, не проверяя параметры функции (этим пусть занимается TS). У нас на проекте, не часто требуется мокировать функции под разное использование, поэтому из теста убирается код мокирования функции и это я назвал "чистотой".

А вот по этому поводу я как раз и писал про переиспользование фикстур между реализацией msw-обработчиков и тестами. Либо вы не дочитали, либо не так поняли :)

Я понял =) Да подход рабочий, как раз для проверки рендера они импортируются.
И да, получается, что остается только описать мок функции и всё наше обсуждение будет закончено =)

...реализации обработчика запросов в конкретном обработчике msw (как будто бы не очень хотелось получить связанность между msw, который используется для dev-режима и тестами, не так ли?)

Это пожалуй, самый важный момент, я бы сказал киллер аргумент =) Тут мне возразить нечего, по уму, да, тесты надо изолировать от внешних зависимостей, но тогда надо бы убрать TS, createTestingPinia, msw и тд. - скажем так, на это зло я пошел намеренно осознавая последствия =).

Подытожу:
1 - спасибо за комментарий, вы заставили задуматься о возможной будущей проблеме времени выполнения (и пока тестов не много можно поправить =)) А так же про разделение ответственности, пожалуй еще раз взвешу плюсы и минусы.

2 - msw можно использовать в тестах, но не обязательно, как и использование любого другого инструмента имеет свои сильные и слабые стороны.

3 - Мне очень импонирует ваш подход в разделении ответственности, буду рад продолжить обсуждение =) Можете описать как у вас организовано unit тестирование, как разбросано по папочкам, сколько тестов и время их выполнения.

Нет, сервер запускается 1 раз

Вы запускаете его в сетап-файле (setupFiles). Сетап-файлы запускаются каждый раз на каждый тест-файл, а не перед всеми тестами. Это как и в джесте, так и в витесте работает

Из документации витеста
Из документации витеста

Тут мне возразить нечего, по уму, да, тесты надо изолировать от внешних зависимостей, но тогда надо бы убрать TS, createTestingPinia, msw и тд.

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

Можете описать как у вас организовано unit тестирование, как разбросано по папочкам, сколько тестов и время их выполнения

В двух словах это полностью не опишешь, а слишком много писать, простите, лень :)

Сколько время выполнения тестов? - много. Очень много. Поэтому я это всё и написал. К сожалению, не можем получить столько ресурсов, чтобы это всё отрефакторить и оптимизировать, так как это дорого. Сейчас около 3 тысяч тестов. Это на все проекты (у нас много модулей). Много из них мусорных, много из них неправильно написанных. Какие-то из них на джесте, какие-то — на витесте (в процессе переезда на витест). Если суммарно считать время их выполнения (считаем на ci, а поэтому оно ещё больше), то будет примерно минут 20 (да, локально это может превратиться в минут 10, а то и меньше, но нам важен ci этап).

Спасибо, за развернутый ответ. Есть над чем подумать

Sign up to leave a comment.

Articles