В Vue Fes Japan 2018 я нашел очень интересную презентацию, посвященную тестированию компонентов Vue и, в частности, визуальному тестированию. Я впервые узнал о рег-визе / рег-костюме. Это отличный инструмент для повышения скорости визуального тестирования.

TL;TR

Разве не будет здорово, если вы сможете получать визуальные различия, подобные приведенным ниже, при каждой загрузке в репозиторий? Вот что может reg-suit.

reg-suit подробно объясняется в их репозитории README. Кроме того, у них есть демонстрационный репозиторий для тестирования визуального тестирования с помощью GitHub, AWS S3, CircleCI здесь. Одна вещь, которую я хотел избежать, - это использовать облачного провайдера для тестирования этой функциональности (я хочу по возможности избегать использования кредитной карты). Вот почему я использовал Minio вместо AWS S3 - частное облачное хранилище, совместимое с S3 API, - и я собираюсь объяснить, как вы можете протестировать его самостоятельно, ниже.

Требования

Прежде всего, вам нужно подготовиться и получить базовые знания о следующем, чтобы все работало:

  • Node.js
    Основная среда выполнения, используемая reg-suit и связанными с ней инструментами.
  • Докер
    Чтобы легко запускать Minio и передавать содержимое через Nginx
  • учетная запись ngrok и двоичный файл
    Чтобы легко опубликовать Minio и Nginx с помощью HTTPS
  • Учетная запись GitHub
    Для интеграции reg-suit с репозиторием GitHub
  • Учетная запись CircleCI
    Для запуска reg-suit с CI

Создать проект

$ mkdir reg-puppeteer-demo-with-minio
$ cd reg-puppeteer-demo-with-minio
$ git init
$ npm init

Создать страницу

Давайте создадим демонстрационную страницу.

$ touch index.html

Откройте файл index.html в редакторе и вставьте следующее содержимое (не обращайте внимания на подробности здесь):

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <link
      rel="stylesheet"
      href="https://fonts.googleapis.com/css?family=Lato"
    />
    <link
      rel="stylesheet"
      href="https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.4.1/semantic.css"
    />
    <style>
      body {
        background: #d7d8d9;
        margin: 0 auto;
      }
      .cards {
        margin: 0 auto;
        padding: 60px 0;
        width: 480px;
      }
      .ui.card.large {
        width: 100%;
      }
    </style>
  </head>
  <body>
    <div class="cards">
      <div class="ui raised card large">
        <div class="content">
          <div class="header">It's a real "Robot Guitar"</div>
        </div>
        <div class="image">
          <img
            src="https://github.com/reg-viz/reg-puppeteer-demo/blob/master/assets/photo.jpg?raw=true"
          />
        </div>
        <div class="content">
          <span class="right floated">
            <i class="heart outline like icon"></i> 25 likes
          </span>
          <i class="comment icon"></i> 3 comments
        </div>
        <div class="extra content">
          <div class="ui large transparent left icon input">
            <i class="heart outline icon"></i>
            <input type="text" placeholder="Add Comment..." />
          </div>
        </div>
      </div>
    </div>
  </body>
</html>

Вы должны увидеть что-то подобное, когда откроете index.html.

Создайте сценарий для создания снимков экрана

Чтобы reg-suit зафиксировал визуальные различия, нам нужно создать снимки экрана index.html. Reg-puppeteer-demo использует Puppeteer для достижения этой цели, поэтому давайте установим его и напишем простой скрипт.

$ npm install -D puppeteer mkdirp
$ touch capture.js

Откройте capture.js и вставьте следующее содержимое:

const puppeteer = require('puppeteer');
const mkdirp = require('mkdirp');

async function main() {
  const browser = await puppeteer.launch({ args: ['--no-sandbox', '--disable-setuid-sandbox'] });
  let page = await browser.newPage();

  page.setViewport({ width: 640, height: 680 });
  await page.goto(`file://${__dirname}/index.html`);
  await new Promise(res => setTimeout(() => res(), 300));
  await page.screenshot({ path: 'screenshot/index.png' });

  await page.close();
  await browser.close();
}

mkdirp.sync('screenshot');
main();

Подготовьте Minio

А теперь приготовим Минио. Простая архитектура выглядит следующим образом:

