Как настроить автоматизированные интеграционные тесты во Vue приложении

Denis Grushkin
Mad Devs — блог об IT
6 min readMar 2, 2021
Настройка интеграционных тестов во 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

Если всё было выполнено правильно, будет открыт браузер со списком наших тестов. Ура!

Cypress Integration & component tests.
Cypress Integration & component tests

И в консоли будет вот такая картина

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 мин. После поднимет контейнер с тестами и контейнер для запуска браузера. Запустит браузер.
Вот и всё, остаётся только писать тесты и радоваться тому, что проект становится немного стабильнее, а сон ваш крепче.

Заключение

Всё, что я написал выше – это всего лишь настройка, подготовка проекта. Дальше вас ожидают многочасовые поиски информации о том, как правильно писать тесты, мокать данные, мокать плагины и т.д. Там столько всего, что чёрт ногу сломит.
Но что остается главным для достижения любой цели? Конечно же это движение. Теперь у вас под рукой есть мануал, который даст вам старт не только для стабилизации проекта, но и для повышения ваших профессиональных скиллов.

Будьте внимательны!

Кибирд.

--

--