RESTfulAPI機能のテストとJavaScript SDK開発の裏側

PowerCMS X Advent Calendar 2021」の14日目です。

9月初旬、PowerCMS X Ver.3で新しく搭載されたRESTfulAPI機能のテストを担当することになりました。私は元々フロントエンドエンジニアとして活動してきましたが、PowerCMS Xが登場してからはPHPも読み書きすることが格段に増え、2021年はフロントエンド〜バックエンドまで通して見ることがよくありました。CMSの機能開発においてはバックエンド(CMSのコード)を見ることができる方がバグか否かの切り分けなどができて開発スピードや効率が上がるので、今回のミッションには適切な人材だったと考えます。

テストの計画

単に「テストをしてほしい」依頼を受けたので、どのようにテストをするか?から検討しました。過去に参加したセミナーなどでテストを書くことを知っていたこともありますが、以下の3点からJasmineでテストを書こうと考えました。

  • テストの記録を残すことができること
  • バグの修正後、他の箇所に不具合がでていないことが確認できること
  • 機能のリリース後も継続的にテストが実施できること(特にパッケージのアップデート版を提供するタイミング)

ブラウザ上で容易にテストを実行し結果が確認できることからJasmineを選択しました。コマンドラインを利用したテストに慣れていない人にも利用してもらうことができます。
ブラウザ上でJasmineでのテストを実行している画面

当サイトのようにJamstackで運用していると、CMSとフロントエンドは完全に分離しているのでPowerCMS Xの新しいバージョンがリリースされた場合もほぼ互換性などを気にすることなく気軽にアップデートができます。(目下個人の研究開発サイトのため、JamstackですがPowerCMS Xクラウドではなく自前でCMSをホストしています。)しかし、CMSのAPIが正しく動作することだけは強く求められます。当サイトを運用している中で「機能のリリース後も継続的にテストが実施できること」の重要性を感じることとなりました。

テストの記述とJavaScript SDKの開発

RESTfulAPIで提供される11のエンドポイントに加え、プラグインで拡張したエンドポイントについてテストを実施しました。エンドポイント毎にテストのSpecを書くとテストがスムーズでした。

オブジェクトの一覧を取得するlistエンドポイントや、単一オブジェクトを取得するgetエンドポイントはFetch APIで簡単に書けるのですが、オブジェクトを新規作成するinsertエンドポイントやオブジェクトを削除するdeleteエンドポイントは、認証を行った後でトークンを取得したり、POSTでデータを送信したりする必要がありコードが複雑になってきます。このような状況でテストを正確かつ素早く書くにはJavaScript SDKが必要だと考え、テストと同時にJavaScript SDK(PTRESTfulAPIClient)を開発することになりました。このJavaScript SDKはのちにコマンドラインでのテストでも利用できましたし、当サイトのようにNext.jsでも利用できました。

describe('Deleteのテスト', () => {
    let client;
    let token;
    let object;

    beforeAll(async () => {
        client = new PTRESTfulAPIClient(apiTestConfig.apiUrl, 1);
        const name = apiTestConfig.testUser1.name;
        const password = apiTestConfig.testUser1.password;
        const authResponse = await client.authentication(name, password);
        const authData = await authResponse.json();
        token = authData.access_token;

        const dataString = await fetch('/api_test/resouce/entry_ok.json');
        const data = await dataString.json();
        const response = await client.createObject('entry', 1, token, data);
        object = await response.json();
    });

    it('オブジェクトが削除できないこと(トークンなし)', async () => {
        const response = await client.deleteObject('entry', object.id, 1);
        expect(response.status).toBe(403);
    });

    it('オブジェクトが削除できること', async () => {
        const response = await client.deleteObject('entry', object.id, 1, token);
        const result = await response.json();
        expect(result.Success).toBeDefined();
    });

    it('該当するオブジェクトがなくHTTP 404が返ること', async () => {
        const response = await client.deleteObject('entry', 99999999, 1, token);
        expect(response.status).toBe(404);
    });
});

保守フェーズでのテスト

PowerCMS X Ver.3は2021年11月8日にリリースされました。従ってRESTfulAPI Ver.1は開発段階から保守の段階に移行したことになります。先に11あるエンドポイント毎にSpecファイルを用意したことを書きましたが、ブラウザで11ページ(プラグインを含めると12ページ)開いてテスト結果を確認するのは少々大変です。そこで、コマンドラインでテストを実行できるようにほんの少しSpecファイル等を書き換えました。テストの実行順がランダムになることを忘れ多数のテストが失敗になることにハマりましたが、設定ファイルを追加することですんなりテストが通るようになりました。
コマンドラインでJasmineでのテストを実行している画面

先月書いたようにGitHub Actionsで継続的にテストを実行することができると尚良いですが、CMSサーバーを用意する必要があることからフロントエンドのようにはできず実現には至っていません。

まとめ

テストを書くことで正しく動作しないリクエストの発見、修正後の確認とリグレッションテスト実施を適切に行う事ができ、無事RESTfulAPI機能のリリースに至りました。テスト期間は無限にあるわけではないので、定められた期間で用意されたエンドポイントについて一通りテストできたことも良かったと考えます。

記事「ウェブサイトのフロントエンドのテスト」・「ブログ検索の実装」でも取り上げましたが、テストを書くと常に正しく動作する機能・正しいコンテンツをユーザーに届けることができます。まだテストを書いたことがないエンジニアの方がいらっしゃれば、ぜひテストにチャレンジしてもらいたいと思います。

なおこの記事は『「Amazonの採用面接」と「高度情報処理技術者試験の午後Ⅱ論述問題」の共通点は何か。15字以内で答えよ』の内容を意識しつつ書いてみました。