Поскольку это тестовая среда, мы собираемся использовать ngrok, чтобы открыть соединение TSL с нашей локальной средой. Убедитесь, что у вас есть учетная запись и двоичный файл ngrok. Поскольку reg-suit загружает отчет в Minio, нам нужно просмотреть и этот отчет. S3 может размещать веб-сайты из коробки, но Minio не может. Вот почему мы также готовим контейнер Nginx для просмотра содержимого внутри Minio.

Сначала создадим docker-compose.yml файл и вставим его содержимое:

version: '3'
services:
  minio:
    image: minio/minio
    ports:
      - '9000:9000'
    env_file:
      - .env
    volumes:
      - ./.tmp_data:/data
    command: ['server', '/data']
  web:
    image: nginx
    volumes:
      - ./nginx.conf:/etc/nginx/conf.d/default.conf
    ports:
      - '8080:80'
    command: "nginx -g 'daemon off;'"

Создайте .env файл

Давайте создадим .env файл, чтобы хранить учетные данные Minio внутри переменных среды. (Несмотря на то, что это тестовая среда, давайте не будем фиксировать учетные данные.)

MINIO_ACCESS_KEY=SUPERAWESOMEACCESSKEY
MINIO_SECRET_KEY=SuPeRaWeSoMeSeCrEtKeY

Создайте каталог данных

Давайте также сохраним данные minio вне контейнера. Создайте каталог .tmp_data, чтобы подключить его к контейнеру minio.

$ mkdir .tmp_data

Создать конфигурацию Nginx

Создайте файл с именем nginx.conf со следующим содержимым:

server {
 listen 80;
 server_name localhost;
 location / {
   rewrite ^/$ /static/index.html break;
   proxy_set_header Host $http_host;
   proxy_pass http://minio:9000/static/;
 }
}

Nginx будет обратным прокси-сервером, указывающим на сегмент Minio под названием static. Сюда reg-suit загрузит отчеты.

Запустите контейнеры

Теперь, когда мы подготовили контейнеры, приступим к ним!

$ docker-compose up -d
# Check the logs
$ docker-compose logs -f

Интеграция с ngrok

Теперь мы можем запустить ngrok, чтобы службы могли получить доступ к Minio из Интернета.

# Open Minio
$ ngrok http 9000
# Open Nginx to serve Minio files
$ ngrok http 8080

Линии, на которых вы должны сосредоточить внимание, следующие:

# Minio
https://0880c053.ngrok.io -> localhost:9000
# Nginx
https://c8a8fd88.ngrok.io -> localhost:8080

Доступ к Minio

Как видите, мы можем получить доступ к Minio из Интернета.

Доступ к Nginx

Похоже на страницу с ошибкой, но это от Minio. Вы также можете подтвердить, что Nginx доступен через ngrok.

Настроить Minio

Мы собираемся настроить сегмент Minio и разрешения с помощью Minio Client mc. Выполните следующие команды через контейнер докера:

# Spin up an interactive docker container
$ docker run -it --entrypoint=/bin/sh minio/mc
# Add a host (be sure to set the ngrok address for Minio)
$ mc config host add myminio https://0880c053.ngrok.io SUPERAWESOMEACCESSKEY SuPeRaWeSoMeSeCrEtKeY
Added `myminio` successfully.
# Create a bucket named `static`
$ mc mb myminio/static
Bucket created successfully `myminio/static`.
# Add a policy so Nginx can reference the files
$ mc policy download myminio/static
Access permission for `myminio/static` is set to `download`

Подготовьте репозиторий GitHub

Создайте репозиторий под названием reg-puppeteer-demo-with-minio на GitHub.

Затем давайте переместим наш локальный репозиторий на GitHub. Но перед этим давайте создадим .gitignore файл со следующим содержанием:

node_modules
.tmp_data/
.env

Теперь давайте зафиксируем и отправим на GitHub:

git add --all
git commit -m "initial commit"
# Be sure to change the repo to your own
git remote add origin https://github.com/<YOUR_GITHUB_USERNAME>/reg-puppeteer-demo-with-minio.git
git push -u origin master

Добавить и настроить приложение reg-suit GitHub

Затем давайте добавим приложение reg-suit GitHub для интеграции с нашим репозиторием. Щелкните ссылку ниже:

