1 つのツールであらゆる要素をテストしたいと思った事はありますか? 開発者なら一度はそう願ったことがあるかもしれません。実は、JavaScript フロントエンド テスト フレームワークである Cypress を使えば、ほぼほぼ叶えられるのです。 Cypress は JavaScript フロントエンド開発者向けに開発されており、サードパーティの依存関係やパッケージを追加することなく、すぐにテストの作成を始められます。 これは、Selenium といった他のツールにはない利点です。このチュートリアルでは、Cypress を使用して API テストを行う方法をご紹介します。また、このガイドに表示されているコードは全て、コピペが可能ですので是非、ガイド内に提供されているコードをご自由にお使い下さい。
本記事では以下のトピックを扱います。
- Cypress フレームワークのセットアップ
- Cypress で API に対して HTTP 呼び出しを行う方法
- Cypress の
cy.request()
メソッドの使い方
前提条件
このチュートリアルを進めるには、以下の準備が必要です。
- JavaScript と Git/GitHub の基礎を理解する
- Node.js (バージョン 10.3 以上) をローカル システムにインストールする
- CircleCI アカウントを用意する
- GitHub アカウントを用意する
Cypressとは?Cypress を使った API テストの概要
Cypressはスタンドアロン型のフロントエンド テスト ツールであり、実行時には Web アプリケーションの代わりに HTTP リクエストを行います。 一見すると Cypress がこうしたリクエストをブラウザーから送信しているように見えますが、実際には API サーバーへの HTTP リクエストを行うエンジンとして Node.js を使用します。 また、サーバーから受け取った応答を返す際にも Node.js を使用しています。
注: Cypress では、メソッド cy.request()
を公開することでフレームワーク内から HTTP リクエストを送信します。 本チュートリアルでは、Cypress を使ってエンドポイントをテストする際に、このメソッドを使用します。
ディレクトリを初期化して Cypress をセットアップする
まず、ターミナルで以下のコマンドを実行して、空のディレクトリを作成し、空の Node プロジェクトを初期化します。
mkdir testing-apis-with-cypress && cd testing-apis-with-cypress
このコマンドでディレクトリを作成したら、以下のコマンドを実行してデフォルト設定の Node.js プロジェクトを作成します。 なお、デフォルト設定の変更については、このチュートリアルの後半で扱います。 テストの作成は、初期化した Node プロジェクトで行います。
npm init -y
npm init -y
を実行すると、デフォルト設定の Node プロジェクトが作成されますが、プロジェクトの package.json
ファイルの中身をカスタマイズするためのメッセージは表示されません。 「-y」なしの npm init
を実行すると、Node プロジェクトのプロパティを設定するためのメッセージが表示されるため、package.json
ファイルの中身が変わってしまうおそれがあるので注意してください。
ディレクトリの初期化が完了したら、Cypress フレームワークをインストールします。 Cypress のインストール方法は、他の npm パッケージのインストールと同じなので、以下のどちらのコマンドでもインストールできます。
npm install cypress
または
yarn add cypress
Cypress のインストールが完了したら、次は Cypress フレームワークを初期化します。 このプロセスでは、デフォルトの Cypress ディレクトリを作成します。このディレクトリで、テストの作成やパッケージの追加 (必要な場合) を行います。
ターミナルで、コマンド cypress open
を実行します。 このコマンドを実行すると、Cypress が初期化され、Cypress のデフォルトのディレクトリとファイルが作成されます。
注: うまく行かない場合は、Cypress をグローバルにインストールしてみることをお勧めします。
Git をセットアップして CircleCI にプッシュする
テストの作成に取りかかる前に、CircleCI をセットアップする必要があります。 まず、以下のコマンドを実行してプロジェクトの Git リポジトリを初期化します。
git init
次に、ルート ディレクトリに .gitignore
ファイルを作成します。 このファイル内に node_modules
を追加して、npm で生成されたモジュールがリモート リポジトリに追加されないように設定します。 次の手順として、コミットを追加し、プロジェクトを GitHub にプッシュします。
CircleCI にログインして、[Projects (プロジェクト)] に移動します。 お使いの GitHub ユーザー名または組織に関連付けられているすべての GitHub リポジトリが一覧表示されます。 CircleCI でセットアップするリポジトリを見つけます。 このチュートリアルでは、api-testing-with-cypress
プロジェクトを使用します。 [Projects (プロジェクト)] ダッシュボードで、使用するリポジトリの [Set Up Project (プロジェクトのセットアップ)] を選択します。 既存の設定ファイルを使用するオプション ([Fastest (最速)]) を選択します。
ビルド プロセスが開始されますが、パイプラインは失敗します。これは、カスタマイズした .circleci/config.yml
ファイルをまだ GitHub に追加していないからです。
CI パイプラインを作成する
CircleCI パイプラインのセットアップが完了したら、続いては CircleCI をローカル プロジェクトに追加します。 まず、ルート ディレクトリに .circleci
というディレクトリを作成します。 このディレクトリの中に config.yml
ファイルを作成します。 config.yml に以下の設定を追加します。
version: 2
jobs:
build:
docker:
- image: cypress/base:14.16.0
environment:
## 出力を色付け
TERM: xterm
working_directory: ~/repo
steps:
- checkout
- restore_cache:
keys:
- v1-deps-{{ .Branch }}-{{ checksum "package.json" }}
- v1-deps-{{ .Branch }}
- v1-deps
- run:
name: 依存関係のインストール
command: npm ci
- save_cache:
key: v1-deps-{{ .Branch }}-{{ checksum "package.json" }}
# NPM モジュールと、Cypress バイナリ格納ディレクトリをキャッシュする
paths:
- ~/.npm
- ~/.cache
- run: $(npm bin)/cypress run
- store_artifacts:
path: ~/repo/api-testing-with-cypress
この設定ファイルでは、環境から Cypress Docker イメージをプルし、依存関係の保存済みキャッシュがあるかどうかを確認しています。
キャッシュが存在する場合は、キャッシュをリストアします。そして、save_cache
の実行時点で変更が検出された場合にのみ、アプリケーションの依存関係を更新します。 続いて、api-testing-with-cypress
の Cypress テストを実行し、キャッシュされたアイテムが ~/repo/api-testing-with-cypress
ディレクトリ内のアーティファクトに保存されます。
変更を GitHub にプッシュすると、CircleCI によって自動的にビルド プロセスが開始されます。 ここでも、まだテストを作成していないため、パイプラインは再び失敗します。 後ほどテストを追加したあとで、再度実行することにしましょう。 CircleCI のダッシュボードでは、リポジトリでテストを実行していなくても、作成されたパイプラインと実行結果を確認できます。
Cypress を使い始める
このチュートリアルでは、CircleCI があらかじめ作成して Heroku にホストしている API をアプリケーションのテストに使用します。 そのためには、まず、テストで使用する API URL (Cypress ではこれを baseUrl
と呼びます) を Cypress に認識させる必要があります。
baseUrl
を設定する
Cypress フレームワークには、Cypress の初期化プロセスで生成される設定ファイル cypress.json
が用意されています。 cypress.json
ファイルは、指定するすべての設定変数を格納するものであり、baseUrl
もこのファイルで設定します。 これによって、テストを実行する際にいちいち URL を入力する必要がなくなります。 baseUrl
は、以下のコード スニペットのように、Heroku API URL を指す設定変数として cypress.json
ファイル内で設定します。
{
"baseUrl": "http://todo-app-barkend.herokuapp.com/"
}
コマンドを設定する
テスト URL の準備ができたので、ターミナルからテストを簡単に実行できるように準備しましょう。 そのために、package.json
ファイル内の “scripts” セクションにスクリプトを 1 つ追加します。 具体的には、package.json
ファイルの “scripts” セクションに以下の test
コマンドを追加します。
"scripts": {
"test": "cypress open"
},
このコマンドは、テストの実行時に Cypress でヘッドレス モードを使用せずブラウザーを開くように設定しています。
package.json
ファイルにスクリプトを追加すると、コマンドやスクリプトを自動化でき、自分でターミナルに入力する必要がなくなります。 また、これらのコマンドやスクリプトをプログラムが理解できる形でパッケージ化すれば、npm
で実行することもできます。
Cypress でテストを作成する
フロントエンド テスト ツールである Cypress は、Cypress テストの書き方の手本となるファイルやディレクトリを豊富に生成してくれます。 ただ、このチュートリアルでは、それらは無視することにします。
Cypress の初期化と CircleCI パイプラインの設定が完了したので、いよいよテストを作成しましょう。
最初の Cypress API テストを作成する
前半で説明したとおり、Cypress では内部で Node.js を使用して HTTP リクエストをトリガーし応答を Cypress に戻すことで、アサーションや、想定される呼び出しの実行結果を検証します。 最初のテストでは、サンプルの ToDo アプリケーションに対して GET
リクエストを送信し、実際に ToDo 項目が API に返されるかを確認することにしましょう。 このテストを始めるには、cypress/integration/
ディレクトリにあるものをすべて削除しておく必要があります。 このディレクトリには、Cypress の初期化で生成されたスキャフォールドが格納されています。 この cypress/integration/
内に、api-tests
という名前のディレクトリを作成します。 Cypress にこのテスト ディレクトリのアクションを理解させるために、cypress.json
ファイルに以下の設定値を追加します。
{
"integrationFolder": "cypress/integration/api-tests"
}
次は、api-tests
ディレクトリ内に todo.spec.js
ファイルを作成します。このファイルにテストを記述します。 ここでのポイントとして、Cypress はスタンドアロンであるため、API のテストに外部の依存関係が一切必要ありません。
todo.spec.js
ファイルを開き、ToDo アプリケーションへの API GET
リクエストに対するテストを設定しましょう。 次のコードを追加します。
describe('TODO api testing', () => {
let todoItem;
it('fetches Todo items - GET', () => {
cy.request('/todos/').as('todoRequest');
cy.get('@todoRequest').then(todos => {
expect(todos.status).to.eq(200);
assert.isArray(todos.body, 'Todos Response is an array')
});
});
});
この例では、cy.request()
メソッドに baseUrl
を渡しています。 このメソッドによって、ホストされている API エンドポイントに対して ToDo 項目を取得する GET リクエストを送信し、API がテストによって呼び出されることを検証します。
注: cy.request()
は、HTTP リクエスト処理が指定されなかった場合、デフォルトで GET リクエストを行います。 そのため、API の GET
リクエストを行うように設定する必要はありません。
Cypress API テストを実行する
最初のテストを実行して問題なく動作するか確認するために、ターミナルで npm test
コマンドを実行します。 npm test
コマンドは、チュートリアルの中盤で package.json に定義したものです。 Cypress ダッシュボードが開きます。
テスト実行コマンドを実行すると、追加したテスト (spec ファイル) が Cypress ダッシュボードに表示されます。 目的のテストを選択し、Cypress が実行する様子を観察しましょう。
テストの実行が正常に完了し、すべての ToDo 項目を取得できたことがダッシュボードに表示されます。 Cypress はデフォルトでブラウザーで実行されるため、テストから返されたすべての要素を詳しく検証することができます。
画面左側で、返された配列が表示されている最後のアサーションをクリックします。 クリックすると、出力がコンソールに表示されます。 また、ウィンドウを右クリックして要素検証/調査オプションを選択すると、ブラウザーの開発者向けツールが開きます。 [Console (コンソール)] タブをクリックすると、テストでアサーションした項目の配列が表示されます。 API とテストが正常に機能していることを確認できたので、ひとまずテストは成功です。
さらにテストを作成して追加する
Cypress でのテストの追加に慣れたところで、さらにテストを追加してみましょう。 例として、新しい ToDo 項目を追加するテストと、ToDo 項目を削除するテストを作成してみます。
it('deletes Todo items - DELETE', () => {
cy.request('DELETE', `/todos/${todoItem}`).as('todoRequest');
// ID が 9 である ToDo 項目を削除する
cy.get('@todoRequest').then(todos => {
expect(todos.status).to.eq(200);
assert.isString(todos.body, 'todo deleted!')
});
});
it('Adds Todo item - POST', () => {
cy.request('POST', '/todos/', { task: "run tests" }).as('todoRequest');
// ToDo 項目の名前を定義して新規項目を追加する
cy.get('@todoRequest').then(todos => {
expect(todos.status).to.eq(200);
cy.wrap(todos.body).should('deep.include', {
task: 'run tests',
completed: false,
});
});
});
このコード スニペットでは、cy.request()
で HTTP リクエストの型を宣言しています。 新しい ToDo 項目を作成する POST
リクエストのbody
といった他の引数も、このコマンドで宣言します。 これらのテストを実行して、API で ToDo 項目を作成し、作成されたすべての ToDo 項目を取得し、ToDo 項目を削除できていることを確認しましょう。 テストが成功すれば、 API は正常に機能しています。
続いては、既存の CircleCI パイプラインでテストに合格することを確認する必要があります。 CircleCI の初期設定は既に行っているので、後は変更をコミットして GitHub にプッシュするだけです。 これで、CircleCI によりテストが自動的に実行されます。
このテストも成功しました! すべてのテストに合格できました。
おわりに
このチュートリアルでは、Cypress をセットアップして、API テストを実行する方法をご紹介しました。 テスト用に baseUrl
を設定する方法を解説し、テスト フレームワークのディレクトリを設定しました。 また、cy.request()
を使ってさまざまな HTTP 処理を行う方法と Cypress のテスト ランナーの使い方についても解説しました。 このチュートリアルで紹介した内容が、みなさまのお役に立てば幸いです。 これからもアプリケーションの開発を楽しみましょう!