Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Effective E2E Test In An Electron Application

joe_re
April 24, 2017

Effective E2E Test In An Electron Application

第36回 西日暮里.rb 「Electronではじめるアプリ開発」発売記念 LT

joe_re

April 24, 2017
Tweet

More Decks by joe_re

Other Decks in Technology

Transcript

  1. Example const app = new spectron.Application({ path: 'path/to/your/app' }); describe('application

    launch', function () { this.timeout(10000); beforeEach(function () { return app.start(); }); afterEach(function () { return app.stop(); }); it('shows an initial window', function () { return app.client.getWindowCount().then(function (count) { assert.equal(count, 1); }); }); });
  2. Strong Points Webdriver.io を通じて、任意のDOM 要素にアクセスして テストが書ける Electron のAPI をテストコードの中から透過的に呼び出す ことができる

    Electron 内部のChromium をそのまま使うのでセットアップ の手間がない( 基本的にパスを指定するだけ) Travis やAppVeyor などのCI サービスをサポートしている
  3. Why maintenance of E2E tests are difficult? E2E テストは画面変更に弱い 画面を変更すると関連するすべてのテストケースに

    影響がある 画面要素へのアクセスが大量に発生するので 修正すべき箇所を把握しづらい
  4. Page Object Pattern is... テストコードをページとシナリオに分ける アプリケーションの1 つの画面をオブジェクトと捉える (Page Object) Page

    Object にはアサーションは含まず、 ページ操作を振る舞いとして記述する アサーションはシナリオに記述する (Page Object はライブラリとして利用されるイメージ) PageObject にはアサーションは含まない 他にも原則があるので、詳しくはSelenium の公式ページへ (https://github.com/SeleniumHQ/selenium/wiki/PageObjects)
  5. Strong Points シナリオから煩雑な画面操作が取り除かれるので、 見通しが良くなる 複数のシナリオから1 つのPage Object を利用するので、 画面変更時にはPage Object

    を変更するだけで良い ( 画面変更に強い) Page Object の振る舞い === 画面操作となるので、 変更箇所の把握が用意になる
  6. Example export default class SlideEditorPage { constructor(private client: Client<void>) {}

    inputText(text: string): WebdriverIO.Client<void> { return this.client.waitForExist('#editor').then(() => { this.client.setValue('#editor textarea', text); }); } getSlideHtml(): WebdriverIO.Client<string> { return this.client.waitForExist('.slide-content') .then(() => this.client.getHTML('.slide-content')) .then((html) => typeof html === 'string' ? html : html.join()); } ... }
  7. Example function capturePage(app: Application, testName: string) { return app.browserWindow.capturePage().then((img) =>

    { fs.writeFileSync(`${outputDir}/capture_${testName}.png`, img); }); } function reportLog(app: Application, testName: string) { return Promise.all([ app.client.getRenderProcessLogs(), app.client.getMainProcessLogs() ]).then(([ rendererLogs, mainLogs ]) => { const logs = JSON.stringify({ renderer: rendererLogs, main: mainLogs }); fs.writeFileSync(`${outputDir}/logs_${testName}.txt`, logs, "utf8"); }); }
  8. 現在のSpectron(v3.6.2) では メニューの操作やファイルダイアログの 操作はできない https://github.com/electron/spectron/issues/21 Menu のAPI がJSON にserialize されていないので、process

    間通信が必要なSpectron では操作が難しい アプリケーションの操作をChrome Driver を通じて行うのが Spectron の基本なので、これらのnative なAPI を必要とする 操作に対するサポートはまだ不十分
  9. ダイアログはこんな感じで差し替える const { dialog } = require('electron'); function mockShowSaveDialog() {

    return 'sandbox/test.md'; }; function mockShowOpenDialog() { return [ 'sandbox/test.md' ]; }; dialog.showSaveDialog = mockShowSaveDialog; dialog.showOpenDialog = mockShowOpenDialog;
  10. おさらい Effective1: Using Page Object Pattern Effective2: Record the state

    at the time of test failure Effective3: Mock a native API