Rokuサービス
wdio-roku-serviceはサードパーティのパッケージです。詳細についてはGitHub | npmをご覧ください。 このサービスはWebdriverIOの多くの部分をオーバーライドし、Rokuアプリで使用できるようにするとともに、テスト中にRokuを制御するためのRoku ECPへのアクセスを提供します。
要件
Roku
テストチャンネル/channel.zipと、macと同じネットワーク上にある開発者モードが有効なRokuデバイスが必要です。
WebdriverIO
これはスタンドアロン製品ではなく、WebdriverIOテストフレームワークのプラグイン(またはサービス)として使用されます。使用する前に、npm init wdio@latestを実行してWDIOのセットアップを完了させてください。
セットアップステップを進める際、すべての質問やオプションをナビゲートする必要がないように、初期化フェーズ中に以下の選択肢を選ぶことができます:
- Roku Testing(注:レポジトリがRokuテスト専用であれば、これがデフォルトかつ唯一のサービスとしてインストールされます。そうでない場合は、複数のサービスをインストールできるようにE2E Testingを選択してください)
- On my local machine(E2Eのみ)
- Web(E2Eのみ)
- Chrome(E2Eのみ)
- Mocha
- Typescript [modulesはTSとJSの両方で動作するので、どちらかを選択]
- autogenerate some test files (Y) -- デフォルトの場所
- page objects (Y) -- デフォルトの場所
- spec reporter
- additional plugins (N)
- Visual Testing (N)
- services (roku)
- npm install (Y)
Typescript設定
テストの記述にTypescriptを使用したい場合は、WebdriverIOによって生成されたtsconfig.jsonファイルに以下のオプションが設定されていることを確認する必要があります。
"moduleResolution": "nodenext",
"module": "NodeNext",
その後、以下に詳述するようにテストにサービスをインポートして使用できます。
WDIO設定
現在、テストは単一のRokuデバイスのみをサポートしています。以下の設定更新が必要です:
maxInstancesとmaxInstancesPerCapabilityは1にする必要があります。複数のデバイスでの自動テストはサポートされておらず、Rokuに重複したコマンドが送信される結果になります。capabilities は1つだけにしてください。
//wdio.conf.js
export const config: WebdriverIO.Config = {
maxInstances: 1,
capabilities: [{
browserName: 'chrome'
// またはヘッドレスモードを使用する場合:
browserName: 'chrome',
'goog:chromeOptions': {
args: ['--headless', '--disable-gpu']
}
}],
//...
}
- 各間隔でRokuからXMLをダウンロードするため、
waitforIntervalとwaitforTimeoutを増やすことをお勧めします。開発環境でbrowser.debug()機能をより活用するために、mochaテストランナーのタイムアウトを5分以上に延長することもできます。
//wdio.conf.js
export const config: WebdriverIO.Config = {
waitforTimeout: 30000,
//オプション:
mochaOpts: {
ui: 'bdd',
timeout: 600000
},
//...
}
これで最初のテストを書く準備ができました!
import { installFromZip } from 'wdio-roku-service/install'
import { exitChannel } from 'wdio-roku-service/channel'
import { Buttons, keyPress, keySequence } from 'wdio-roku-service/controller'
describe('first test', () => {
before('On the landing screen of the test channel', async () => {
await installFromZip(process.env.ROKU_APP_PATH)
})
it('should launch to the homescreen without login', async () => {
await $("//LoadingIndicator").waitForDisplayed({ reverse: true })
await expect($("//ContentCarousel")).toBeDisplayed()
})
after('should return to home', async () => {
await exitChannel()
})
})
また、テストのデバッグやテスト作成のために、wdioのbrowser.debug()機能を利用することをお勧めします:
// ...
it('should launch to the homescreen without login', async () => {
await $("//LoadingIndicator").waitForDisplayed({ reverse: true })
await expect($("//ContentCarousel")).toBeDisplayed()
await browser.debug()
// テストが停止し、コマンド用のREPLが利用可能になります
Chromeがヘッドレスモードでなければ、最後にopenRokuXML()が呼び出された時点(おそらくwaitForXまたはexpectを通じて)を確認できます。ターミナルのREPLを使用して、有効な$コマンドと、追加されたいくつかのカスタムコマンド(browser.openRokuXML()とbrowser.saveScreenshot('path/to/ss.jpg'))を使用できます。controllerクラスはbrowserオブジェクトにアタッチされていないため、現在それらを使用することはできません。幸いにも、おそらくあなたはRokuの隣に座っていて、アプリをナビゲートするためのリモコンを持っているでしょう。そして時々browser.openRokuXML()を呼び出して、ページの状態がどうなったかを確認できます!また、XMLはChrome ブラウザ自体のXPathと自然に連携するため、デバッグ中にChrome コンソールで直接セレクタを評価/開発できることを覚えておいてください。
.env
.env.exampleファイルを参照してください。このファイルをコピーして、このサービスを使用するWebdriverIOプロジェクト内の.envにリネームしてください。.gitignoreにも追加することをお勧めします。
ROKU_IPはRokuのIPである必要があります。コマンドはこのIPを使用してRokuと通信します。これは必須です。ROKU_USERとROKU_PW:アーカイブのインストールやスクリーンショットの撮影には、ログイン認証情報が必要です。ROKU_APP_PATHはRokuチャンネルのzipファイルの絶対パスである必要があります。ROKU_CHANNEL_IDはRokuチャンネルのIDである必要があります(通常は「dev」)。DEBUG=wdio-roku-serviceはデバッグメッセージを有効にします。それらを表示したい場合は、行の先頭にある「#」を削除してください。
変更 された関数
Browser
waitUntilは、各イテレーションでRokuからXMLをフェッチして変更を確認します。saveScreenshotはRokuから現在の画面のスクリーンショットをダウンロードします。特に、これらのスクリーンショットはWebdriverIOが通常使用する.png形式ではなく、.jpg形式です。openRokuXMLは、待機ではなく手動でRokuからXMLをフェッチする必要がある場合に使用します。
Elements
- すべての待機は、Browserと同じ方法でサポートされています。
waitForClickableはwaitForDisplayedにマップされ、waitForStableはwaitForExistにマップされています。 click、doubleClick、およびmoveToはサポートされていません。アプリを手動でナビゲートする必要があります。isFocusedは、要素のfocused属性がtrueであることをチェックします。isDisplayedは、要素のbounds属性をチェックし、visibleがfalseに設定されていないことを確認します。withinViewportが設定されている場合、境界はRokuの画面サイズと比較されます。getSizeとgetLocationはbounds属性から値を取得し、存在しない場合はサイズは0、位置は-Infinityを返します。
その他の関数は変更されていませんが、多くは期待通りに動作します。
Matchers
ほとんどのマッチャーは待機中にXMLをフェッチするように更新されています。いくつかは少し異なる機能を持っています。
toBeDisplayed、toBeDisplayedInViewport、toBeFocused、toBeExisting、toBePresent、toExist、toHaveSize、toHaveWidth、toHaveHeight、およびtoHaveAttributeはすべて、Element の変更を考慮して、期待通りに動作します。toHaveElementPropertyはtoHaveAttributeにマップされています。toHaveElementClassは要素のname属性をチェックします。toHaveIdはtoHaveElementClassにマップされています。toHaveTextは要素のtext属性をチェックします。toHaveChildrenは要素のchildren属性をチェックします。toHaveHTMLはXMLをHTMLとして扱いますが、あまり有用ではない可能性があります。
以下は現在サポートされていません:
toBeSelected- 選択されたボタンのXMLがどのように見えるか、違いがあるかどうかを判断した後、すぐにサポートされる可能性があります。toBeChecked- チェックされたチェックボックスのXMLがどのように見えるか、違いがあるかどうかを判断した後、すぐにサポートされる可能性があります。toHaveComputedLabel- Roku要素でこれと同等のものがある場合は、toHaveAttributeで属性をチェックしてください。toHaveComputedRole- Roku要素でこれと同等のものがある場合は、toHaveAttributeで属性をチェックしてください。toHaveHref- Roku要素にURLがある場合は、toHaveAttributeで属性をチェックしてください。toHaveStyle- XML要素にはスタイルがありません。toHaveClipboardText- これは不明です。toHaveTitle- タイトルはランダムに生成された一時的なXMLのファイル名になります。toHaveUrl- URLはコンピュータ上のXMLファイルへのパスになります。
使用方法
チャンネルのインストール
これには、チャンネルに割り当てられたIDが必要です。
import { installByID } from 'wdio-roku-service/install';
async before() {
await installByID(process.env.ROKU_CHANNEL_ID);
}
アーカイブのインストール
特に複数の開発者がいて、場所やファイル名が異なる可能性がある場合は、パスを.envに保存することをお勧めします。
import { installFromZip } from 'wdio-roku-service/install';
async before() {
await installFromZip(process.env.ROKU_ARCHIVE_PATH);
}
事前インストール済みチャンネル
テスト前にチャンネルを自分でインストールした場合は、単純に起動できます。
import { launchChannel, exitChannel } from 'wdio-roku-service/channel';
async before() {
// チャンネルが既に開いている場合は閉じます。チャンネルがインスタントレジュームをサポートしている場合、これは単にバックグラウンドに移動するだけです
await exitChannel();
// チャンネルIDとして'dev'を使用すると、サイドロードされたアプリケーションが起動します
await launchChannel('dev');
}
テスト
wdio-roku-service/controllerはRokuにボタン押下を送信する機能を提供します。keySequenceが主要なもので、複数のボタン押下を順番に送信します。
import { Buttons, keySequence } from 'wdio-roku-service/controller';
// アプリをナビゲート
await keySequence(Buttons.LEFT, Buttons.LEFT, Buttons.SELECT, Buttons.DOWN, Buttons.SELECT);
// 現在のアプリUIをRokuからフェッチしてブラウザにロード
await browser.openRokuXML();
// または、タイムアウトするか条件が満たされるまで繰り返しXMLをロードする待機を使用
await browser.waitUntil(condition);
await element.waitForDisplayed();
// Roku XMLをウェブページのようにWDIOマッチャーを使用
await expect(element).toHaveAttr('focused');
wdio-roku-service/controllerにはボタンの保持や解放、およびキーボードへのテキスト入力のための関数もあります。
import { Buttons, keyboardInput, keyPress, keySequence } from 'wdio-roku-service/controller';
await keySequence(Buttons.DOWN, Buttons.DOWN, Buttons.SELECT);
await keyboardInput('example');
await keyPress(Buttons.ENTER);
await browser.openRokuXML();
ディープリンク
wdio-roku-service/channelはチャンネル関連の機能を提供します。inputChannelを使用すると、アプリに任意の情報を送信できます。
import { exitChannel, launchChannel, MediaType } from 'wdio-roku-service/channel';
await exitChannel();
await launchChannel(process.env.ROKU_CHANNEL_ID, myContent, MediaType.MOVIE, {myExtraParameter:true});
await expect(MyContent.header).toBeDisplayed();