先日Circle CIのチュートリアルに「Automated testing with continuous integration for Electron applications」という記事が追加されていたのでやってみました。
ちょっと前にGithub ActionsでSpectronのE2Eテストを自動で動かせるようにならないか試してみたところ、以下のようなエラーが発生していてChromeが起動しなかったので、今度はCircle CIでやってみたいと思っていたので良いタイミングでした。
また、今後CypressはElectronをサポートする予定とないGithub issueでコメントしているので、改めてSpectronを試してみようと思いました。
Client initialization failed after ***0 attempts: RuntimeError Client initialization failed after ***0 attempts: Error: unknown error: Chrome failed to start: exited abnormally. (chrome not reachable)
環境
- Node.js (>= 11)がインストールされていること
- CircleCIアカウントがあること
- GitHubアカウントがあること
テストするElectronアプリケーションを作る
まずは、create-electron-appでアプリケーションを作ります。
$ npx create-electron-app electron-test-app
できたアプリケーションのディレクトリに移動しておきます。
$ cd electron-test-app
Electronのバージョン10.0.1が出てその変更の影響か、そのままではテスト実行時に以下のエラーが発生していました。ローカル環境のChromeのバージョンを上げる必要がありそうです。
Failed to create session. session not created: This version of ChromeDriver only supports Chrome version 83
今回は、Electronのバージョンを9.2.0に下げてやってみました。バージョン変更後、npm start
で起動します。
$ yarn upgrade electron@9.2.0 $ npm start
こんな画面が表示されたかと思います。
devtools(画面右側ペイン)が開いていると、テストを実行した時に止まったままになってしまうので、コードを修正しdevtoolsが動かないようにします。
一度、コンソールから起動したElectronアプリケーションをCtrl-C
で停止し、electron-test-app/src/index.js
をテキストエディタで開いて、mainWindow.webContents.openDevTools()
の箇所をコメントアウトします。
// electron-test-app/src/index.js 19: // Open the DevTools. 20: // mainWindow.webContents.openDevTools(); // ←ここをコメントアウト
再度、npm startでアプリケーションを起動すると、今度はdevtoolsが起動しなくなります。
JestとSpectronをセットアップする
以下を作ったアプリケーションに追加します。
- Jest
- Javascriptのテスティングフレームワーク
- Spectron
- Electronのテスティングフレームワーク
以下のコマンドを実行し、アプリケーションにJestとSpectronを追加します。
$ npm install --save-dev jest spectron
アプリケーションのルート直下にあるpackage.json
を修正し、jestのテストが実行されるようにします。
// package.json { 〜〜〜 "scripts" : { 〜〜〜 "test" : "jest" } 〜〜〜 }
テストコードを作る
src
ディレクトリに__tests__
ディレクトリを作成し、その中にAppTest.js
を作ります。
Jestがデフォルトで__tests__
ディレクトリの中のjs/ts/jsxファイルをテストとして実行してくれます。(参照)
こんなテストファイルを追加してみます。テストしている内容に関しては説明を割愛します。
const Application = require("spectron").Application; const electronPath = require("electron"); const path = require("path"); let app; beforeAll(() => { app = new Application({ path: electronPath, args: [path.join(__dirname, "../../")] }); return app.start(); }, 10000); afterAll(function () { if (app && app.isRunning()) { return app.stop(); } }); test("アプリケーションウィンドウが表示されること", async function () { let windowCount = await app.client.getWindowCount(); expect(windowCount).toBe(1); }); test("ヘッダーが適切なテキストになっていること", async function () { const headerElement = await app.client.$("h1"); let headerText = await headerElement.getText(); expect(headerText).toBe("💖 Hello World!"); });
テストを実行して、うまく動くことを確認します。
$ npm run test
Circle CI上でプロジェクトを作成
$ git init && git add . && git commit -m 'initial commit' $ git push
次にCircle CIのProjects画面上でSet Up Project
を押して、アプリケーションのプロジェクトをセットアップします。
言語毎にCIの実行内容を記述したymlファイルのテンプレートが用意されていますがElectronはないので、Use Existing Config
を押します。
とりあえずStart Building
を押して、一度セットアップを終えます。
CIの実行内容を作成
セットアップが終わったら、再度ローカルの開発環境に戻り.circleci/config.yml
というymlファイルを作成します。
$ mkdir .circleci && touch .circleci/config.yml
yml
ファイルをテキストエディタで以下のように編集して、再度GithubにpushするとCircle CIで自動的にテストが行われるようになります。
version: 2.1 jobs: build: working_directory: ~/repo docker: - image: circleci/node:11-browsers steps: - checkout - run: name: Update NPM command: "sudo npm install -g npm" - restore_cache: key: dependency-cache-{{ checksum "package-lock.json" }} - run: name: Install Dependencies command: npm install - save_cache: key: dependency-cache-{{ checksum "package-lock.json" }} paths: - ./node_modules - run: name: Run tests command: npm run test
Cicle CIの画面に戻って、Pipelinesを開くと正常にテストが動いているのを確認できます。