WebExtensionsのE2Eテスト自動化ツールを作った

WebExtensions の E2E テスト自動化ツール『lanthan』を作りました。 元々は Vim Vixen の E2E テストを自動化するために開発を始めたのですが、独立したモジュールとして切り出したため、様々な WebExtensions の E2E テストに利用できます。

lanthanのスクリーンショット

以前、WebExtensions の E2E テスト自動化の取り組みについて記事を書きました。

この仕組みは、テスト実行を Karma などを使ってブラウザ上で実行する必要があり、制限が多くメンテナンス性も乏しかったです。 この記事で紹介する lanthan は別のアプローチで WebExtensions の E2E テストを実行できます。 lanthan は設計を見直して 1 から作り直したライブラリで、現在の Vim Vixen も lanthan を使って E2E テストを自動実行しています。

インストール

lanthan はnpmパッケージとして公開しています。 npm installでインストールできます。

$ npm install -D lanthan

package.jsondevDependenciesに直接記述することでインストールできます。

{
  "devDependencies": {
    "lanthan": "0.0.2"
  }
}

クイックスタート

いくつかのサンプルをプロジェクトのexamplesディレクトリに用意してあります。

lanthan のセットアップと終了処理 (examples/01_setup_teardown.js)

lanthan パッケージは、ビルダークラス Builder を提供しています。

// Common JS
const { Builder } = require("lanthan")

// ES Module
import { Builder } from "lanthan"

Builder はブラウザのセッションを作成して、ブラウザにアクセスする API を提供します。 Builder は static メソッドforBrowser()で初期化します。 現在は"firefox"のみサポートしてます。 build()を呼び出すことで、Firefox が起動して、ブラウザにアクセスできる Lanthan オブジェクトを返します。

let lanthan = await Builder.forBrowser("firefox").build()

ブラウザのセッションを閉じるには quit() メソッドを呼び出します。

await lanthan.quit()

WebExtensions API を取得する (examples/02_webext_api.js)

lanthan のブラウザセッションは、リモート WebExtensions API を提供します。 これは WebExtensions 互換の API ですが、ブラウザの外から呼び出せます。 つまり Node.js などのローカル環境からブラウザを制御したり、WebExtensions の振る舞いを検証できます。

Lanthan オブジェクトの getWebExtBrowser() メソッドは WebExtensions API 互換のオブジェクトを返します。

// WebExtensions APIを取得
let browser = lanthan.getWebExtBrowser()

たとえば、タブを作成したり、現在のタブを取得できます。

// タブを作成する
await browser.tabs.create({ url: "https://example.com/" })
await browser.tabs.create({ url: "https://example.org/" })

// 全てのタブを取得する
let tabs = await browser.tabs.query({})

// 取得したタブを検証する
assert.strictEqual(tabs.length, 3)

WebDriver API を取得する (examples/03_webdriver_api.js)

lanthan は Selenium WebDriver API も提供しています。 キーイベントを送信したり、DOM を検証したり、JavaScript を実行できます。 この API はテスト自動化に役立ちます。

Lanthan オブジェクトの getWebDriver() メソッドは、Selenium WebDriver API を返します。

// WebDriver APIを取得
let webdriver = lanthan.getWebDriver()

たとえば、ページを開いてリンクをクリックする例は以下のとおりです。

// Open https://example.com/
await webdriver.navigate().to("https://example.com/")

await webdriver.findElement(By.css("a")).click()

Selenium WebDriver API の詳しい情報は、Selenium projectJavaScipt API ドキュメントを参照してください。

Add-on への spy (examples/04_spy_addon.js)

Lanthan はリモートから WebExtensions API を呼び出すために、HTTP サーバーを立てる add-on をインストールします。 これは 1 つの独立したアドオンですが、既存のアドオンに組み込むこともできます(spy)。 既存のアドオンに spy することで、内部状態(たとえば local storage)などにアクセスできます。

lanthan プロジェクトのexamples/addonに、サンプル add-on を用意しました。 このアドオンはページ内の打鍵数をカウントして、local storage にページ origin ごとの打鍵回数を保存します。

lanthan が add-on を spy するには、ビルダーオブジェクトのspyAddon()メソッドを呼び出します。

let lanthan = await Builder.forBrowser("firefox") // Lanthan currently supports only Firefox
  .spyAddon(path.join(__dirname, "addon")) // Spy to the add-on
  .build()

リモート WebExtensions API はターゲットアドオンの local storage にアクセスできるので、テストなどで検証できます。

let { count } = await browser.storage.local.get("count")
assert.strictEqual(count["https://example.com"], 1)
assert.strictEqual(count["https://example.org"], 3)
assert.strictEqual(count["https://example.net"], undefined)

まとめ

lanthan は Vim Vixen の E2E 自動化のために始めたプロジェクトですが、npm パッケージとして切り出して Vim Vixen 以外にも利用できるようにしました。 Vim Vixen は 100 を超えるテストケースを、lanthan を使って CircleCI 上で E2E テストを実行しています。

lanthan の開発は GitHub 上で進めています。 今後の開発の動向はそちらを参照してください。


Profile picture

Shin'ya Ueoka

B2B向けSaaSを提供する会社の、元Webエンジニア。今はエンジニアリング組織のマネジメントをしている。