Https://github.com/apps/reg-suit

Вы должны увидеть такую ​​страницу:

Продолжайте и установите приложение. Я выбрал только этот конкретный репозиторий (reg-puppeteer-demo-with-minio), но выбрал то, что подходит.

Теперь вы должны увидеть страницу рег-костюма, как показано ниже:

Подготовить библиотеку reg-suit

Добавим в наш проект reg-suit:

$ npm install -D reg-suit

После этого давайте инициализируем его. Вот как это выглядит:

$ npx reg-suit init
[reg-suit] info version: 0.7.17
? Plugin(s) to install (bold: recommended) (Press <space> to select, <a> to toggle all, <i> to inverse selection)
❯◉  reg-keygen-git-hash-plugin : Detect the snapshot key to be compare with using Git hash.
 ◉  reg-notify-github-plugin : Notify reg-suit result to GitHub repository
 ◉  reg-publish-s3-plugin : Fetch and publish snapshot images to AWS S3.
 ◯  reg-notify-gitlab-plugin : Notify reg-suit result to GitLab repository
 ◯  reg-notify-slack-plugin : Notify reg-suit result to Slack channel.
 ◯  reg-publish-gcs-plugin : Fetch and publish snapshot images to Google Cloud Storage.
 ◯  reg-simple-keygen-plugin : Determine snapshot key with given values
? Working directory of reg-suit. .reg
? Append ".reg" entry to your .gitignore file. Yes
? Directory contains actual images. screenshot
? Threshold, ranges from 0 to 1. Smaller value makes the comparison more sensitive. 0
[reg-suit] info Set up reg-notify-github-plugin:
? notify-github plugin requires a client ID of reg-suit GitHub app. Open installation window in your browser Yes
? This repositoriy's client ID of reg-suit GitHub app MzS1MLcwMDay1C9KTdctKC0oSC1JTS3STUnNzdctzyzJ0M3NzMvM1zcxNzQ2ttDPTs1LS0ktAwA=
[reg-suit] info Set up reg-publish-s3-plugin:
? Create a new S3 bucket No
? Existing bucket name static

Примечание: открыть окно установки в вашем браузере Да

Когда вы ответите на вопрос выше, вы должны увидеть страницу рег-костюма, которую вы видели ранее. Вы можете нажать Get client ID и скопировать Client ID, чтобы ответить на следующий вопрос:

Ваш regconfig.json должен выглядеть следующим образом:

{
  "core": {
    "workingDir": ".reg",
    "actualDir": "screenshot",
    "thresholdRate": 0,
    "addIgnore": true,
    "ximgdiff": {
      "invocationType": "client"
    }
  },
  "plugins": {
    "reg-keygen-git-hash-plugin": true,
    "reg-notify-github-plugin": {
      "clientId": "MzS1MLcwMDay1C9KTdctKC0oSC1JTS3STUnNzdctzyzJ0M3NzMvM1zcxNzQ2ttDPTs1LS0ktAwA="
    },
    "reg-publish-s3-plugin": {
      "bucketName": "static"
    }
  }
}

Кроме того, нам нужно настроить reg-publish-s3-plugin так, чтобы он указывал на Minio, а не на AWS. Отредактируйте его, как показано ниже:

"reg-publish-s3-plugin": {
  "bucketName": "static",
  "customDomain": "c8a8fd88.ngrok.io",       <- Your Nginx Domain
  "sdkOptions": {
    "endpoint": "https://0880c053.ngrok.io", <- Your Minio Endpoint
    "s3ForcePathStyle": true,
    "signatureVersion": "v4"
  }
}

Теперь давайте добавим несколько скриптов npm для запуска тестов. Отредактируйте свои скрипты package.json:

"scripts": {
  "test": "node capture.js",
  "reg-suit": "reg-suit run"
},

Настройка рег-костюма завершена! Обязательно обновите .gitignore, чтобы он выглядел так, и зафиксируйте / отправьте на GitHub:

node_modules
.tmp_data/
.env
.reg/
/screenshot/

зафиксировать и нажать:

$ git add --all
$ git commit -m "configured reg-suit"
$ git push origin master

Настроить CircleCI

Мы почти там! Теперь давайте настроим CircleCI. Давайте сначала создадим файл конфигурации.

