Как настроить автоматизированные интеграционные тесты во Vue приложении
Качество продукта всегда зависит от того, насколько разработчик внимателен. Чем лучше прокачен этот скилл, тем меньше багов и недовольных клиентов.
У меня, например, с этим иногда бывают проблемы. Но к счастью решение есть, и это решение называется автотестами. Автоматизация тестирования позволяет организовать постоянную проверку качества продукта, снимая эту задачу с вас.
И сегодня я расскажу, как настроить автоматизированные тесты во Vue проекте. Появится возможность тестировать как целые страницы, так и отдельные компоненты, подменять запросы сервера, ну и конечно запускать все это в докере.
Давайте представим, что у нас есть Vue проект, который разрабатывается уже тысячу лет и единственные тесты, которыми там еле пахнет – это юниты. То есть функциональные, которые были настроены из коробки и несознательно.
Первое, что мы сделаем, – откроем документацию фреймворка Cypress. Собственно с помощью него мы и будет писать интеграционные тесты. Он довольно хорошо развит и имеет куче фичей, плагинов и прочих вспомогательных штук.
Обязательно почитайте документацию, чтобы понимать, что это и как работает.
Теперь займемся установкой необходимых пакетов.
Откроем консоль в корне проекта и вставим команду ниже
npm i -D cypress @cypress/vue @vue/cli-plugin-e2e-cypress vue-cli-plugin-cypress-experimental
После того, как пакеты успешно установились, добавим основной файл настроек cypress.json. Его нужно создать также в корне проекта и вставить код ниже
{
"baseUrl": "http://localhost:3000",
"chromeWebSecurity": false,
"pluginsFile": "tests/e2e/plugins/index.js",
"supportFile": "tests/e2e/support/index.js",
"fixturesFolder": "tests/e2e/fixtures",
"integrationFolder": "tests/e2e/integrations",
"testFiles": "**/*.spec.js*",
"experimentalComponentTesting": true,
"componentFolder": "tests/e2e/components",
"nodeVersion":"system",
"video": false,
"viewportWidth": 1366,
"viewportHeight": 768
}
Несколько слов о том, что значат эти параметры
- baseUrl — URL, на котором будет запущен cypress браузер
- chromeWebSecurity — позволит открывать небезопасные страницы, даст доступ к iframe’ам и т.д.
- pluginsFile — путь, где хранятся файлы с плагинами для cypress
- supportFile — путь, где хранятся вспомогательные файлы
- fixturesFolder — путь, где хранятся мок-файлы, которыми можно подменять данные api
- integrationFolder — путь, где хранятся файлы c интеграционными тестами
- testFiles — путь, где хранятся все файлы с тестами
- componentFolder — путь, где хранятся файлы с тестами для компонентов
- experimentalComponentTesting — этот флаг обязателен, если хотите тестировать компоненты
- nodeVersion — указать версию node.js
- video — вкл\выкл запись видео о том, как проходят тесты
- viewportWidth — ширина окна браузера
- viewportHeight — высота окна браузера
В настройках уже можно увидеть список файлов и папок, которые нужно создать.
Во Vue папка для тестов располагается в корне проекта и обычно называется tests. Там сейчас уже должна быть создана папка unit, около которой мы создадим еще одну для наших тестов.
Новую папку назовём e2e. В неё добавим еще несколько файлов и папок. В итоге должно получиться вот так
tests
e2e
components
- HelloWorld.spec.js
- ...
fixtures
- example.json
- ...
integrations
- Home.spec.js
- ...
plugins
- index.js
support
- commands.js
- index.js
Чтобы оградить вас от лишних заморочек, я подготовил репу с уже настроенным проектом. Вы можете скопировать оттуда всё и не париться https://github.com/denisoed/setup-cypress-vue.
Далее в файл package.json, в блок scripts добавим команду для запуска тестов
"scripts": {
"test:e2e": "vue-cli-service test:e2e --mode test"
}
Основные шаги мы выполнили, теперь можно запускаться.
npm run test:e2e
Если всё было выполнено правильно, будет открыт браузер со списком наших тестов. Ура!
И в консоли будет вот такая картина
DONE Compiled successfully in 3572msApp running at:
- Local: http://localhost:8080/
- Network: http://192.168.88.241:8080/Note that the development build is not optimized.
To create a production build, run npm run build.It looks like this is your first time using Cypress: 6.5.0✔ Verified Cypress! /home/denisoed/.cache/Cypress/6.5.0/CypressOpening Cypress...
Это можно назвать победой, но не нужно расслабляться, мы еще не закончили.
Настройка сервера для подмены API запросов
Суть – подменить реальный api сервер, дать возможность манипулировать данными.
В качестве mock сервера мы будем использовать библиотеку JSON server. Она работает на базе Express.js, поэтому с настройкой или расширением не должно возникнуть проблем.
Установим пакет
npm i json-server
И сразу можно добавить команду для запуска в package.json, заодно и обновим команду для запуска тестов. Теперь первым будет стартовать сервер, потом запустится cypress.
"scripts": {
"test:e2e": "npm run test:server & vue-cli-service test:e2e --mode test",
"test:server": "node ./tests/server/server.js"
}
Далее добавим в папке tests новую папку для нашего сервера. Назовем её server.
Повторим процесс, который проделывали с файлами и папками для тестов – просто скопируем их из уже готового проекта https://github.com/denisoed/setup-cypress-vue.
tests
server
data
- users.js
config.js
server.js
- Файл server.js — это основной файл для запуска сервера.
- Файл config.js — опции для сервера.
- Папка data — хранит файлы с тестовыми данными, которые будут возвращены json-сервером.
Сейчас вкратце расскажу, как мокать api запросы.
Допустим, ваше приложение запрашивает список пользователей у бэкенда.
К примеру, урл такой https://backend.com/users
В первую очередь идем в файл server.js и обращаем внимание на блок ниже
// ---- Сustom routes ---- \\server.get('/users', (req, res) => {
res.jsonp(users);
});
В нём видно, что если запросить что-то по урлу /users, он вернет данные из переменной users. Здесь, думаю, понятно. Если ваше приложение делает запросы еще на какие-то урлы, то просто копируем блок выше и меняем как нам нужно.
Данные я тоже заранее подготовил, их можно найти в папке data. Выглядят они вот так
module.exports = [
{
name: 'Bob',
age: 32
},
{
name: 'Alice',
age: 19
}
];
Урл мы поменяли, данные подготовили. Этого достаточно, чтобы мокать api. Таким образом мы можем подменять все запросы, описывая в тестах разные кейсы.
Подведем итог.
Когда ваше приложение будет делать запрос на бэкенд, наш mock сервер перехватит его и вернет нужные нам данные. Вот так просто!
“Но как он будет перехватывать запросы?” – спросите вы. Тут тоже ничего сложного.
Обычно в проектах создают .env файл, который нужен для хранения переменных. В нем и хранят ссылку на бэкенд api сервер. Если поменять эту ссылку, соответственно ваше приложение будет ориентироваться на неё. Так мы и сделаем.
В корне проекта нужно создать файл .env или заменить в нем переменную, если файл уже существует. С https://backend.com на http://localhost:8888
VUE_APP_API_URL=http://localhost:8888
http://localhost:8888 — это адрес нашего mock сервера. В файле config.js можно поменять порт, если этот уже занят.
Попробуем запустить сервер, выполнив команду
npm run test:server
Если ошибок нет, то увидим такой результат
> node ./tests/server/server.jsJSON Server is running on port: 8888
Mock сервер для тестов успешно подготовлен.
Чтобы закончить эту часть статьи, я хотел бы повторить основную идею:
Когда мы будем тестировать наше приложение, все запросы, которые раньше были направлены на реальный api сервер, будут перехвачены нашим mock сервером. И нам не придется задумываться о том, что бэкенд не работает, или нет интернета, или что-то ещё.
Ваши тесты будут независимы – а это очень важно.
Запуск тестов в Докере
Этот вариант хорош тем, что не нужно устанавливать на вашу рабочую машину кучу npm зависимостей. Докер инкапсулирует весь этот мусор и не позволит загадить систему.
Для этого вам потребуется установить всего лишь Docker и Docker compose.
Начнем копировать необходимые файлы. По той же схеме перетащим их из уже готово проекта https://github.com/denisoed/setup-cypress-vue.
Нам нужны три файла cy-open.yml
, docker-compose.e2e.yml
, Dockerfile.e2e
Их нужно разместить в корне проекта.
- Dockerfile.e2e — соберёт всё необходимое для контейнера, в котором будут запускаться тесты.
- docker-compose.e2e.yml — настройки для контейнера.
- cy-open.yml — этот файл нужен для запуска браузера из докера.
Обновим файл package.json
"scripts": {
"test:e2e": "npm run test:server & vue-cli-service test:e2e --mode test",
"test:server": "node ./tests/server/server.js",
"docker:test:e2e": "docker-compose -f docker-compose.e2e.yml -f cy-open.yml up --exit-code-from cypress"
}
При запуске может появиться вот такая ошибка
cypress_1 | ----------
cypress_1 |
cypress_1 | No protocol specified
cypress_1 | [101:0208/050449.746174:ERROR:browser_main_loop.cc(1434)] Unable to open X display.
cypress_1 | The futex facility returned an unexpected error code.
cypress_1 | No protocol specified
cypress_1 | [115:0208/050450.882329:ERROR:browser_main_loop.cc(1434)] Unable to open X display.
cypress_1 |
cypress_1 | undefined:0
cypress_1 |
cypress_1 |
cypress_1 | illegal access
cypress_1 | (Use `Cypress --trace-uncaught ...` to show where the exception was thrown)
cypress_1 |
cypress_1 | ----------
Чтобы решить её, нужно в консоли запустить эту команду
xhost +si:localuser:root
Результат должен быть таким
localuser:root being added to access control list
Дальше всё должно запуститься нормально
npm run docker:test:e2e
Докер начнет устанавливать и распаковывать пакеты, это обычно 2–5 мин. После поднимет контейнер с тестами и контейнер для запуска браузера. Запустит браузер.
Вот и всё, остаётся только писать тесты и радоваться тому, что проект становится немного стабильнее, а сон ваш крепче.
Заключение
Всё, что я написал выше – это всего лишь настройка, подготовка проекта. Дальше вас ожидают многочасовые поиски информации о том, как правильно писать тесты, мокать данные, мокать плагины и т.д. Там столько всего, что чёрт ногу сломит.
Но что остается главным для достижения любой цели? Конечно же это движение. Теперь у вас под рукой есть мануал, который даст вам старт не только для стабилизации проекта, но и для повышения ваших профессиональных скиллов.
Будьте внимательны!