Итак, я пытаюсь войти в TDD с React. Везде, где я читал о тестировании в целом, всегда подчеркивалось, что мы хотим тестировать только поведение, а не детали реализации. Звучит хорошо, но затем, просматривая некоторые примеры, я нахожу такие вещи:
expect(onSubmit).toBeCalledTimes(1)
Это ли не деталь реализации? Должен ли я действительно заботиться о том, вызывается ли функция с именем «onSubmit»? Что, если завтра он изменится на «onFormSubmit»? Или что, если функция пуста? Тест все равно пройдет...
Не следует ли вместо этого проверить, выполняется ли все, что должно делать onSubmit? Например, проверить, изменился ли элемент DOM или что-то в этом роде...
Клянусь, это настоящее путешествие — пытаться постигнуть искусство написания тестов (вообще, не только в React).
Мы должны протестировать компонент пользовательского интерфейса с точки зрения пользователей. Пользователей не волнуют детали реализации, их интересует только пользовательский интерфейс (вывод компонента). Утверждение проверяет детали реализации. Если мы рефакторим наш компонент, в дальнейшем вывод компонента не изменится, то наши тестовые примеры должны пройти без изменений.
Если вы хотите избежать тестирования каждой детали реализации и тестировать только то, что волнует пользователя, вам нужно будет провести сквозное тестирование с помощью такого инструмента, как Cypress, на реальном бэкэнде и реальной базе данных. Реализм этих тестов имеет большое значение. Но есть и недостатки: они могут быть медленными и менее надежными, поэтому полностью покрыть ими все пути кода большого приложения нереально.
Как только вы переходите к тестированию компонентов, вы уже тестируете некоторые вещи, которые не волнуют пользователя: если вы передаете реквизиты компоненту или имитируете бэкэнд, пользователю все равно на эти реквизиты или API бэкэнда. Но это выгодный компромисс, поскольку он позволяет проводить более быстрые тесты, охватывающие больше пограничных случаев.
В тестах компонентов я бы рекомендовал тестировать входы и выходы компонента. Если функция onSubmit определена внутри функции рендеринга вашего компонента, я бы не стал запускать против нее утверждение; это определенно деталь реализации. Вместо этого я бы проверил результат работы этой функции. Но если onSubmit передается как реквизит функции, то я бы передал фиктивную функцию и проверил, что она была вызвана, да. Если это функция, определенная в другом модуле, все становится более размытым: вы можете решить, хотите ли вы имитировать этот модуль или протестировать реальную реализацию этой функции.
В тестировании всегда есть компромиссы; выше приведены некоторые из вещей, которые вы можете учитывать при принятии решения о том, как тестировать конкретный случай.
Я бы проверил, что происходит после успешной отправки / или с ошибкой - может быть фиктивный сервер и увидеть сообщение об успехе или ошибке на экране ... Или я могу что-то упустить 🤔