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();