はじめに
E2Eテスト1を行うにあたって、フロントエンドのE2EテストツールのCypressを導入していましたが、例えばユーザーにログインをさせ、ユーザー固有のページを表示させるようなwebシステムでは、データベースに格納されている値に応じて動的に画面表示を切り替える事が必要となります。
その時に、Cypressだけでは、データベースの事前テストデータ生成を行った状態でのテストを、テストケース単位で行う事が容易にはできません。
これでは、どうしてもE2Eテストで検証できるパターンが少なくなってしまうため、
データベースの事前テストデータ生成をテストケース単位で実行できるツールとして、
CypressOnRailsを導入する事に決めました。
今回の記事では、CypressOnRailsの導入方法についてまとめたいと思います。
環境について
Dockerを用いているため、frontendコンテナ・backendコンテナが存在しています。(他にも存在しますが、今回関係ないため省略します)
開発環境で起動するサーバーは以下を条件とします。
- frontendコンテナは
localhost:8080
で起動 - backendコンテナは
localhost:3000
で起動
バージョンについては以下となります。
- backend
- ruby 3.2.2
- rubyonrails 7.0.5
- frontend
- vue 3.2.13
- vite 3.2.0
前提
ある程度フロントエンドのE2EテストツールのCypressでテストを実施した事がある人向けの内容となります。
また、Docker環境でfrontendコンテナ・backendコンテナを起動しているので、
CypressOnRailsもe2eコンテナを実行環境とし、xquartzというxサーバーを用いてyarn cypress open
させてみたのですが、以下理由により、一旦導入をやめています。
-
yarn cypress open
でブラウザを起動するまでの設定が手間である - ブラウザを起動した場合カーソルの動作が重たい
そのため、本記事の前半では、
単純にmacの環境でyarn cypress open
するまでの手順を記載します。
ただ、今後CIツールでcypressを実行する際には、e2eコンテナでyarn cypress run
させる事が必要となってくるので、本記事の後半部分では、Dockerコンテナ内でyarn cypress run
を実行するまでの導入手順についても記載します。(なのでコンテナを実行環境としたブラウザの起動までは行いません)
mac環境で構築する手順
まずは、mac環境でyarn cypress open
するまでの手順を記述します。
インストール
Gemfileに以下を記述し、bundle install
します。
group :test, :development do
gem 'cypress-on-rails', '~> 1.0'
end
セットアップ
以下コマンドにて、必要なファイルをgenerateします。
私の場合、テスト関係のファイル群はspecディレクトリの中で管理したかったので、以下コマンドを実行しました。
bin/rails g cypress_on_rails:install --cypress_folder=spec/cypress
そうすると、railsプロジェクトのspecディレクトリ内にcypressディレクトリが生成されます。
次に、database.yml
を編集します。
CypressOnRailsのドキュメントを見ると、環境変数に CYPRESS=1
が設定されていると、テスト用のデータベースを参照する仕組みのようです。
Cypressを起動してブラウザを操作する際はdevelopment環境でのテスト実行となるが、実際のデータベースはtest環境を参照する事で、FactoryBotにより生成したテストデータを利用できる形となるようです。
development:
<<: *default
database: <%= ENV['CYPRESS'] ? 'my_db_test' : 'my_db_development' %>
test:
<<: *default
database: my_db_test
次にspecディレクトリ内にpackage.jsonを作成し、以下記述します。
{
"devDependencies": {
"cypress": "^12.10.0",
}
}
specディレクトリにて、以下実行します。
cd spec
yarn install
あとは、私の場合dotenv-railsを用いてbackendのrailsアプリケーション側の環境変数を管理しているため、.env
内に以下追加し、railsのサーバーを再起動します。
CYPRESS=1
この状態で、specディレクトリにて、以下コマンドを実行すると、cypressのテストブラウザを起動する事ができます。
yarn cypress open
これにより、以下流れでデータベースの事前テストデータ生成をテストケース単位で実行できる状態となります。
- Cypress側でフロントエンド側のサーバーlocalhost:8080にvisitする
- backend側のlocalhost:3000にリクエストすると、test環境のデータベースを参照する形となる
- cy.jsファイル内でFactoryBotテストデータ生成の記述を行う事で、テストケース実行時に事前テストデータが生成されている状態となる
Docker環境で構築する手順
次に、Docker環境でyarn cypress run
するまでの手順を記述します。
インストール
Gemfileへの記述は同様です。コンテナ内でbundle install
します。
group :test, :development do
gem 'cypress-on-rails', '~> 1.0'
end
セットアップ
以下はmac環境での構築手順と同じです。
bin/rails g cypress_on_rails:install --cypress_folder=spec/cypress
development:
<<: *default
database: <%= ENV['CYPRESS'] ? 'my_db_test' : 'my_db_development' %>
test:
<<: *default
database: my_db_test
{
"devDependencies": {
"cypress": "^12.10.0",
}
}
次に、spec/Dockerfile.cy
を作成します。
コンテナのイメージは以下を参照ください。
私の場合、当初Dockerコンテナを実行環境としてyarn cypress open
する事も目的としていたため、cypress/browsersイメージを用いています。
FROM cypress/browsers:node-18.16.0-chrome-114.0.5735.133-1-ff-114.0.2-edge-114.0.1823.51-1
ARG WORKDIR
ENV HOME=/${WORKDIR}
WORKDIR ${HOME}
RUN apt-get update && \
apt-get install -y --no-install-recommends fonts-noto fonts-noto-cjk
COPY . ./
RUN yarn install
docker-compose.ymlの設定は以下です。
# WORKDIRはシステム構成に合わせて設定する
services:
backend:
build:
context: ./backend
args:
WORKDIR: $WORKDIR
...
...
ports:
- "3000:3000"
networks:
app_net:
ipv4_address: "172.20.0.2"
depends_on:
...
frontend:
build:
context: ./frontend
...
ports:
- "8080:8080"
networks:
app_net:
ipv4_address: "172.20.0.3"
depends_on:
- backend
e2e:
build:
context: ./backend/spec
dockerfile: Dockerfile.cy
args:
WORKDIR: $WORKDIR/spec
platform: linux/amd64
networks:
app_net:
ipv4_address: "172.20.0.4"
depends_on:
- backend
networks:
app_net:
driver: bridge
ipam:
driver: default
config:
- subnet: 172.20.0.0/24
それぞれのコンテナをbridgeで繋ぎ、ネットワークを構成しています。
なので、cypress側の設定ファイルそれぞれに関して、localhostではなく、IPを指定してあげれば設定完了となります。
※インストール時、設定ファイルなどのファイルはデフォルトではjsファイルで生成されますが、その後TypeScriptを導入したため、tsファイルで今回記述しています。ご容赦ください。
import { defineConfig } from "cypress";
export default defineConfig({
e2e: {
baseUrl: "http://172.20.0.2:3000",
supportFile: "cypress/support/index.ts",
},
env: {
// frontendページURL用の環境変数
VITE_APP_URL: "http://172.20.0.3:8080",
}
})
Cypress.Commands.add('appCommands', function (body) {
Object.keys(body).forEach(key => body[key] === undefined ? delete body[key] : {});
const log = Cypress.log({ name: "APP", message: body, autoEnd: false })
return cy.request({
method: 'POST',
// 以下を修正する
url: "http://172.20.0.2:3000/__cypress__/command",
body: JSON.stringify(body),
log: false,
failOnStatusCode: false
}).then((response) => {
log.end();
if (response.status !== 201) {
expect(response.body.message).to.equal('')
expect(response.status).to.be.equal(201)
}
return response.body
});
});
...
...
あとはDockerのbuildがうまく完了すれば、構築は終了となります。
Cypress実行
以下コマンドで、Cypress用実行環境を起動し、CypressOnRailsによるe2eテストがheadlessで実行できます。
docker-compose run e2e yarn cypress run
まとめ
ひとまず、CypressOnRailsを用いて、データベースの事前テストデータ生成をテストケース単位で実行するための準備として、今回の記事を書きました。次の機会には、実際に事前テストデータ生成の書き方
についてまとめてみたいと思います。
-
利用者の観点に立ったWebブラウザの操作により、システム全体が一貫して想定通りに動作しているかを確認すること ↩