自動化プロトコルとしてのChrome DevTools
ここ数年で、さまざまな機能を提供する一方で、特定制限も伴う新しいテストフレームワークが多数登場しました。Seleniumのようなツールは、動作が遅く不安定であると見なされることが多い一方、Cypress.ioやPuppeteerのようなツールは、テストの分野における将来のツールとして喧伝されています。現実には、すべてのツールには独自のユースケースがあり、サポートレベルが異なり、まったく異なるアーキテクチャに基づいています。それらを比較することは、リンゴとオレンジを比較することになるため、あまり意味がありません。大規模なテストスイートでは、これらのツールをすべて使用しても不安定さや競合状態が発生する可能性があり、現時点では、それらのいずれも(WebdriverIOを含めて)世界`/(domin|autom)ation/`の究極の解決策を見つけていないと言っても過言ではありません。
このブログ記事で発表された機能は、WebdriverIO v9以降で非推奨となりました。
結局のところ、ブラウザを自動化する方法は、大まかに言って2つあります。1つはWebDriverと呼ばれる公式のW3C Web標準を使用する方法で、もう1つは最近一部のブラウザが公開しているネイティブブラウザインターフェースを使用する方法です。WebDriverプロトコルは、すべてのデスクトップブラウザを自動化できるだけでなく、モバイルデバイス、デスクトップアプリケーション、さらにはスマートTVなどの任意のユーザーエージェントで自動化を実行できる、事実上の標準自動化技術です。WebDriverを使用しない場合、自動化フレームワークは、多くの場合、ネイティブブラウザインターフェースを使用して自動化を実行します。過去には、すべてのブラウザが独自の(しばしば文書化されていない)プロトコルを持っていましたが、現在では、Chrome、Edge、そして間もなくFirefoxを含む多くのブラウザが、Chrome DevToolsプロトコルと呼ばれるものに近い、ある程度統一されたインターフェースを備えています。WebDriverは真のクロスブラウザサポートを提供し、Sauce Labsのようなベンダーを使用して、クラウドで大規模にテストを実行できる一方、ネイティブブラウザインターフェースを使用すると、多くの場合、ネットワークイベントやDOMイベントをリッスンしてやり取りするなど、より多くの自動化機能を利用できますが、単一のブラウザに限定されることがよくあります。
WebdriverIO v5.13のリリースに伴い、テストの自動化プロトコルを指定して、両方の世界の機能を活用できる新しいオプションを導入しました。これにより、WebDriverまたはChrome DevTools(Puppeteer経由)のどちらを使用してテストを実行するかを決定できます。テスト自体には実際には何も変更はなく、自動化が異なるテクノロジーを使用して実行されるだけです。Puppeteerを使用してWebDriverコマンドを実装する新しいNPMパッケージdevtools
を作成しました。これは、WebdriverIOを使用して任意のデバイスを自動化するための独自のWebDriverベースの自動化パッケージを構築することもできる新しいタイプのプラグインです。automationProtocol
と呼ばれる新しいオプションは、文字列を想定しており、デフォルトでは、WebdriverIO自身のwebdriver
バインディングを使用して自動化を実行するために"webdriver"
に設定されています。ただし、次の方法で新しいdevtools
パッケージをインストールし、
$ npm install --save-dev devtools webdriverio
オプションでautomationProtocol: 'devtools'
を設定すると、すべての自動化が(より具体的にはPuppeteerを介して)Chrome DevTools経由で実行される一方、同じWebdriverIOコマンドインターフェースを使用します。
const { remote } = require('webdriverio')
let client;
(async function () {
client = await remote({
automationProtocol: 'devtools', // CHANGE PROTOCOL HERE
capabilities: { browserName: 'chrome' } // or `browserName: 'firefox'`
})
await client.url('https://webdriverio.dokyumento.jp')
console.log(await client.getTitle())
await client.deleteSession()
})().catch(async (e) => {
console.error(e.stack)
await client.deleteSession()
})
これは、ブラウザドライバをダウンロードする必要がないため、ローカルテストに特に便利です。ブラウザドライバのダウンロード場所や実行方法について混乱が生じることがよくあります。それに加えて、WebdriverIOはブラウザに直接接続されるため、テストの実行がはるかに高速になります。
前述したように、WebDriverを使用して大規模なクロスブラウザテストを実行する利点と、1つのツールでDevToolsのすべての追加の自動化機能を活用できるようになりました。ただし、セッション中にプロトコルを切り替えることができないという事実を考慮すると、Puppeteerの関与を必要とするテストのセットと、クラウドでクロスブラウザ実行する2番目のセットが必要になる場合があります。
テストでPuppeteerにアクセスするために、Puppeteerフレームワークのbrowser class
を返すgetPuppeteer()
というコマンドを導入しました。そこから、Puppeteerインターフェースとその他のすべてのクラスにアクセスできます。これらのインターフェースはプロミスベースのコマンドのみを提供し、WDIOテストランナーを使用するときのようにWebdriverIOがそれらをラップしないことに注意してください。この場合、他のコマンドに進む前にすべてのプロミスが解決されるようにするcall
コマンド内で、すべてのPuppeteerコマンド呼び出しを手動でラップすることをお勧めします。たとえば、次のスクリプトは、WDIOテストランナーの世界でPuppeteerを介してdevtools
自動化プロトコルを使用してWebdriverIOを使用する方法を示しています。
describe('my e2e tests', () => {
// ...
it('replaces the WebdriverIO logo with the Puppeteer logo', () => {
browser.url('https://webdriverio.dokyumento.jp')
/**
* run Puppeteer code with promises to intercept network requests
* and replace the WebdriverIO logo in the docs with the Puppeteer logo
*/
browser.call(async () => {
const puppeteerBrowser = browser.getPuppeteer()
const page = (await puppeteerBrowser.pages())[0]
await page.setRequestInterception(true)
page.on('request', interceptedRequest => {
if (interceptedRequest.url().endsWith('webdriverio.png')) {
return interceptedRequest.continue({
url: 'https://user-images.githubusercontent.com/10379601/29446482-04f7036a-841f-11e7-9872-91d1fc2ea683.png'
})
}
interceptedRequest.continue()
})
})
// continue with sync WebdriverIO commands
browser.refresh()
browser.pause(2000)
})
// ...
})
また、エクスペリエンスを可能な限りシームレスにするために、@wdio/devtools-service
のようなWDIOテストランナーサービスでdevtools
自動化プロトコルを使用できるようにしました。スタンドアロンモードで実行する完全なスクリプト例は、WebdriverIOのexampleディレクトリにあります。
機能テストでWebDriverでは提供されない何らかの自動化機能が必要な場合にのみ、devtoolsプロトコルでテストを実行することをお勧めします。また、テストの実行がはるかに高速になるため、ローカルでテストを実行するときはいつでもdevtools
に切り替えるのも理にかなっています。ベストプラクティスに従う場合は、環境ごとにwdio構成ファイル(たとえば、ローカルテストとSauce Labsまたはグリッドに対するテストの実行)を分割する必要があります。Puppeteerのやり取りを必要とする一連のテストを定義する構成を使用できるようになりました。
// wdio.devtools.conf.js
const { config } = require('./wdio.conf.js')
exports.config = Object.assign(config, {
/**
* set automation protocol to devtools
*/
automationProtocol: 'devtools',
/**
* define a set of tests that require Puppeteer involvement
*/
specs: [
'tests/e2e/devtools/**'
],
/**
* run tests only on Firefox and Chrome in headless mode
*/
capabilities: [{
browserName: 'chrome',
'goog:chromeOptions': {
headless: true
}
}, {
browserName: 'firefox',
'moz:firefoxOptions': {
headless: true
}
}]
// other specific options ...
})
新しいautomationProtocol
オプションにより、WebDriver以外の自動化テクノロジーにプロジェクトを開放しました。両方のアプローチを使用することには長所と短所があり、この機能を使用すると、1つのツールで両方を使用できます。devtools package
はまだ開発中の段階であり、今後数週間以内にすべての機能を完成させる予定です。これに関するフィードバック、バグ、またはコメントがある場合は、TwitterまたはコミュニティのDiscordサーバー経由でご連絡ください。
ありがとうございます!