跳到主要内容

多重远程

WebdriverIO 允许您在单个测试中运行多个自动化会话。这在测试需要多个用户的功能时非常方便(例如,聊天或 WebRTC 应用程序)。

与其创建多个远程实例,在每个实例上都需要执行常见命令如 newSessionurl,您可以简单地创建一个 multiremote 实例并同时控制所有浏览器。

要做到这一点,只需使用 multiremote() 函数,并传入一个对象,对象的键为名称,值为 capabilities。通过给每个能力一个名称,您可以在对单个实例执行命令时轻松选择和访问该实例。

信息

Multiremote 并_不_是用来并行执行所有测试的。 它旨在帮助协调多个浏览器和/或移动设备进行特殊的集成测试(例如聊天应用程序)。

所有多重远程实例都会返回一个结果数组。第一个结果代表在能力对象中首先定义的能力,第二个结果代表第二个能力,依此类推。

使用独立模式

以下是如何在__独立模式__中创建多重远程实例的示例:

import { multiremote } from 'webdriverio'

(async () => {
const browser = await multiremote({
myChromeBrowser: {
capabilities: {
browserName: 'chrome'
}
},
myFirefoxBrowser: {
capabilities: {
browserName: 'firefox'
}
}
})

// open url with both browser at the same time
await browser.url('http://json.org')

// call commands at the same time
const title = await browser.getTitle()
expect(title).toEqual(['JSON', 'JSON'])

// click on an element at the same time
const elem = await browser.$('#someElem')
await elem.click()

// only click with one browser (Firefox)
await elem.getInstance('myFirefoxBrowser').click()
})()

使用 WDIO 测试运行器

要在 WDIO 测试运行器中使用多重远程,只需在 wdio.conf.js 中将 capabilities 对象定义为一个以浏览器名称为键的对象(而不是能力列表):

export const config = {
// ...
capabilities: {
myChromeBrowser: {
capabilities: {
browserName: 'chrome'
}
},
myFirefoxBrowser: {
capabilities: {
browserName: 'firefox'
}
}
}
// ...
}

这将创建两个使用 Chrome 和 Firefox 的 WebDriver 会话。除了 Chrome 和 Firefox,您还可以使用 Appium 启动两个移动设备,或者一个移动设备和一个浏览器。

您还可以通过将浏览器能力对象放在数组中来并行运行多重远程。请确保在每个浏览器中都包含 capabilities 字段,因为这是我们区分每种模式的方式。

export const config = {
// ...
capabilities: [{
myChromeBrowser0: {
capabilities: {
browserName: 'chrome'
}
},
myFirefoxBrowser0: {
capabilities: {
browserName: 'firefox'
}
}
}, {
myChromeBrowser1: {
capabilities: {
browserName: 'chrome'
}
},
myFirefoxBrowser1: {
capabilities: {
browserName: 'firefox'
}
}
}]
// ...
}

您甚至可以将云服务后端与本地 Webdriver/Appium 或 Selenium Standalone 实例一起启动。如果您在浏览器能力中指定了 bstack:optionsBrowserstack)、sauce:optionsSauceLabs)或 tb:optionsTestingBot),WebdriverIO 会自动检测云后端能力。

export const config = {
// ...
user: process.env.BROWSERSTACK_USERNAME,
key: process.env.BROWSERSTACK_ACCESS_KEY,
capabilities: {
myChromeBrowser: {
capabilities: {
browserName: 'chrome'
}
},
myBrowserStackFirefoxBrowser: {
capabilities: {
browserName: 'firefox',
'bstack:options': {
// ...
}
}
}
},
services: [
['browserstack', 'selenium-standalone']
],
// ...
}

这里可以使用任何操作系统/浏览器组合(包括移动和桌面浏览器)。您的测试通过 browser 变量调用的所有命令都会在每个实例上并行执行。这有助于简化集成测试并加快执行速度。

例如,如果您打开一个 URL:

browser.url('https://socketio-chat-h9jt.herokuapp.com/')

每个命令的结果将是一个对象,以浏览器名称为键,命令结果为值,如下所示:

// wdio testrunner example
await browser.url('https://www.whatismybrowser.com')

const elem = await $('.string-major')
const result = await elem.getText()

console.log(result[0]) // returns: 'Chrome 40 on Mac OS X (Yosemite)'
console.log(result[1]) // returns: 'Firefox 35 on Mac OS X (Yosemite)'

请注意,每个命令都是一个接一个执行的。这意味着命令在所有浏览器都执行完后才会完成。这很有帮助,因为它保持浏览器操作的同步,使得更容易理解当前正在发生什么。

有时,为了测试某些功能,需要在每个浏览器中执行不同的操作。例如,如果我们要测试聊天应用程序,必须有一个浏览器发送文本消息,而另一个浏览器等待接收它,然后对其进行断言。

使用 WDIO 测试运行器时,它会将浏览器名称及其实例注册到全局作用域:

const myChromeBrowser = browser.getInstance('myChromeBrowser')
await myChromeBrowser.$('#message').setValue('Hi, I am Chrome')
await myChromeBrowser.$('#send').click()

// wait until messages arrive
await $('.messages').waitForExist()
// check if one of the messages contain the Chrome message
assert.true(
(
await $$('.messages').map((m) => m.getText())
).includes('Hi, I am Chrome')
)

在这个例子中,一旦 myChromeBrowser 实例点击了 #send 按钮,myFirefoxBrowser 实例就会开始等待消息。

多重远程使控制多个浏览器变得简单方便,无论您是希望它们并行执行相同的操作,还是协同执行不同的操作。

通过浏览器对象使用字符串访问浏览器实例

除了通过全局变量(例如 myChromeBrowsermyFirefoxBrowser)访问浏览器实例外,您还可以通过 browser 对象访问它们,例如 browser["myChromeBrowser"]browser["myFirefoxBrowser"]。您可以通过 browser.instances 获取所有实例的列表。这在编写可以在任一浏览器中执行的可重用测试步骤时特别有用,例如:

wdio.conf.js:

    capabilities: {
userA: {
capabilities: {
browserName: 'chrome'
}
},
userB: {
capabilities: {
browserName: 'chrome'
}
}
}

Cucumber 文件:

When User A types a message into the chat

步骤定义文件:

When(/^User (.) types a message into the chat/, async (userId) => {
await browser.getInstance(`user${userId}`).$('#message').setValue('Hi, I am Chrome')
await browser.getInstance(`user${userId}`).$('#send').click()
})

扩展 TypeScript 类型

如果您使用 TypeScript 并希望直接从多重远程对象访问驱动程序实例,您也可以扩展多重远程类型。例如,给定以下能力:

export const config: WebdriverIO.MultiremoteConfig = {
// ...
capabilities: {
myAppiumDriver: {
// ...
},
myChromeDriver: {
// ...
}
}
// ...
}

您可以通过添加自定义驱动名称来扩展多重远程实例,例如:

declare namespace WebdriverIO {
interface MultiRemoteBrowser {
myAppiumDriver: WebdriverIO.Browser
myChromeDriver: WebdriverIO.Browser
}
}

现在您可以直接访问驱动程序,例如:

multiremotebrowser.myAppiumDriver.$$(...)
multiremotebrowser.myChromeDriver.$(...)

Welcome! How can I help?

WebdriverIO AI Copilot