前提
- 今回はnode.jsのパッケージマネージャーとしてyarnを使っている
- したがって本稿で使用しているコマンドは
yarn
を使っているが、使っていない方は各自npm
に変換して読み進めてください
Cypressとは
- Cypress は、テストのセットアップ、作成、実行、デバッグなどをシンプルにするブラウザテストツール
- Seleniumと似ているがCypressは完全にテスト目的に特化しているのが特徴
目的
今回はCypressのプラグインにあるCucumberを導入して実際に簡単なテストを書いて回してみる
※最短で目的を達成するため細かい説明は多少省きますが(必要だと思った部分は一応リンク貼っておきます)、参考サイトにを挙げておきますのでそちらを確認してみてください
1. インストール
本稿ではルートのディレクトリをsample-e2e
とする
初めにsample-e2e
ディレクトリを作成し、cypressやその依存関係をTypeScriptへトランスパイルのために必要なものをインストール
mkdir sample-e2e
cd e2e
yarn init -y
yarn add cypress webpack @cypress/webpack-preprocessor typescript ts-loader
次にCucumberのプラグインの導入に必要なやつをインストール
yarn add cypress-cucumber-preprocessor @types/cypress-cucumber-preprocessor tsify
2. セットアップ
まずはTypeScriptの設定をするためtsconfig.json
を作成
{
"compilerOptions": {
"strict": true,
"sourceMap": true,
"module": "commonjs",
"target": "es5",
"lib": [
"dom",
"es6"
],
"jsx": "react",
"experimentalDecorators": true
},
"compileOnSave": false
}
次にCypressの最初のdry runを行い、Cypressのフォルダ構造を準備(デフォルトのディレクトリの役割については後述)
yarn cypress open
- コマンドを実行するとCypress IDEが勝手に開く
- ウェルカムメッセージが表示されるので、確認したら一旦閉じましょう
プラグインのindex.js
を編集
const cucumber = require("cypress-cucumber-preprocessor").default;
const browserify = require("@cypress/browserify-preprocessor");
module.exports = (on) => {
const options = browserify.defaultOptions;
options.browserifyOptions.plugin.unshift(['tsify']);
// Or, if you need a custom tsconfig.json for your test files:
// options.browserifyOptions.plugin.unshift(['tsify', {project: 'path/to/other/tsconfig.json'}]);
on("file:preprocessor", cucumber(options));
};
Cucumberの書き方でテストを書くstep
ファイルを置く場所を指定(step
ファイルについては後述)
"cypress-cucumber-preprocessor": {
"step_definitions": "cypress/support/step_definitions/"
}
- 注意点として説明のしやすさの都合上今回はあえてCucunberのレガシーなスタイルである
/cypress/support/step_definitions
以下でstep
ファイルを作成する方法で進めていく - 最近は
step
ファイルを/cypress/integration
以下に任意のディレクトリを作成し、その中に置く方法を取っている場合が多い - その辺は運用次第なので各々やりやすい方法で進めてください
- その場合は上記の代わりに以下のように
package.json
を編集
// /cypress/support/step_definitions以下でstepファイルを作成していく場合は無視してください
"cypress-cucumber-preprocessor": {
"nonGlobalStepDefinitions": true
}
任意で/package.json
にいくつかのスクリプトを追加(今回は参考サイトのスクリプトを真似したのでやらなくてもよい)
"scripts": {
"cypress:open": "cypress open",
"cypress:run": "cypress run"
}
3. *.feature
の作成
- Cucumberでは
*.feature
に仕様等を定義していく - 今回はexampleでよくやるGoogle.comのページに行くテストをやってみようと思うので、とりあえず
Google.feature
を作成
Feature: Access Google
Googleの検索ページのテスト
Scenario: Googleの検索ページにアクセス
Given google.comにアクセスする
Then タイトルにGoogleがある
- Feature、Scenario、諸々の書き方等はCucumber公式を参照
- とりあえず大事なのはStep(例では
Given
、Then
だが他にもWhen
等がある)でGiven
、When
などで前提の処理を記述しThen
で期待する動作を記述する
4. *.step.ts
の作成
- Cucumberでは
step
ファイルで*.feature
で定義した内容に対応したテストを実装する - 今回は
step
ファイルを/cypress/support/step_definitions
以下にaccessingGoogle.step.ts
を作成しそこでCypressを使いつつテストを実装していく
/// <reference types="cypress"/>
import {Given, Then} from "cypress-cucumber-preprocessor/steps";
Given(`google.comにアクセスする`, () => {
cy.visit("https://google.com")
});
Then(`タイトルにGoogleがある`, () => {
cy.title().should("include", "Google")
});
注意点として以下の2点がある
- TypeScriptでやる場合、ファイルの先頭に
/// <reference types="cypress"/>
を記述する - 各Stepの第一引数の文字列は
*.feature
と一致させる必要がある
2点目についてはよく正規表現を使うことが多いが今回は必要ないと思ったためやっていない
Cypress Apiについて
-
step
ファイルの例でしれっとcy.visit(url)
等が出てきているが、他にも色々なメソッドが用意されている - どのようなメソッドがあるのかはCypress公式が全てなので各自確認するといいと思います
- とりあえず大事なのは
cy.should(arg)
で、これは明示的なアサーションに使う - この引数にはアサーションツールの「Chai」をベースにテストでアサーションを行う
-
cy.should(arg)
についてもCypress公式のshouldのページに書いてあるので確認してみてください
5. テストの実行
手っ取り早くテストの実行の方法は以下の2つのやり方がある
- 実際にブラウザが起動されてStepで実装した挙動をして、テストする
- コマンドラインで任意のコマンドによってテストする
ローカルでテストする場合は1つ目の方法でテストし、CI上でテストする等ブラウザを使わずにテストする必要がある場合は2つ目の方法でテストする
他にもタグをつけて細かくテスト対象を変えることなどもできるので色々調べてみてください
1つ目の方法でテストする場合は以下のコマンドでウィンドウが開く(今回はscriptを用意したのでそれを使用)
yarn cypress:open
ウィンドウが開いたらGoogle.feature
をクリックするとテストが走ります
2つ目の方法で実行する場合は
yarn cypress:run
ちなみにコマンドで動かした場合/cypress/videos
以下にビデオが追加され、ブラウザでの挙動がビデオで確認できる
必要ない場合は設定で追加しないようにできる
参考. ディレクトリについて
最初のdry runをしてウィンドウを閉じたらデフォルトで以下のようにディレクトリが作成される
e2e
└─cypress
├─fixtures
│ └─examples
├─integration
│ └─examples
├─plugins
└─support
とりあえず大事なのはcypress/fixture
とcypress/integration
-
cypress/fixture
:*.json
ファイルに複数のテストで使用するサンプルデータを用意しておくことができる -
cypress/integration
: 実際にテストを記述するディレクトリ -
examples
はただの例なので安全に削除可能
fixturesについて
{
"name": "foo"
}
このように用意しておくと次のようにするとテストで呼び出せる
// テストの中で
cy.fixture('foo').then((fooJson) => {
...
})
- 文法的には
cy.fixture(filePath)
でfilePath
はデフォルトでcypress/fixture
-
fooJson
にfoo.json
のデータが入る
呼び出しの方法は他にもありますが、詳細は省きます
参考にしたサイト
https://www.cypress.io/
https://docs.cypress.io/api/api/table-of-contents.html
https://github.com/TheBrainFamily/cypress-cucumber-preprocessor
https://typescript-jp.gitbook.io/deep-dive/intro-1/cypress
https://www.kaizenprogrammer.com/entry/2017/12/23/144242