Roku 服务
wdio-roku-service 是一个第三方包,更多信息请参见 GitHub | npm 此服务重写了 WebdriverIO 的许多部分,以允许它们与 Roku 应用程序一起使用,并提供对 Roku ECP 的访问,以在测试期间控制 Roku。
要求
Roku
一个测试频道/channel.zip 和一个 Roku 设备(启用了开发者模式),与您的 Mac 在同一网络上。
WebdriverIO
这不是一个独立的产品 -- 它被用作 WebdriverIO 测试框架插件(或者按照他们的术语称为 Service)。在使用之前,您应该通过运行 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。应该只有一个能力。
//wdio.conf.js
export const config: WebdriverIO.Config = {
maxInstances: 1,
capabilities: [{
browserName: 'chrome'
// 或者如果您想要无头模式:
browserName: 'chrome',
'goog:chromeOptions': {
args: ['--headless', '--disable-gpu']
}
}],
//...
}
- 建议增加
waitforInterval
和waitforTimeout
,因为每个间隔都涉及从 Roku 下载 xml。为了更好地利用browser.debug()
功能,您也可以选择延长 mocha testrunner 的超时时间到 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
文件。复制并将其重命名为 .env
,放在使用此服务的 WebdriverIO 项目中。您可能还想将其添加到 .gitignore 中。
ROKU_IP
应该是您的 Roku 的 IP。命令将使用此 IP 与之通信。这是必需的。ROKU_USER
和ROKU_PW
:需要登录凭证来安装归档文件,以及拍摄屏幕截图。ROKU_APP_PATH
应该是 Roku 频道 zip 文件的绝对路径。ROKU_CHANNEL_ID
应该是您的 Roku 频道的 ID(通常是 "dev")。DEBUG=wdio-roku-service
将启用调试消息。如果您想要这些消息,请移除行首的 '#'。
修改的函数
浏览器
waitUntil
将在每次迭代时从 Roku 获取 xml 以检查更改。saveScreenshot
将从 Roku 下载当前屏幕的截图。值得注意的是,这些截图采用 .jpg 格式,而不是 WebdriverIO 通常使用的 .png。openRokuXML
如果您需要手动而不是通过等待来获取 Roku 的 xml,可以使用此函数。
元素
- 所有等待的支持方式与浏览器相同。
waitForClickable
映射到waitForDisplayed
,waitForStable
映射到waitForExist
。 - 不支持
click
、doubleClick
和moveTo
。您必须手动导航应用程序。 isFocused
将检查元素上的focused
属性是否为 true。isDisplayed
将检查元素上的bounds
属性,并且visible
未设置为 false。如果设置了withinViewport
,则会将 bounds 与 Roku 的屏幕大小进行比较。getSize
和getLocation
从bounds
属性获取值,如果不存在,则返回大小为 0,位置为 -Infinity。
其他函数未更改,但许多仍然按预期工作。
匹配器
大多数匹配器都已更新为在等待时获取 xml。有些功能略有不同。
toBeDisplayed
、toBeDisplayedInViewport
、toBeFocused
、toBeExisting
、toBePresent
、toExist
、toHaveSize
、toHaveWidth
、toHaveHeight
和toHaveAttribute
都按预期工作,考虑到元素的更改。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');
}