Slide 1

Slide 1 text

WebExtensionsとテスト WebExtensions Meetup #3, 2018-10-30 @ueokande

Slide 2

Slide 2 text

Shin'ya Ueoka @ueokande WebExtensions歴1年ちょい Vim Vixen つくってます 2

Slide 3

Slide 3 text

Vim Vixen

Slide 4

Slide 4 text

Vim Vixen Vimでブラウザを操作できるWebExtensions Vimperator (XUL) が使えなくなったのが開発のきっかけ +1,000 starts、+10,000ユーザー 4

Slide 5

Slide 5 text

目次 WebExtensionsのテスト自動化 Vim Vixenの取り組み これからのVim Vixenのテスト まとめ 5

Slide 6

Slide 6 text

Vim Vixenの開発環境 本体コード5,000行 + テストコード3,000行くらい BabelでES7をトランスパイル webpackでsingle js化 CircleCIで継続的にlint + テスト 6

Slide 7

Slide 7 text

なんでテストを書くんだっけ? テストの自動化による効率化 コード品質の向上 テスタビリティが高いとメンテナンス性もよい リグレッションの早期発見 7

Slide 8

Slide 8 text

ユニットテスト E2E テスト ユニットテスト (単一の) クラス・メソッドが対象 依存メソッドはモック化したり 一番高速なテスト手法で、 テストケースも追加しやすい 8

Slide 9

Slide 9 text

E2E テスト ユニットテスト E2Eテスト ユーザーの操作に最も近いテスト 一般的に高コストで遅い 気をつけないと不安定なテスト になることもしばしば 9

Slide 10

Slide 10 text

E2E テスト ユニットテスト (理想の)テストピラミッド ユニットテストの方が 費用対効果が高い ユニットテストの比率を 大きくなるよう配分 するのが理想 10

Slide 11

Slide 11 text

Vim Vixenのユニットテスト 11

Slide 12

Slide 12 text

Vim Vixenのユニットテスト WebExtensionsはフロントエンドの技術と親和性が高い JavaScriptのユニットテストのよくある構成で実行 テストフレームワークにMocha テストランナーに Karma を使ってFirefoxを起動 12

Slide 13

Slide 13 text

ビジネスロジックのテスト ピュアなビジネスロジックはWebExtensions APIや DOM操作がない 通常のJavaScriptとしてテストできる ビジネスロジックを切り出すために設計する DDD、Clean Architecture ... 13

Slide 14

Slide 14 text

DOMアクセスのテスト content scriptではDOMアクセスが多い karma-html2js-preprocessor: Karma上でHTMLをロード HTMLファイルをJavaScriptの文字列として格納 window.__html__ オブジェクトでアクセス document.body.innerHTML = __html__['testcase1.html']; 14

Slide 15

Slide 15 text

利用例 15 describe('#myInjectElements', () => { beforeEach(() => { // render HTML from a static file document.body.innerHTML = __html__['testcase1.html']; }); it('injects three elements', () => { myInjectElements(window); let es = window.document.querySelector(".injected") expect(es).to.have.lengthOf(3); }); });

Slide 16

Slide 16 text

browserオブジェクトのモック webextensions-api-fake: browserオブジェクトをモック Karma上でbrowserオブジェクトが使える const browserFake = require('webextensions-api-fake'); const browser = browserFake(); 16

Slide 17

Slide 17 text

利用例 17 const browserFake = require('webextensions-api-fake'); describe("#myLastCreatedTab", () => { beforeEach(() => { // set fake browser to global variable global.browser = browserFake(); }); it('should get last created tab', async() => { const created = await browser.tabs.create({}); const tab = await myLastCreatedTab(); expect(tab.id).to.equal(created.id); }); });

Slide 18

Slide 18 text

E2Eテスト 18

Slide 19

Slide 19 text

Vim Vixenのリリースフロー 受け入れ条件を元に100個以上の試験項目 リグレッションが怖いのでリリース毎に全て試験 Pull Requestの本文にチェックリスト化して手動テスト 19

Slide 20

Slide 20 text

No content

Slide 21

Slide 21 text

E2Eテストの自動化 リリース毎に試験項目は増え続ける 毎リリース100以上の試験をするのは辛い E2Eテストも自動化だ! 21

Slide 22

Slide 22 text

自動化の方針 ビルド済みのVim Vixenを試験 Vim Vixen本体にテストコードを加えない ユーザーの操作に近い方法で入力と結果を観測 22

Slide 23

Slide 23 text

Vim VixenのE2E試験の仕組み テスト用の「ambassador」アドオンを作成 テストコードからメッセージ経由でキー入力や結果を観測 23

Slide 24

Slide 24 text

ambassadorアドオン (1/2) テストコードからタブ情報や別タブにキーイベントを送信 24 Background Script browser.runtime.sendMessage() browser.tabs.sendMessage() tab1 Content Script Page Script tab2 Content Script Page Script window.postMessage() press(tab2, 'j') window.body .dispatchEvent(e)

Slide 25

Slide 25 text

ambassadorアドオン (2/2) 別タブの結果の観測もメッセージ経由 25 Background Script browser.runtime.sendMessage() browser.tabs.sendMessage() tab1 Content Script Page Script tab2 Content Script Page Script window.postMessage() getScroll(tab2) document .documentElement .scrollTop {x:10, y:20} {x:10, y:20} {x:10, y:20}

Slide 26

Slide 26 text

ambassadorアドオンの実行 web-extで実行 複数アドオンをロードできるようweb-extを改造 Karmaでweb-ext用テストランナーを自作 Karma vim-vixen/manifest.json ambassador/manifest.json Vim Vixen Ambassador web-ext 26

Slide 27

Slide 27 text

E2Eテストのテストケース例 ambassadorアドオンとの通信は適当にラップ ES7 async/awaitでユーザーの操作を手続き的に記述 27 it('deletes tab by d', async () => { let tab = await tabs.create(targetWindow.id, CLIENT_URL); let before = await windows.get(targetWindow.id); await keys.press(tab.id, 'd'); let actual = await windows.get(targetWindow.id); expect(actual.tabs).to.have.lengthOf(before.tabs.length - 1); });

Slide 28

Slide 28 text

CircleCI git push毎にテストを流す lint ユニットテスト E2Eテスト パスしたPull Requestをマージ 28

Slide 29

Slide 29 text

デモ 29

Slide 30

Slide 30 text

これからのVim Vixenのテスト 30

Slide 31

Slide 31 text

ambassadorアドオンの限界 45/163ケースしか自動化できてない 他アドオンのアクセスできない領域 option_ui, storage, browserAction, ... 表示(スタイル)のリグレッション検出 31

Slide 32

Slide 32 text

Vim Vixenのこれから ユニットテストを充実させてE2Eテストを軽減 本体コードもテストしやすいような構造に CI/CDに力を入れたい git tagを打ったら新しいバーションをリリースとか 32

Slide 33

Slide 33 text

まとめ Vim Vixenで取り組んでるテストについて紹介 メンテナンスで怖くないようテストを書く WebExtensionsはフロントエンドの技術と親和性が高い Vim Vixenは品質を維持しつつ機能追加も頑張るぞい 33