WordPressのブロック開発のE2Eテストを書いてみよう [Jest, puppeteer]


こんにちは、みみです。

今年のコード周りの抱負はテスト駆動開発に慣れることと、TypeScriptと仲良くなることです(すでに及び腰)。あとブログ記事をもう少しコンスタントに書きたいですね。

というわけで、最近気に入っているテストである、ブロック開発のe2eテストについて書いてみたいと思います。っていってもよく分かって無いまま雰囲気で使っている勢なので、参考に留めてください。

なぜテストが必要なのか

とそもそも疑問に思う人はきっとテストを書かなくてもいい人生なんだと思います。この記事をそっ閉じしましょう。

e2eテストとは

エンドツーエンドテスト(E2Eテスト)とは、アプリケーションのワークフローを最初から最後までテストするソフトウェアテスト手法のことである。この方法は、基本的に実際のユーザーシナリオを再現し、システムの統合性とデータの整合性を検証することを目的としています。

End to end testing (E2E testing) refers to a software testing method that involves testing an application’s workflow from beginning to end. This method basically aims to replicate real user scenarios so that the system can be validated for integration and data integrity.

https://www.browserstack.com/guide/end-to-end-testing

だそうです。わかったようなよくわからないような感じですね。

私がe2eテストというものをちゃんと認識したのはWordPressのGutenbergプロジェクトからでして、うっかりテストが関わる箇所のPR書いちゃってSnapshotもアップデートする必要があった時です。ちょっとCSS書いただけのつもりだったのになんだよすなっぷしょっとって(涙目)、てなったのが最初です。

スナップショットとは

ソフトウェア開発やプログラミングの分野では、開発中のソフトウェアについて、ある時点におけるソフトウェアを構成するプログラムコードや関連するデータなどのまとまりをスナップショットという。

https://e-words.jp/w/%E3%82%B9%E3%83%8A%E3%83%83%E3%83%97%E3%82%B7%E3%83%A7%E3%83%83%E3%83%88.html

Gutenbergでのe2eテスト

さて、Gutenbergプロジェクトには今や多数のe2eテストが書いてあり、WordPress専用のe2eテストのライブラリがあります。

e2eで使うよく聞くテストフレームワークとしてCypressJestやほかにもいくつかある様なのですが、GutenbergプロジェクトのライブラリがJestで出来ているので、今回はJestを使います。

Jestをまず触ってみるなら

公式のドキュメントとしてはココから
はじめましょう · Jest

TypeScriptならこのへん
Jest – TypeScript Deep Dive 日本語版

全く初めてな方は、まずJestがどんな感じかを↑を見ながら触ってみるのが良いかもしれません。
日本語になっててすてきですね。

Gutenbergのe2eテストの構成

Gutenbergでのe2eテストについてのドキュメントはこの辺りです。
https://github.com/WordPress/gutenberg/blob/trunk/docs/contributors/code/testing-overview.md#end-to-end-testing

つまり、 package.jsonのこの辺りが基本。

"test-e2e": "wp-scripts test-e2e --config packages/e2e-tests/jest.config.js"

jest.config.js
https://github.com/WordPress/gutenberg/blob/trunk/packages/e2e-tests/jest.config.js

というファイルで設定されている内容でのテストを実行する感じのスクリプトです。wp-scriptsはWordPress関連のスクリプトの主幹となっていて、いっろいろ入っているのでデカイですが、その分、色々してくれるのでもう無いと生きていけないやつ。

jest.config.jsはその名の通り、Jestの設定を行うファイルです。公式ドキュメントは→Jestの設定 · Jest

どのファイルをテストするか、どのファイルをIgnoreするか、使うモジュールはなにか、とかが設定されています。

つまりテストの本体は/packages/e2e-tests/specs/以下にあって、
例えばbuttonsブロックのテストは
https://github.com/WordPress/gutenberg/blob/trunk/packages/e2e-tests/specs/editor/blocks/buttons.test.js
とかになるわけです。

テストの書き方は先に書いたドキュメントの上の方にばーっと書いてあります。取り敢えず目を通しておきましょう。ほんとに書く時は、似たようなブロック用に書いてあるテストを読んで参考にするのがてっとり早い気配がします。

参考になるかわかりませんが、先のButtonsの最初にあるテストを抜き出して適当にコメントを書いてみました。

/**
 * WordPress dependencies
 */
import {
	insertBlock,
	getEditedPostContent,
	createNewPost,
	pressKeyWithModifier,
} from '@wordpress/e2e-test-utils';

