Cypressを使用してExpress.js REST APIをテストする方法

Cypressは、JavaScriptアプリケーションに合わせて調整された人気の高いテストフレームワークです。主にブラウザでのUIコンポーネントとUI要素の対話をテストするために設計されていますが、APIのテストにも適しています。このフレームワークを使用して、HTTPリクエストを介してRESTful APIをテストし、レスポンスを検証できます。

Cypressを使用すると、Webアプリケーションのワークフローの全範囲にわたる包括的なテストを作成できます。

Cypressを使用したAPIテストの開始

Cypressは、APIが期待どおりに動作することを確認するのに役立ちます。このプロセスには通常、APIのエンドポイント、入力データ、およびHTTPレスポンスのテストが含まれます。外部サービスとの統合を確認し、エラー処理メカニズムが正しく機能することを確認できます。

APIをテストすることで、APIが機能していて信頼性があり、依存するアプリのニーズを満たしていることを確認します。これにより、本番環境で問題が発生するのを防ぐために、バグを早期に特定して修正するのに役立ちます。

Cypressは、一部の人気のあるJavaScriptフレームワークで使用されている優れたUIテストツールです。HTTPリクエストを作成してテストする機能により、APIのテストにも同様に効果を発揮します。

これは、Node.jsをエンジンとして使用してHTTPリクエストを作成し、そのレスポンスを処理することで実現しています。

このプロジェクトのコードは、GitHubリポジトリにあります。

Express.js REST APIの作成

開始するには、Express Webサーバーを作成し、このパッケージをプロジェクトにインストールします。

npm install cors

次に、Cypressパッケージをプロジェクトに追加します。

npm install cypress --save-dev

最後に、このテストスクリプトを含めるようにpackage.jsonファイルを更新します。

"test": "npx cypress open"

APIコントローラの定義

実際のケースでは、データベースまたは外部APIからデータを読み書きするためにAPIを呼び出します。ただし、この例では、配列からユーザーデータを追加してフェッチすることで、このようなAPI呼び出しをシミュレートしてテストします。

プロジェクトフォルダーのルートディレクトリにcontrollers/userControllers.jsファイルを作成し、次のコードを追加します。

最初に、ユーザー登録ルートを管理するregisterUserコントローラ関数を定義します。リクエストボディからユーザーのデータを取り出し、新しいユーザーオブジェクトを作成して、users配列に追加します。プロセスが成功すると、201ステータスコードとユーザーを登録したことを示すメッセージを返します。

const users = [];
exports.registerUser = async (req, res) => {
const { username, password } = req.body;
try {
const newUser = { username, password };
users.push(newUser);
res.status(201).send({ message: 'User registered successfully' });
} catch (error) {
console.error(error);
res.status(500).send({ message: 'An error occurred!!' });
}
};

2番目の関数getUsersを追加して、配列からユーザーデータを取得し、JSONレスポンスとして返します。

exports.getUsers = async (req, res) => {
try {
res.json(users);
} catch (error) {
console.error(error);
res.status(500).send({ message: 'An error occurred!!' });
}
};

最後に、ログインの試行をシミュレートすることもできます。同じファイルに、指定されたユーザー名とパスワードがusers配列のユーザーデータと一致するかどうかを確認する次のコードを追加します。

exports.loginUser = async (req, res) => {
const { username, password } = req.body;
try {
const user = users.find((u) =>
u.username === username && u.password === password);
if (user) {
res.status(200).send({ message: 'Login successful' });
} else {
res.status(401).send({ message: 'Invalid credentials' });
}
} catch (error) {
console.error(error);
res.status(500).send({ message: 'An error occurred!!' });
}
};

APIルートの定義

Express REST APIのルートを定義するには、ルートディレクトリに新しいroutes/userRoutes.jsファイルを作成し、次のコードを追加します。

const express = require('express');
const router = express.Router();
const userControllers = require('../controllers/userControllers');
const baseURL = '/v1/api/';
router.post(baseURL + 'register', userControllers.registerUser);
router.get(baseURL + 'users', userControllers.getUsers);
router.post(baseURL + 'login', userControllers.loginUser);
module.exports = router;

Server.jsファイルの更新

次の手順に従ってserver.jsファイルを更新し、APIを構成します。

