PlaywrightとLambdaTestを用いたE2Eテストをやってみた
こんにちは!
リンクウェルオンライン診療システムチーム、フロントエンドエンジニアの松原です。
今回はPlaywrightとLambdaTestを組み合わせて、複数の OS、ブラウザでの E2E テスト自動化の方法を紹介したいと思います。
やりたいこと
特定の機種やブラウザで発生するバグはユニットテストや統合テストでは検出するのが困難でしばしば問題となっていました。
特に古い OS をサポートするのは、LambdaTest で毎回手動で立ち上げて確認するにはコストが高く、トラブルを未然に防ぐのは難しい状況でした。
そこで、今回提案する Playwright と LambdaTest を組み合わせることで、上記の問題を解決できるのではないかと検討しました。
本記事ではサンプルコードを参考に、以下の順番に説明することで最終的に、共通のコードで Playwright 単体と LambdaTest 環境で自動テストの両方に対応できる環境構築の方法を紹介したいと思います。
- 1種類の OS,ブラウザに対して LambdaTest にジョブを1ケース投げる方法
- 複数の OS,ブラウザに対して LambdaTest にジョブを1ケース投げる方法
- 複数の OS,ブラウザに対して LambdaTest にジョブを複数ケース投げる方法
- 実運用のための設定
LambdaTest とは
Playwrightは日本ユーザーも多く有名だと思いますが、LambdaTestはご存じでない方もいると思いますので、最初に紹介したいと思います。
LambdaTest は、ユーザーがさまざまなブラウザーや OS で Web サイトや Web アプリケーションをテストできる、クラウドベースのクロスブラウザーテストプラットフォームです。
手元に実機がなくても、iOS/Android の様々な機種と OS 環境でテストできるのが非常に便利で、トラブル発生時には重宝してます。
テストできるデバイスの種類はこちらから確認できます。
日本語の資料が少ないのが欠点ですが、YouTube チャンネルが豊富ですので、参考にすると良いでしょう。
自動テストするためにはWeb Automation Testing プランを契約する必要があるのですが、Manual Testing プラン登録に100分のテスト時間が付与されますので、Web Automation Testing プラン契約前に試してみると良いでしょう。
https://www.lambdatest.com/pricing
Playwright の注意点
現時点(2023/06)で Playwright は iOS/Safari のドライバーにまだ対応していないため、以下のような Android 実機でのテストは iPhone 実機でのブラウザテストには対応できないので注意が必要です。
iOS/Safari の対応は以下の issue で議論されているようです。
iOS の対応が必須の場合は appium の利用を検討すると良いかもしれません。
Github:issue: [Feature] Run Playwright tests on real mobile device browsers?
https://github.com/microsoft/playwright/issues/1122
対応デバイスの参考
https://playwright.dev/
https://developers.play.jp/entry/2022/12/09/160940
1. 単一の OS,ブラウザに対して LambdaTest にジョブを投げる方法
サンプルコードを見ながら LambdaTest にジョブを投げる方法を確認してみましょう。
まずは環境構築からです。
$ git clone https://github.com/LambdaTest/playwright-sample.git
$ cd cd playwright-sample
$ npm install
次に LambdaTest の環境変数を追加します
アカウント登録していれば、こちらのページから LT_USERNAME
と LT_ACCESS_KEY
を取得できます
$ export LT_USERNAME="your_name"
$ export LT_ACCESS_KEY="your_key"
以上が環境構築です。
早速サンプルコードを動かしてみましょう。
最も簡単なサンプルがplaywright-single.js
です。
https://github.com/LambdaTest/playwright-sample
以下を実行すると、LambdaTest にジョブを投げることができます
$ node playwright-single.js
実行結果は以下のように LambdaTest の管理画面で確認できます
今回実行したコードを確認すると、capabilities
オブジェクトに実行したい OS とブラウザの情報を設定して、
chromium.connect
に渡し、browser
オブジェクトより先は通常の Playwright の書き方となるようです。
https://github.com/LambdaTest/playwright-sample/blob/main/playwright-single.js
(async () => {
// 一つのブラウザに対する設定
const capabilities = {
// ブラウザの種類をここで設定します
'browserName': 'Chrome', // Browsers allowed: `Chrome`, `MicrosoftEdge`, `pw-chromium`, `pw-firefox` and `pw-webkit`
// ブラウザのバージョンをここで設定します
'browserVersion': 'latest',
'LT:Options': {
// 実行するPCの種類をここで設定します
'platform': 'Windows 10', // `MacOS Ventura`,`Windows 11`,等
'build': 'Playwright Single Build',
'name': 'Playwright Sample Test',
'user': process.env.LT_USERNAME,
'accessKey': process.env.LT_ACCESS_KEY,
'network': true,
'video': true,
'console': true,
'tunnel': false, // Add tunnel configuration if testing locally hosted webpage
'tunnelName': '', // Optional
'geoLocation': '', // country code can be fetched from https://www.lambdatest.com/capabilities-generator/
'playwrightClientVersion': playwrightClientVersion
}
}
const browser = await chromium.connect({
wsEndpoint: `wss://cdp.lambdatest.com/playwright?capabilities=${encodeURIComponent(JSON.stringify(capabilities))}`
})
const page = await browser.newPage()
await page.goto('https://www.bing.com')
const element = await page.$('[id="sb_form_q"]')
await element.click()
// 以下テストコード...
capabilities
の設定は LambdaTest の capabilities-generator ページから作成できます。
。
2. 複数の OS,ブラウザに対して LambdaTest にジョブを投げる方法
次は、1 つのテストケースを複数のブラウザで実行できるように拡張した場合のサンプルになります。
以下のコマンドでサンプルを実行できます。
$ node playwright-parallel.js
複数のブラウザで実行できていることが確認できました。
コードを見ると、capabilities
を配列に変えて、forEach
で複数のブラウザ条件で実行していることがわかります。
https://github.com/LambdaTest/playwright-sample/blob/main/playwright-parallel.js
// 実行したいブラウザを設定
const capabilities = [
{
'browserName': 'Chrome', // Browsers allowed: `Chrome`, `MicrosoftEdge`, `pw-chromium`, `pw-firefox` and `pw-webkit`
'browserVersion': 'latest',
'LT:Options': {
'platform': 'Windows 10',
'build': 'Playwright With Parallel Build',
'name': 'Playwright Sample Test on Windows 10 - Chrome',
'user': process.env.LT_USERNAME,
'accessKey': process.env.LT_ACCESS_KEY,
'network': true,
'video': true,
'console': true,
'playwrightClientVersion': playwrightClientVersion
}
},
{
...
]
capabilities.forEach(async (capability) => {
await parallelTests(capability)
})
3. 複数の OS,ブラウザに対して LambdaTest にジョブを複数ケース投げる方法
これまではテストケースが1つの場合のみでしたが、次は複数のテストケースに対応する例を紹介します
この例は以下のサンプルを参考にすると良いです。TypeScript の場合も用意されています。
- JavaScript の場合:
https://github.com/LambdaTest/playwright-sample/tree/main/playwright-test-js - TypeScript の場合:
https://github.com/LambdaTest/playwright-sample/tree/main/playwright-test-ts
このサンプルは以下のコマンドで実行可能です。
$ cd playwright-test-js
$ npm install
$ npm run test
このサンプルのファイル構成は以下のようになっており、3つのテストケースが用意されていました。
├── README.md
├── lambdatest-setup.js # playwrightのテストメソッドのラッパーを定義
├── package.json
├── playwright.config.js # playwrightのテスト条件に加えて、実行するブラウザを管理
└── tests # テストケース
├── multipleBrowserContexts.spec.js
├── test_1.spec.js
└── test_2.spec.js
test_1.spec.js
のテストコードを見ると、LambdaTest のことを意識しなくても Playwright のテストを書けていることがわかります。
ただしtest関数
はlambdatest-setup
からインポートしており、ここで LambdaTest の設定を加えたラッパー関数としています。
const { test } = require('../lambdatest-setup') // playwrightのtest関数をインポートしていない
const { expect } = require('@playwright/test')
test.describe('Browse LambdaTest in different search engines', () => {
test('Search LambdaTest on Bing', async ({ page }) => {
await page.goto('https://www.bing.com')
await page.waitForLoadState('domcontentloaded')
await page.waitForTimeout(3000)
const element = await page.$('[id="sb_form_q"]')
await element.click()
await element.type('LambdaTest')
await page.waitForTimeout(1000)
await page.waitForTimeout(1000)
await page.keyboard.press("Enter")
await page.waitForSelector('[class=" b_active"]')
const title = await page.title()
console.log('Page title:: ', title)
// Use the expect API for assertions provided by playwright
expect(title).toEqual(expect.stringContaining('LambdaTest'))
})
})
@playwright/test
のラッパー関数を見てみるとtestInfo
にlambdatest
の文字が含まれている場合は LambdaTest にジョブを投げる設定をし、そうでない場合は通常の Playwright のpage
を使う関数となっていました。
// 40行目 付近
exports.test = base.test.extend({
page: async ({ page, playwright }, use, testInfo) => {
// Configure LambdaTest platform for cross-browser testing
let fileName = testInfo.file.split(path.sep).pop()
if (testInfo.project.name.match(/lambdatest/)) {
modifyCapabilities(testInfo.project.name, `${testInfo.title} - ${fileName}`)
const browser = await chromium.connect({
wsEndpoint: `wss://cdp.lambdatest.com/playwright?capabilities=${encodeURIComponent(JSON.stringify(capabilities))}`
})
const ltPage = await browser.newPage(testInfo.project.use)
await use(ltPage)
const testStatus = {
action: 'setTestStatus',
arguments: {
status: testInfo.status,
remark: testInfo.error?.stack || testInfo.error?.message,
}
}
await ltPage.evaluate(() => {},
`lambdatest_action: ${JSON.stringify(testStatus)}`)
await ltPage.close()
await browser.close()
} else {
// Run tests in local in case of local config provided
await use(page)
}
}
})
testInfo
とはplaywright.config.js
にて設定されている、configオブジェクト
の中の projects
に記載されているname
が対応しているようです。下の例だとchrome:latest:MacOS Ventura@lambdatest
とchrome:latest:Windows 11@lambdatest
です。
const config = {
testDir: "tests",
testMatch: "**/*.spec.js",
timeout: 60000,
use: {},
projects: [
{
name: "chrome:latest:MacOS Ventura@lambdatest",
use: {
viewport: { width: 1920, height: 1080 },
},
},
{
name: "chrome:latest:Windows 11@lambdatest",
use: {
viewport: { width: 1280, height: 720 },
},
},
....
また、lambdatest-setup.js
では、modifyCapabilities
とうメソッドを使ってtestInfo
から各ブラウザの設定である capabilities
を作成していました
// capabilitiesのモック
const capabilities = {
'browserName': 'Chrome', // Browsers allowed: `Chrome`, `MicrosoftEdge`, `pw-chromium`, `pw-firefox` and `pw-webkit`
'browserVersion': 'latest',
'LT:Options': {
'platform': 'Windows 10',
'build': 'Playwright JS Build',
'name': 'Playwright Test',
'user': process.env.LT_USERNAME,
'accessKey': process.env.LT_ACCESS_KEY,
'network': true,
'video': true,
'console': true,
'tunnel': false, // Add tunnel configuration if testing locally hosted webpage
'tunnelName': '', // Optional
'geoLocation': '', // country code can be fetched from https://www.lambdatest.com/capabilities-generator/
'playwrightClientVersion': playwrightClientVersion
}
}
// ここでtestInfoからcapabilitiesを作成している
const modifyCapabilities = (configName, testName) => {
let config = configName.split('@lambdatest')[0]
let [browserName, browserVersion, platform] = config.split(':')
capabilities.browserName = browserName ? browserName : capabilities.browserName
capabilities.browserVersion = browserVersion ? browserVersion : capabilities.browserVersion
capabilities['LT:Options']['platform'] = platform ? platform : capabilities['LT:Options']['platform']
capabilities['LT:Options']['name'] = testName
}
例えば、testInfo
が"chrome:latest:MacOS Ventura@lambdatest"
の場合はcapabilities
次のようになります。
{
'browserName': 'Chrome',
'browserVersion': 'latest',
'LT:Options': {
'platform': 'MacOS Ventura',
'build': 'Playwright JS Build',
'name': 'Playwright Test',
'user': process.env.LT_USERNAME,
'accessKey': process.env.LT_ACCESS_KEY,
'network': true,
'video': true,
'console': true,
'tunnel': false,
'tunnelName': '',
'geoLocation': '',
'playwrightClientVersion': playwrightClientVersion
}
}
以上で、複数の OS,ブラウザに対して LambdaTest にジョブを複数ケースを実行する方法を確認しました。
4. 実運用のための設定
最後にplaywright-test-js
サンプルを参考に実運用に合わせて行うとよさそうな設定を紹介したいと思います。
Playwright 単体でも実行できるようにしておく
LambdaTest 上で実行するテスト環境と Playwright のエミュレーター上で実行する環境をそれぞれ用意します。
/**
* LambdaTest上でテストするブラウザの一覧
* nameに「@lambdatest」が含まれていると、LambdaTestのブラウザーでテストする。
*/
const lambdatestDeviceConfig = [
{
name: 'chrome:latest:MacOS Ventura@lambdatest',
use: {
viewport: { width: 1920, height: 1080 }
}
},
...
]
/**
* エミュレーター上でテストするブラウザの一覧
*/
const browserDeviceConfig = [
{
name: 'chromium',
use: {
...devices['Desktop Chrome']
}
},
...
]
次に環境変数で LambdaTest と Playwright の切り替えを制御できるようにしました。
localhost とステージング環境を切り替えたい場合はbaseURL
も環境変数で制御すると良いでしょう。
const config = {
testDir: "tests",
testMatch: "**/*.spec.js",
timeout: 60000,
use: {
// localhostやstgのURLを渡す
baseURL: process.env.PLAYWRIGHT_TEST_URL,
...
},
// LambdaTestの場合とPlaywrightの場合で設定を切り替える
projects: process.env.RUN_LAMBDATEST ? lambdatestDeviceConfig : browserDeviceConfig
};
module.exports = config;
package.json の scripts にて切り替えを制御した例が以下です
...
"scripts": {
"test:lambdatest": "PLAYWRIGHT_TEST_URL=https://stg.xxx.com && RUN_LAMBDATEST=true && npx playwright test --config=./playwright.config.js",
"test:local": "PLAYWRIGHT_TEST_URL=localhost:xxxx && npx playwright test --config=./playwright.config.js"
},
...
$ npm run test:lambdatest
$ npm run test:local
以下のように Playwright のレポートを見ることができます。
Android 実機へ対応
今回は詳細な説明をしませんでしたが、Android 実機でブラウザテストするサンプルも公式から用意されています。
https://github.com/LambdaTest/playwright-sample/blob/main/playwright-android-real-device.js
もし Android 実機でテストしたい場合は、先ほど紹介したlambdatest-setup.js
の中で Playwright と LambdaTest で場合わけしている部分に Android 実機の場合分けを追加することで対応できそうです。
// PCのテストの場合
const browser = await chromium.connect({
wsEndpoint: `wss://cdp.lambdatest.com/playwright?capabilities=${encodeURIComponent(
JSON.stringify(capabilities)
)}`,
});
const ltPage = await browser.newPage(testInfo.project.use);
// Androidのテストの場合
let device = await _android.connect(
`wss://cdp.lambdatest.com/playwright?capabilities=${encodeURIComponent(
JSON.stringify(capabilities)
)}`
);
await device.shell("am force-stop com.android.chrome");
let context = await device.launchBrowser();
let page = await context.newPage();
ただし、capability の構成が Android の場合は異なるので注意が必要です
// PCの場合
const capabilities = {
browserName: "Chrome",
browserVersion: "latest",
"LT:Options": {
platform: "Windows 10",
build: "Playwright Single Build",
name: "Playwright Sample Test",
user: process.env.LT_USERNAME,
accessKey: process.env.LT_ACCESS_KEY,
network: true,
video: true,
console: true,
tunnel: false,
tunnelName: "",
geoLocation: "",
playwrightClientVersion: playwrightClientVersion,
},
};
// Androidの場合
const capabilities = {
"LT:Options": {
platformName: "android",
deviceName: "Galaxy S21 5G",
platformVersion: "12",
isRealMobile: true,
build: "Playwright Android Build",
name: "Playwright android test",
user: process.env.LT_USERNAME,
accessKey: process.env.LT_ACCESS_KEY,
network: true,
video: true,
console: true,
projectName: "New UI",
},
};
Android の場合も PC の時と同じく公式サイトから capabilities の作成が可能です
https://www.lambdatest.com/playwright-android-capability-generator/
さいごに
Playwright と LambdaTest を組み合わせて、複数の OS、ブラウザでの E2E テスト自動化の方法を紹介しました。
iOS のリアルデバイスに対応できていないことは残念でしたが、公式の回答によると、Playwright 側の対応待ちとのことでその内対応しているかもしれません。
今後の動向もウォッチしていきたいと思います。
ありがとうございました。
Discussion