【E2E】CodeceptJSのHelperを作ってみよう

今回はCodeceptJSでのHelperの作り方について紹介していきます。

Helperとは?

CodeceptJSの基本機能でフロントエンドテストは大体できますが、バックエンドテストを行うのは厳しいです。

Node.jsのライブラリを利用することでメールのチェックなどのテストを行えます。
ですが、テストコード内でコーディングしてしまうと可読性が下がってしまいます。

そこで用意するものがHelperです。
公式リファレンスでは以下のように説明されています。

Helper is a wrapper on top of various libraries providing unified interface around them.

Helperはライブラリのラッパーとして活躍してくれるやつだぜ!(意訳)」

というわけで、ラッパークラスという名のHelperを作っていきましょう。

Helperを作成してみよう

前回の記事で使ってみたJSON Server用のhelperを作っていきます。

【E2E】CodeceptJSでREST APIのテストをやろう

前回の手順ではテスト実行前にJSON Serverを手動で起動しておく必要があり、
また終了させるのにも手動で行わなければいけませんでした。

これだとJSON Serverの起動し忘れなどのミスが発生してしまう可能性があるので、
テスト開始時にJSON Serverを起動して、テスト終了時に停止するようなHelperを作成してみましょう。

JSON Serverのインストール

npm install json-server

Helperファイルの作成

npx codeceptjs initでCodeceptJSの実行なファイルを作成します。
各設定項目についてはこちらの記事を参考にしてください。

npx codeceptjs ghコマンドを実行するとHelper作成用の対話コンソールが起動します。
各設定項目はテキトーでOKです。

npx codeceptjs gh 
 
Creating a new helper
--------------------------
? Name of a Helper jsonServer
? Where should it be stored ./jsonserver_helper.js
Helper for JsonServer was created in C:\Dev\helperCreate\jsonserver_helper.js
Update your config file (add to helpers section):

helpers: {
  JsonServer: {
    require: './jsonserver_helper.js',
  },
},

作成が完了すると、設定ファイルのHelpersセクションに設定項目を追加しろ!と言われます。

「codecept.conf.js」ファイルに追記

「codecept.conf.js」を開き、Helpersセクションに追記しましょう。
あとついでにREST機能も利用するので16~27行目の設定項目を追加して保存してください。

const { setHeadlessWhen } = require('@codeceptjs/configure');

// turn on headless mode when running with HEADLESS=true environment variable
// export HEADLESS=true && npx codeceptjs run
setHeadlessWhen(process.env.HEADLESS);

exports.config = {
  tests: 'sample/*_test.js',
  output: './output',
  helpers: {
    Playwright: {
      url: 'http://localhost',
      show: true,
      browser: 'chromium'
    },
    JsonServer: {
      require: './jsonserver_helper.js',
      url: 'http://localhost',
      port: 3000,
    },
    REST: {
      endpoint: 'http://localhost:3000',
      defaultHeaders: {
        'Content-Type': 'application/json'
      },
      onRequest: (request) => {},
    },
  },
  include: {
    I: './steps_file.js'
  },
  bootstrap: null,
  mocha: {},
  name: 'helperCreate',
  translation: 'ja-JP',
  plugins: {
    pauseOnFail: {},
    retryFailedStep: {
      enabled: true
    },
    tryTo: {
      enabled: true
    },
    screenshotOnFail: {
      enabled: true
    }
  }
}

Helperファイルの確認

Helper作成用の対話コンソールで作成されたHelperファイルを開いてみましょう。
すると_beforeメソッドと_afterメソッドが用意されています。

_beforeメソッドは1つのテストシナリオの開始前に実行され、
_afterメソッドは1つのテストシナリオ終了後に実行されます。

const Helper = require('@codeceptjs/helper');

class JsonServer extends Helper {

  // before/after hooks
  /**
   * @protected
   */
  _before() {
    // remove if not used
  }

  /**
   * @protected
   */
  _after() {
    // remove if not used
  }

  // add custom methods here
  // If you need to access other helpers
  // use: this.helpers['helperName']

}

module.exports = JsonServer;

他のHook達

_before、_after以外にも用意されています。