describe( 'Buttons', () => {
	beforeEach( async () => { // ← テストの前に実行
		await createNewPost(); // ← 新規投稿を作成
	} );

	it( 'has focus on button content', async () => { // ← どんなテストか書くところ
		await insertBlock( 'Buttons' ); // ← Buttonsブロックを挿入する
		await page.keyboard.type( 'Content' ); // ← Contentと入力する

		expect( await getEditedPostContent() ).toMatchSnapshot(); // ← 生成されたPostの中身がSnapshotと合致するかどうか
	} );
    // 中略
}

みたいな感じで書くことができます。

最初にインポートしている @wordpress/e2e-test-utils が便利なので活用しましょう。ドキュメントはこちら@wordpress/e2e\-test\-utils \| Block Editor Handbook \| WordPress Developer Resources

カスタムブロック開発へe2eテストを導入する

というわけで、これらを参考に、カスタムブロック開発(WordPressプラグイン開発)のリポジトリにテストを導入してみましょう。

手前味噌で恐縮すが、miminari/alternative-site-logoという絶賛開発途中のリポジトリがあるのでそれを例にして説明します。

もっと参考になるブロック開発リポジトリ

自分で読み取れるぜ、という方は浜野さんやもとはちさんのリポジトリとかの方がより参考になるかと!

https://github.com/t-hamano/fse-blocks
FSE用のブロックを開発中だそうです。超楽しみ。TypeScriptで極力書かれているのでその点でも学びが多いかと。

https://github.com/mt8/hello-tencho
モダンなWordPressのプラグイン開発のセットアップとして、有名なHello Dollyをフォークして作られています。
e2eテストだけじゃなくてphpunitとか他のテストなどの書き方も学べます。コンセプトからステキ。

0. 必要なモジュールのインストール

というわけで、取り敢えず必要そうなモジュールをざっとインストールしてみます。

create blockを使って開発を開始している場合は @wordpress/scripts はすでに入っているはずなので必要ないです。

npm i @wordpress/scripts @wordpress/jest-console @wordpress/jest-puppeteer-axe @wordpress/jest-preset-default --save-dev

全部WordPressが用意しているモジュールで済んでしまうのですよね。WordPressなんでもあるな。

1. jest.config.jsを作成

/tests/e2e/jest.config.js

のようなファイルを生成します。Gutenberg本体のものよりシンプルで大丈夫なはず。

2. bootstrap.jsを作成

/tests/e2e/config/bootstrap.js

のようなファイルを生成します。
このファイルほとんど読み解いて無くて、もとはちさんの丸パクリです。多謝!
Gutenbergだと/packages/e2e-tests/config/setup-test-framework.jsというファイルでこの辺りを設定しています。

jest.config.jsのsetupFilesAfterEnvで読み込まれていて、タイムアウトの時間とかエラーの出方とかをもろもろ設定しているファイルです。

3. package.jsonに追記

私のリポジトリだと、別ファイル化しちゃってるんですが、多分浜野さんやGutenbergのリポジトリのようにpackage.jsonにそのまま書いちゃっていいと思います。

"test:e2e": "wp-scripts test-e2e --config test/e2e/jest.config.js"

4. 仮のテストを用意する

テストがちゃんと動いているかテストをするために、まずは仮のテストとして必ずtrueが返ってくるようなものをtest/e2e/specs/以下に書いてみましょう。ファイル名は、*.test.jsの形だったら何でもヨシなので、sample.test.jsとかにしてみましょう。

こんな感じです。管理画面を開いてtrueを返すだけのテスト。

import { visitAdminPage } from '@wordpress/e2e-test-utils';

describe('Sample Plugin', () => {

    it('Sample Test', async () => {
        await visitAdminPage( '/' );
        expect(true).toEqual(true);
    });

});

ここまで出来たらnpm run test:e2eを実行してみましょう。

PASS  tests/e2e/specs/sample.test.js

みたいなログが出たらテストが出来ています。やったね!🎉

逆にテストが失敗すると、ログで色々怒られて、怒られたタイミングの画面キャプチャとHTMLが自動生成されて./artifactsというフォルダ以下に自動保存されますので確認してみましょう。それ以前のエラーだったりの場合は、ごめんなさい、このブログの書き方がまずいか何かなのでエラー文読んでがんばってみてください。

デバックの puppeteer-interactive モードが楽しい

しれっと、必要そうなモジュールの中に含めているのですが、Puppeteerという、Chromeを制御するライブラリがありまして、WordPressでも採用されています。いろいろ出来るヤバイやつなのですが、プラグイン開発においては、テストのデバックをする時に意識して使うかなと思います。

wp-scripts test-e2e --config tests/e2e/jest.config.js --puppeteer-interactive

というふうに、puppeteer-interactiveモードでテストを開始すると、PC画面上でChromiumが勝手に立ち上がって勝手にテスト通りの挙動を再現し始めます。ただ、それを眺めているのが普通に楽しくて最近ハマっているポイントです。

オマケ

言語切り替えのヘルパーっぽいのを書いてみたので良かったらどうぞ。utilsにあっても良さそうなんだけど今の処ないので。

📷 Photo by Rachel on Unsplash


この記事を書いた人