読者です 読者をやめる 読者になる 読者になる

How To Test Electron App On Travis CI

Electron test

This is an English translation of my Japanese post on Qiita.

I recently created Shiba, which is a rich markdown previewer. I wrote some tests for it.

shibainu

I could not find Electron app which was tested well so much and how to test Electron app seemed not to be established enough. So I wrote the test for Shiba from scratch. Tests in Shiba are put around here.

Test Electron App

I used npm to execute tests as below.

$ npm test

I wrote package.json to make npm test run test runner script with node.js. I created tiny Electron app for test. And the runner script runs the test Electron app.

// scripts/run-test.js

var electron = require('electron-prebuilt');

// ...

var finished = child_process.spawnSync(
        electron,
        ['path/to/test-app', 'test-file1.js', 'test-file2.js'],
        {stdio: 'inherit'}
    );
process.exit(finished.status);

run-test.js inherits the stdio of test Electron app because tests are executed on the app and app would exit after all test executed. The test electron app in Shiba is here.

I used mocha and chai to test JavaScript (via TypeScript).

Test Codes for Browser Process

Browser process is run on iojs, so simply running tests on browser process outputs the result to console. I wrote tests as below.

app.on('ready', function() {
    let mocha = new Mocha();
    global.assert = chai.assert;

    // Add test files which are passed by process.argv

    mocha.ui('bdd').run(function(failures) {
        process.on('exit', function(){ process.exit(failures); });
        app.quit();
    });
});

We can't specify exit status to app.quit() directly but hooking app exit enables to overwrite the status as above.

Test Codes for Renderer Process

I also wrote the tests for renderer process codes with mocha and chai. I refer this page to test frontend JavaScript code with mocha and chai, install mocha and chai with bower and load them from index.html directly. As I wrote previously, I use TypeScript. So my test code for frontend is bundled as index.js. index.html simply loads index.js with <script> tag and tests them.

In order to test frontend code, we need to open the browser window. The test Electron app opens window with BrowserWindow object and loads index.html by loadUrl(). In Shiba, the code is around here. The result of tests are displayed in the window, so it is needed to call app.quit() after the window is closed.

If you have some files to test or you need to load test files dynamically, I think passing the names of files from browser process to renderer process via ipc or executing the test scripts using BrowserWindow.webContents().executeJavaScript() is good way. If browser process wants to know the result of front test executed in renderer process, it also seems to need ipc.

Test on Travis CI

It bothered me to run Electron app on Travis CI. When I tried to run Electron app simply on Travis CI, I got below error.

Gtk: cannot open display: 

Electron(Chromium) doesn't have headless mode and it seems never to be implemented.

I found that Xvfb can open a virtual display for X. I decided to use it.

Write .travis.yml

sudo: false

Although it is not related to testing Electron app, setting sudo to false is useful because it introduces new container-based worker.

I used addon to install xvfb with apt because sudo is not available.

addons:
  apt:
    packages:
      - xvfb

And then, install phase opens the virtual display by Xvfb as below.

install:
  - export DISPLAY=':99.0'
  - Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 &

$DISPLAY is necessary because Electron looks $DISPLAY on start up.

Finally, the environment to test Electron app is ready. Simply run it on script phase.

script:
  - npm test

The .travis.yml for Shiba is here.

And the log on Travis CI is here. Happy testing!