_init 全テスト開始前。最初に1度だけ呼ばれるやつ。コンストラクタ的なイメージ。
_finishTest 全テスト終了後。最後に1度だけ呼ばれるやつ。デストラクタ的なイメージ。
_beforeSuite 各スイートの実行前。1ファイル = 1スイート的なイメージでOK。
_afterSuite 各スイートの実行前後。
_passed テストシナリオ成功時。
_failed テストシナリオ失敗時。
_before テストシナリオ開始前。テストシナリオの数だけ実行される。
_after テストシナリオ終了後。
_beforeStep テストステップ実行前。ステップ数だけ実行される。
_afterStep テストステップ実行後。ステップ数だけ実行される。

db.jsonの作成

JSON Serverで利用するためのdb.jsonを作成します。
ルートディレクトリにファイルを作成し、以下の値をコピペして保存してもらうだけでOKです。

{
  "posts": [
  ],
  "comments": [],
  "profile": {
    "name": "typicode"
  }
}

JsonServerHelperのコーディング

さて、実際にHelperを作成していきましょう。
以下のコードをHelperファイルに入力してください。

const Helper = require('@codeceptjs/helper');
const jsonServer = require('json-server');

class JsonServer extends Helper {

  constructor(config) {
    super(config);

    this.server = jsonServer.create();
    this.router = jsonServer.router('db.json');
    this.middlewares = jsonServer.defaults();
  }

  _init() {
    // JSON Server起動
        this.server.use(this.middlewares);
        this.server.use(this.router);

    if (process.argv[2] === 'def') {
      return;
    }

    this.executionJsonServer = this.server.listen(this.config.port, () => {
        console.log('JSON Server is running')
    });
  }

  _finishTest() {
    // 全てのテストが終了したらJSON Serverを停止する
        this.executionJsonServer.close();
    }
}

module.exports = JsonServer;

今回は_beforeと_afterは利用しないので削除しました。
_initを利用してテスト開始時にJSON Serverを起動し、_finishTestを利用してテスト終了時にJSON Serverを停止させています。

動作確認

さて、実際に作成したHelperが動作しているのか、テストコードを作成・実行して確認してみましょう。
REST APIを利用してJSON Serverに値を登録し、登録された内容を取得しています。

npx codeceptjs runコマンドで実行します。

Feature('JSON Server');

Scenario('REST APIで動作確認', async ({ I }) => {
    // ダミーデータを作成
    await I.sendPostRequest('/posts', {'id': '', "title": "posted from node-webhooks"});

    // JSON Serverに登録されたデータを確認する
    let result = await I.sendGetRequest('/posts?title=posted from node-webhooks');
    console.log(result.data);
});

実行結果

正常に実行できたら、以下のような実行結果が表示されているはずです。

JSON Server --
POST /posts 201 21.808 ms - 53
GET /posts?title=posted%20from%20node-webhooks 200 21.517 ms - 65
[ { title: 'posted from node-webhooks', id: 1 } ]
  √ REST APIで動作確認 in 76ms

テスト開始前にデータクリア

大体、Helperの作成は終わりましたが、
このままだとこのテストコードを実行する度にデータが増えていってしまいます。

今回はスイートごとでデータをクリアする想定で、_beforeSuite(_afterSuiteでも可)を利用して以下のコードを追記してみましょう。
登録済みのデータを全て取得して、取得数分だけ削除リクエストを送っています。

  async _beforeSuite() {
    const jsonServerUrl = `${this.config.url}:${this.config.port}/posts`;
    let result = await this.helpers['REST']._executeRequest({
      method: 'GET',
      url:jsonServerUrl,
    });

    await Promise.all(result.data.map(async (data) => {
      this.helpers['REST']._executeRequest({
        method: 'DELETE',
        url:jsonServerUrl + '/' + data.id,
      });
    }));
  }

まとめ

メールチェック、Webhookチェック、データベースチェックなどなどチェックする対象はいくらでもあります。
システムごとに必要となるHelperを作成してE2Eテストを効率的に進めてみましょう!

雑記

E2Eテストの目的は手動テストの自動化が主目的ではなく、デグレーションの検知が主目的だと考えています。
ちゃんとフロントとバックの隅々まで確認し、デグレを阻止しましょう!

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です