75
56

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

E2EテストをCIでも気軽に利用しよう 〜 Cypress x Docker Compose

Last updated at Posted at 2019-11-13

2019/11/18追記 日本語フォント表示用にDockerfileを修正しました。

はじめに : Cypressの紹介

Cypressは、無料で利用できるOSSのEnd-to-End(E2E)のテストツールです。以下のように自分のブラウザを利用してWeb UIテストを実行します。

以下のようなコードを元に、実際にブラウザで動かしながら、直感的にテストをすることができます。JavaScriptでテストコードを記述できるので、利用しているJSerも多いです。

describe('The Login Page', function () {
  beforeEach(function () {
    // reset and seed the database prior to every test
    cy.exec('npm run db:reset && npm run db:seed')
    // seed a user in the DB that we can control from our tests
    // assuming it generates a random password for us
    cy.request('POST', '/test/seed/user', { username: 'jane.lane' })
      .its('body')
      .as('currentUser')
  })

  it('sets auth cookie when logging in via form submission', function () {
    // destructuring assignment of the this.currentUser object
    const { username, password } = this.currentUser
    cy.visit('/login')
    cy.get('input[name=username]').type(username)
    // {enter} causes the form to submit
    cy.get('input[name=password]').type(`${password}{enter}`)
    // we should be redirected to /dashboard
    cy.url().should('include', '/dashboard')
    // our auth cookie should be present
    cy.getCookie('your-session-cookie').should('exist')
    // UI should reflect this user being logged in
    cy.get('h1').should('contain', 'jane.lane')
  })
})

参考URL : https://docs.cypress.io/guides/getting-started/testing-your-app.html#Logging-in

E2EテストをCIサーバで実行する

ローカルブラウザでCypressを利用すると捗るのですが、CIへの組み込みがなかなか進まず、専用のマシンを用意しておこうか、と思ったところCypressの公式コンテナがあることに気が付きました。

そして少しのコードで専用マシンなどを用意せず、以下の構成でCIのフローに乗せることができました。

追加したファイルの紹介

追加したファイルは以下の3つです。

フロントエンド用のDockerfile

全環境共通のDockerfileです。環境変数で環境ごとの情報を管理します。

# ファイルをビルド
FROM node:13.1.0-alpine as build
WORKDIR /app
ENV PATH /app/node_modules/.bin:$PATH
COPY . /app
RUN npm install --silent
RUN npm run build

# nginxコンテナにビルドしたファイルをコピー
FROM nginx:1.16.0-alpine
COPY --from=build /app/build /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

Cypress用Dockerfile

FROM cypress/base:10
# 日本語フォント表示用にnoto-cjkを追加
RUN apt-get install --no-install-recommends -y fonts-noto fonts-noto-cjk
WORKDIR /app
COPY package.json .
COPY package-lock.json .
ENV CI=1
RUN npm ci
RUN npx cypress verify

docker-compose.yml

version: '3'
services:
  web:
    image: frontend:latest
    ports:
      - "8080:80"
  e2e:
    build:
      context: .
      dockerfile: ./Dockerfile
    command: npx cypress run
    depends_on:
      - web
    environment:
      - CYPRESS_baseUrl=http://web
      - CYPRESS_browser=chrome
      - CYPRESS_screenshotsFolder=/results/screenshots
      - CYPRESS_videosFolder=/results/videos
    volumes:
      - ./cypress:/app/cypress
      - ./cypress.json:/app/cypress.json
      - ./results:/results

docker-compose.yamlの解説

CYPRESS_xxxx の環境変数部分でConfigurationを設定しています。CYPRESS_browserという変数もありますが、現在選べるのは、chrome/chromium/canaryのいずれかです。それ以外のブラウザはサポートされません。

ローカルで docker-compose up を実行すれば、マウントされた results/videos 以下にスクリーンショットと、動作時の録画データが入ります。

/results/screenshots に出力される録画データ。 (mp4で出力されたものをgifに変換)
※ /results/screenshots に出力される録画データ。 (mp4で出力されたものをgifに変換)

CI時、テストが失敗したら終了したい場合、以下のコマンドを利用します。

docker-compose up --abort-on-container-exit --exit-code-from e2e

CI上で試したいときは、Slackなどにファイルを添付して渡すと、原因究明がはかどります。

最後に : 実際の利用シーン

Google Chromeがインストールされていない環境でも、簡単にテストが行えるようになりました。

新しくテストコードを書く時は、実際にブラウザで操作しながら書く方が楽なので、ローカルでも動くようにしています。

以下のようなフローでテストを追加しているという一例です。

  1. npx cypress open を実行して、ローカルブラウザでテストを書く
  2. docker-compose upを実行すると、コンテナ内でテストが自動実行される

リクエストが多ければGitHubにひな形を作成するので、興味がある方はリクエストをください。

75
56
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
75
56

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?