const express = require('express');const cors = require('cors');const app = express();const port = 5000;app.use(express.json());app.use(express.urlencoded({ extended: true }));app.use(cors());const userRoutes = require('./routes/userRoutes');app.use('/', userRoutes);app.listen(port, () => {console.log(Server is listening at http://localhost:${port});});module.exports = app;

テスト環境の設定

デモAPIが用意できたら、テスト環境を設定する準備が整いました。次のターミナルコマンドを使用して開発サーバーを起動します。

node server.js

次に、別のターミナルでテストスクリプトコマンドを実行します。

npm run test

このコマンドはCypressデスクトップクライアントを起動し、テスト環境を提供します。起動したら、E2E Testingボタンをクリックします。エンドツーエンドテストでは、Express API全体をテストします。つまり、CypressはWebサーバー、ルート、関連するコントローラ関数にアクセスできます。

次に、ContinueをクリックしてCypress設定ファイルを追加します。

セットアッププロセスが完了すると、プロジェクトに新しいCypressフォルダーが表示されます。また、Cypressはテストの設定を含むcypress.config.jsファイルも追加します。

このファイルを更新して、サーバーのベースURLを次のように含めます。

const { defineConfig } = require("cypress");
module.exports = defineConfig({
chromeWebSecurity: false,
e2e: {
baseUrl: 'http://localhost:5000',
setupNodeEvents(on, config) {
},
},
});

テストケースを書く

これで、いくつかのテストケースを書く準備が整いました。まず、Cypressクライアントで利用可能なオプションから、Cypressがテストを実行するために起動するブラウザを選択します。

次に、Create new specボタンをクリックしてテストファイルを作成し、名前を指定します。次に、Create specをクリックします。

次に、cypress/fixtures/example.jsonファイルを開き、その内容を次のユーザー資格情報で更新します。フィクスチャは、テストケースで使用できる静的なテストデータを含むファイルです。

{
"username": "testuser",
"password": "password123"
}

Cypressは、WebサーバーにHTTPリクエストを行うcy.requestメソッドを提供しています。これを使用して、GET、POST、PUT、DELETEを含むさまざまな操作を管理するさまざまなタイプのHTTPエンドポイントをテストできます。

以前に定義した3つのAPIルートをテストするには、まず登録エンドポイントのテストケースを記述します。このテストケースは、新しいユーザーを正常に登録してアサーションを検証することにより、エンドポイントが正しく機能していることを確認する必要があります。

cypress/e2e/user.routes.spec.cy.jsファイルを開き、その内容を次のコードで更新します。

describe('User Routes', () => {it('registers a new user', () => {cy.fixture('example').then((testUser) => {cy.request({method: 'POST',url: ${baseUrl}/v1/api/register,body: testUser,}).then((response) => {expect(response.status).to.eq(201);expect(response.body.message).to.eq('User registered successfully');});});});

このテストでは、Cypressはフィクスチャファイルのテストデータを読み込み、リクエストボディのデータで指定されたエンドポイントにPOSTリクエストを行います。すべてのアサーションが通過すると、テストケースは通過します。そうでなければ、失敗します。

Cypressテストの構文は、Cypressが採用したMochaテストで使用される構文と非常によく似ていることに注意することが重要です。

次に、usersルートのテストを記述します。このテストは、このエンドポイントにリクエストが行われたときに、レスポンスにユーザーデータが含まれていることを確認する必要があります。これを実現するには、describeテストブロック内に次のコードを追加します。

it('gets users data and the username matches test data', () => {cy.fixture('example').then((expectedUserData) => {cy.request({method: 'GET',url: ${baseUrl}/v1/api/users,}).then((response) => {expect(response.status).to.eq(200);const username = response.body[0].username;expect(username).to.eq(expectedUserData.username);});});});

最後に、ログインエンドポイントをテストし、レスポンスステータスが200であることをアサートして、ログインが成功したことを示すテストケースを含めます。

it('logs in a user', () => {cy.fixture('example').then((loginData) => {cy.request({method: 'POST',url: ${baseUrl}/v1/api/login,body: loginData,}).then((response) => {expect(response.status).to.eq(200);});});});});

テストを実行するには、Cypressが管理するブラウザバージョンに戻り、実行する特定のテストファイルを選択します。

Cypressテストランナーはテストを実行し、その結果を記録し、各テストケースの合格または不合格のステータスを示します。

上記の例は、さまざまなルートとその対応するコントローラ関数をテストし、その機能と期待される動作を保証する方法を示しています。APIの機能をテストすることは不可欠ですが、テストの範囲をこの側面のみに限定すべきではありません。

包括的なAPIテスト戦略には、パフォーマンス、負荷、および他のサービスとの統合に関するテストも含まれるべきです。戦略にさまざまな種類のテスト方法を含めることで、徹底したテストカバレッジを実現し、コードを本番環境にデプロイする前にAPIが機能的で信頼できることを確認できます。

Cypressを使用したWebエクスペリエンス全体のテスト

Cypressは、Webアプリケーションをテストするための素晴らしいツールであり、フロントエンドとバックエンドの両方のテストをシームレスにカバーしています。

ユーザーフレンドリーなテスト機能により、1つのプラットフォームですべてを簡単に迅速にテスト環境をセットアップできます。その後、それを使用して、アプリケーションのさまざまな側面を徹底的にテストし、最高のパフォーマンスを保証できます。