[JavaScript, Тестирование мобильных приложений, ReactJS] Моки не кусаются! Осваиваем мокинг с React Testing Library (перевод)
Автор
Сообщение
news_bot ®
Стаж: 6 лет 9 месяцев
Сообщений: 27286
Перевод статьи подготовлен в преддверии старта курса «Автоматизация тестирования на JavaScript».
Моки — не кусаются!
Они предназначены помочь вам создавать более простые и надежные тесты. В этой серии статей я продемонстрирую вам паттерны, на которые я опираюсь при написании моков (mocks или “заглушек”) компонентов React.
Вот наглядный пример заглушки компонента. Я использую jest.mock, который мы рассмотрим подробнее ниже.
jest.mock("../src/PostContent", () => ({
PostContent: jest.fn(() => (
<div data-testid="PostContent" />
))
}))
Типичная заглушка React компонента не должна выглядеть сложнее. Следует обратить внимание на очень простое значение-заглушку (div) и атрибут data-testid, который позволяет нам очень легко найти в DOM отрисованный экземпляр. По соглашению, используемый тестовый идентификатор должен совпадать с именем компонента. В данном случае это PostContent.
Прежде чем мы рассмотрим, как они используются, давайте сначала вспомним, что такое моки и почему вы вообще можете захотеть их использовать.
Что такое мок?
В мире JavaScript термин mock очень широко применяется для обозначения любой имитированной реализации или тестового двойника (test double). Имитированные реализации — это просто значения, которые заменяют другие в вашем производственном коде во время выполнения тестов. Они примеряют на себя интерфейс заменяемого объекта, так что остальная часть вашего кода работает так, как если бы никакой замены не было.
Есть несколько разных причин, по которым вам может это понадобиться; мы рассмотрим их на примерах.
Если вам интересно узнать больше о имитированных реализациях, почитайте книгу Мартина Фаулера «Моки — не заглушки».
Jest и мокинг
В Jest есть функция jest.mock, которая позволяет мокать целые модули, которые вы заменяете. В этом руководстве я сосредоточился именно на этой функции, хотя в JavaScript есть и другие способы замены объектов.
В книге Mastering React Test-Driven Development я использую импорт именованных модулей ES6 для создания тестовых двойников. Такой подход дает немного больше гибкости, но выглядит слегка более хакерским.
На странице Jest про jest.mock говорится, что моки гарантируют, что ваши тесты будут быстрыми и не хрупкими.
Хотя это правда, это не основная причина, по которой я использую моки.
Я использую моки, потому что они помогают мне поддерживать мои тесты независимыми друг от друга.
Чтобы понять, почему это так, давайте рассмотрим пример.
Почему моки?
Ниже приведен листинг компонента BlogPage, который выполняет две функции: он извлекает id из свойства url и затем отображает PostContent компонент с этим id.
const getPostIdFromUrl = url =>
url.substr(url.lastIndexOf("/") + 1)
export const BlogPage = ({ url }) => {
const id = getPostIdFromUrl(url)
return (
<PostContent id={id} />
)
}
Представьте, что вы пишете тесты для этого компонента, и все ваши тесты включены в BlogPage.test.js, который представляет собой единый набор тестов, покрывающий компоненты BlogPage и PostContent.
На этом этапе моки вам еще не нужны: мы еще не видели PostContent, но, учитывая размер BlogPage, действительно нет необходимости иметь два отдельных набора тестов, поскольку BlogPage — это в целом просто PostContent.
Теперь представьте, что и у BlogPage, и у PostContent прибавляется функциональность. Вы, как одаренный разработчик, каждый день добавляете все больше и больше функций.
Поддерживать тесты в рабочем состоянии становится сложнее. Каждый новый тест имеет более сложный сетап, и набор тестов начинает поедать все больше вашего времени — бремя, которое теперь необходимо поддерживать.
Это распространенная проблема, и я все время вижу ее в кодовых базах React. Наборы тестов, в которых даже простейшее изменение результирует в сбоях многих тестов.
Одно из решений — разделить тестовые наборы. Мы оставим BlogPage.test.js и создадим новый PostContent.test.js, который должен содержать тесты исключительно для PostContent. Основная идея заключается в том, что любые функции, размещенные в PostContent, должны быть указаны в PostContent.test.js, а любые функции, размещенные в BlogPage (например, парсинг URL), должны быть в BlogPage.test.js.
Хорошо.
Но что, если рендеринг PostContent имеет побочные эффекты?
export const PostContent = ({ id }) => {
const [ text, setText ] = useState("")
useEffect(() => {
fetchPostContent(id)
}, [id])
const fetchPostContent = async () => {
const result = await fetch(`/post?id=${id}`)
if (result.ok) {
setText(await result.text())
}
}
return <p>{text}</p>
};
Набор тестов в BlogPage.test.js должен знать о побочных эффектах и быть готовым обрабатывать их. Например, он должен будет держать наготове fetch ответ.
Зависимость, которой мы пытались избежать путем разделения наших тестовых наборов, все еще существует.
Организация нашего тестирования, безусловно, стала лучше, но в конечном итоге ничего, что бы сделало наши тесты менее хрупки, не произошло.
Для этого нам нужна заглушка (или мок) PostContent.
И в следующей части мы рассмотрим, как это сделать.
Так ли это необходимо?
Кстати, пара слов о переходе из области сквозных тестов в область модульных тестов.
Наличие тестовых двойников — ключевой показатель того, что вы пишете модульные тесты.
Многие опытные тестировщики сразу же начинают новые проекты с модульных тестов (и моков), потому что они знают, что по мере роста их кодовой базы они будут сталкиваться с проблемой нестабильности тестов.
Модульные тесты обычно намного меньше, чем сквозные. Они могут быть настолько малы, что часто занимают не больше трех-четырех строк кода. Это делает их отличными кандидатами для таких практик социального кодирования, как парное и ансамблевое программирование.
Даже когда мы проводим модульное тестирование, тестовые двойники не всегда необходимы — это просто еще один инструмент в вашем наборе, который вы должны знать, когда и как применять.
В следующей части мы рассмотрим основные техники мокинга.
оригинал
===========
Источник:
habr.com
===========
===========
Автор оригинала: Daniel Irvine
===========Похожие новости:
- Открыты исходные тексты GitHub Docs
- [Тестирование IT-систем, Тестирование веб-сервисов, Тестирование игр, Тестирование мобильных приложений] Топ-11 лучших систем управления тестированием 2020
- [Настройка Linux, Программирование, Разработка под Linux] Знакомимся с семафорами в Linux (перевод)
- [JavaScript, ReactJS, Программирование, Разработка веб-сайтов] Мифы о useEffect (перевод)
- [Разработка веб-сайтов, JavaScript, Социальные сети и сообщества] Front End Meetup от Facebook Developer Circle: Moscow
- [JavaScript, C++, WebAssembly] Как скрестить Clion, Emscripten и Cmake
- [Управление продуктом] Как найти и описать платящий сегмент пользователей?
- [Конференции] Новая неделя YouTube-стримов: от Vue.js до SIMD-инструкций
- [Разработка веб-сайтов, Python, Django] Отношение один к одному: связывание модели пользователя с кастомной моделью профиля в Django (перевод)
- [SQL, Microsoft SQL Server, Администрирование баз данных] Шифрование в MySQL: хранилище ключей (перевод)
Теги для поиска: #_javascript, #_testirovanie_mobilnyh_prilozhenij (Тестирование мобильных приложений), #_reactjs, #_javascript, #_react, #_testing, #_blog_kompanii_otus._onlajnobrazovanie (
Блог компании OTUS. Онлайн-образование
), #_javascript, #_testirovanie_mobilnyh_prilozhenij (
Тестирование мобильных приложений
), #_reactjs
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 12:25
Часовой пояс: UTC + 5
Автор | Сообщение |
---|---|
news_bot ®
Стаж: 6 лет 9 месяцев |
|
Перевод статьи подготовлен в преддверии старта курса «Автоматизация тестирования на JavaScript». Моки — не кусаются! Они предназначены помочь вам создавать более простые и надежные тесты. В этой серии статей я продемонстрирую вам паттерны, на которые я опираюсь при написании моков (mocks или “заглушек”) компонентов React. Вот наглядный пример заглушки компонента. Я использую jest.mock, который мы рассмотрим подробнее ниже. jest.mock("../src/PostContent", () => ({
PostContent: jest.fn(() => ( <div data-testid="PostContent" /> )) })) Типичная заглушка React компонента не должна выглядеть сложнее. Следует обратить внимание на очень простое значение-заглушку (div) и атрибут data-testid, который позволяет нам очень легко найти в DOM отрисованный экземпляр. По соглашению, используемый тестовый идентификатор должен совпадать с именем компонента. В данном случае это PostContent. Прежде чем мы рассмотрим, как они используются, давайте сначала вспомним, что такое моки и почему вы вообще можете захотеть их использовать. Что такое мок? В мире JavaScript термин mock очень широко применяется для обозначения любой имитированной реализации или тестового двойника (test double). Имитированные реализации — это просто значения, которые заменяют другие в вашем производственном коде во время выполнения тестов. Они примеряют на себя интерфейс заменяемого объекта, так что остальная часть вашего кода работает так, как если бы никакой замены не было. Есть несколько разных причин, по которым вам может это понадобиться; мы рассмотрим их на примерах. Если вам интересно узнать больше о имитированных реализациях, почитайте книгу Мартина Фаулера «Моки — не заглушки». Jest и мокинг В Jest есть функция jest.mock, которая позволяет мокать целые модули, которые вы заменяете. В этом руководстве я сосредоточился именно на этой функции, хотя в JavaScript есть и другие способы замены объектов. В книге Mastering React Test-Driven Development я использую импорт именованных модулей ES6 для создания тестовых двойников. Такой подход дает немного больше гибкости, но выглядит слегка более хакерским. На странице Jest про jest.mock говорится, что моки гарантируют, что ваши тесты будут быстрыми и не хрупкими. Хотя это правда, это не основная причина, по которой я использую моки. Я использую моки, потому что они помогают мне поддерживать мои тесты независимыми друг от друга. Чтобы понять, почему это так, давайте рассмотрим пример. Почему моки? Ниже приведен листинг компонента BlogPage, который выполняет две функции: он извлекает id из свойства url и затем отображает PostContent компонент с этим id. const getPostIdFromUrl = url =>
url.substr(url.lastIndexOf("/") + 1) export const BlogPage = ({ url }) => { const id = getPostIdFromUrl(url) return ( <PostContent id={id} /> ) } Представьте, что вы пишете тесты для этого компонента, и все ваши тесты включены в BlogPage.test.js, который представляет собой единый набор тестов, покрывающий компоненты BlogPage и PostContent. На этом этапе моки вам еще не нужны: мы еще не видели PostContent, но, учитывая размер BlogPage, действительно нет необходимости иметь два отдельных набора тестов, поскольку BlogPage — это в целом просто PostContent. Теперь представьте, что и у BlogPage, и у PostContent прибавляется функциональность. Вы, как одаренный разработчик, каждый день добавляете все больше и больше функций. Поддерживать тесты в рабочем состоянии становится сложнее. Каждый новый тест имеет более сложный сетап, и набор тестов начинает поедать все больше вашего времени — бремя, которое теперь необходимо поддерживать. Это распространенная проблема, и я все время вижу ее в кодовых базах React. Наборы тестов, в которых даже простейшее изменение результирует в сбоях многих тестов. Одно из решений — разделить тестовые наборы. Мы оставим BlogPage.test.js и создадим новый PostContent.test.js, который должен содержать тесты исключительно для PostContent. Основная идея заключается в том, что любые функции, размещенные в PostContent, должны быть указаны в PostContent.test.js, а любые функции, размещенные в BlogPage (например, парсинг URL), должны быть в BlogPage.test.js. Хорошо. Но что, если рендеринг PostContent имеет побочные эффекты? export const PostContent = ({ id }) => {
const [ text, setText ] = useState("") useEffect(() => { fetchPostContent(id) }, [id]) const fetchPostContent = async () => { const result = await fetch(`/post?id=${id}`) if (result.ok) { setText(await result.text()) } } return <p>{text}</p> }; Набор тестов в BlogPage.test.js должен знать о побочных эффектах и быть готовым обрабатывать их. Например, он должен будет держать наготове fetch ответ. Зависимость, которой мы пытались избежать путем разделения наших тестовых наборов, все еще существует. Организация нашего тестирования, безусловно, стала лучше, но в конечном итоге ничего, что бы сделало наши тесты менее хрупки, не произошло. Для этого нам нужна заглушка (или мок) PostContent. И в следующей части мы рассмотрим, как это сделать. Так ли это необходимо? Кстати, пара слов о переходе из области сквозных тестов в область модульных тестов. Наличие тестовых двойников — ключевой показатель того, что вы пишете модульные тесты. Многие опытные тестировщики сразу же начинают новые проекты с модульных тестов (и моков), потому что они знают, что по мере роста их кодовой базы они будут сталкиваться с проблемой нестабильности тестов. Модульные тесты обычно намного меньше, чем сквозные. Они могут быть настолько малы, что часто занимают не больше трех-четырех строк кода. Это делает их отличными кандидатами для таких практик социального кодирования, как парное и ансамблевое программирование.
Даже когда мы проводим модульное тестирование, тестовые двойники не всегда необходимы — это просто еще один инструмент в вашем наборе, который вы должны знать, когда и как применять. В следующей части мы рассмотрим основные техники мокинга. оригинал =========== Источник: habr.com =========== =========== Автор оригинала: Daniel Irvine ===========Похожие новости:
Блог компании OTUS. Онлайн-образование ), #_javascript, #_testirovanie_mobilnyh_prilozhenij ( Тестирование мобильных приложений ), #_reactjs |
|
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 12:25
Часовой пояс: UTC + 5