$ mkdir .circleci
$ touch .circleci/config.yml

Откройте config.yml и вставьте содержимое ниже:

version: 2
jobs:
  build:
    docker:
      - image: regviz/node-xcb
working_directory: ~/repo
steps:
      - checkout
# Download and cache dependencies
      - restore_cache:
          keys:
          - v1-dependencies-{{ checksum "package.json" }}
          # fallback to using the latest cache if no exact match is found
          - v1-dependencies-
- run: npm install
- save_cache:
          paths:
            - node_modules
          key: v1-dependencies-{{ checksum "package.json" }}
        
      # run tests!
      - run: npm test
      - run: npm run reg-suit

Я не буду вдаваться в подробности, но это npm install модули и run the test для создания захватов с помощью кукловода, а затем run reg-suit для создания визуальных отчетов о тестах. Давайте также отправим это на GitHub:

$ git add --all
$ git commit -m "add circleci"
$ git push origin master

Настроить через Личный кабинет

Теперь перейдите на панель управления CircleCI (при условии, что у вас уже есть учетная запись). Давайте настроим наш проект.

У нас уже есть config.yml, поэтому нажмите кнопку Start building:

Это запустит вашу первую CI, но не удастся, потому что мы не установили учетные данные для Minio. Щелкните Gear Icon в правом верхнем углу.

Ищите AWS Permissions в разделе Permissions. Теперь установите клавиши Minio, как показано ниже, и Save AWS keys:

Теперь вернитесь к неудачному тесту и нажмитеRerun workflow. Теперь вы должны увидеть, что ваши тесты проходят успешно!

Испытайте силу визуального тестирования

Наконец-то все готово. Давайте посмотрим, как cool reg-suit интегрируется с GitHub.

Представьте, что в какой-то момент какой-то сумасшедший добавил в ваш проект следующий класс css:

.extra.content {
  opacity: 0;
}

Добавьте вышеуказанное в index.html. Раздел style теперь должен выглядеть так:

<style>
  body {
    background: #d7d8d9;
    margin: 0 auto;
  }
  .cards {
    margin: 0 auto;
    padding: 60px 0;
    width: 480px;
  }
  .ui.card.large {
    width: 100%;
  }
  .extra.content {
    opacity: 0;
  }
</style>

Создадим для этого пиар:

$ git checkout -b adjust-css
$ git add --all
$ git commit -m "adjusted the css"
$ git push origin adjust-css

Теперь после того, как вы нажмете Create pull request, вы должны увидеть следующую страницу:

Видишь этого reg-suit бота?

Этот бот просто потрясающий. Он говорит, что обнаружил визуальную разницу. Посмотрим на отчет.

Обратите внимание, что загрузка этой страницы может занять некоторое время, потому что между ними используется ngrok.

Не запуская эту среду для просмотра PR, вы можете увидеть, какие изменения были внесены визуально. Я почти уверен, что вы не одобрит этот пиар (кроме случаев, когда он преднамерен). Это сэкономит кучу времени при рассмотрении визуальных изменений, и это одна из тех революций, которые я пережил недавно.

Вы можете либо запросить изменения для этого PR, либо утвердить / объединить PR, чтобы reg-suit использовал более новую версию для следующего сравнения. Так интуитивно понятно, не правда ли?

Заключение

Я почти уверен, что я не единственный, кто подумал: «Думаю, это изменение в порядке. Но позвольте мне проверить свою местную среду, чтобы убедиться ». при просмотре PR и обнаружил, что это действительно нормально. Напротив, я пропустил много регрессов, потому что я не знал (всех возможных) изменений, когда просматривал их. Это не то, в чем умеет большинство людей. Это то, что я хотел автоматизировать в течение долгого времени, и DX (опыт разработчика) reg-suit кажется действительно хорошим в этом.

Это был PoC, чтобы увидеть, легко ли он работает с Minio. Так оно и было! Так что теоретически, если вы объедините его с GitLab, этот рабочий процесс также должен работать локально.

GitLab + GitLab CI + Minio

Вау, это звучит довольно интересно, не так ли?

Если вы считаете, что рег-иск был интересным, давайте продемонстрируем нашу поддержку, выделив репо в главной роли!