ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

如何把 Protractor 测试用例迁移到 Puppeteer

如何把 Protractor 测试用例迁移到 Puppeteer 如何把 Protractor 测试用例迁移到 Puppeteer【免费下载链接】puppeteerJavaScript API for Chrome and Firefox项目地址: https://gitcode.com/GitHub_Trending/puppeteer1/puppeteer如果你的 Angular 项目还依赖 Protractor 跑 e2e 测试这篇文章给出一条基于 Puppeteer 官方 Schematicpuppeteer/ng-schematics的迁移路径用 Angular CLI 的ng add命令装上 Puppeteer 测试基础设施再把 Protractor 的browser/element(by.css(...))写法逐类翻译成 Puppeteer 的page/page.locator(...)写法最后用ng e2e验证迁移后的用例能否跑通。以下内容全部来自仓库内的 Puppeteer Angular Schematic 指南 与 ng-schematics 包文档适用前提是你有一个 Angular CLI 应用目录里面存在待迁移的 Protractor e2e 用例。一、安装 Schematic用 ng add 替换 Protractor 测试栈在 Angular CLI 应用目录下执行ng add puppeteer/ng-schematics该命令会把 Schematic 作为依赖加入你的项目随后按交互提示完成配置也可以直接在命令后追加选项ng add puppeteer/ng-schematics --test-runner jasmine--test-runner是必选项决定 Schematic 随 Puppeteer 一起安装哪个测试框架可选值只有四个jasmine、jest、mocha、nodeNode Test Runner。迁移 Protractor 用例时选择与你现有断言风格一致的那个即可避免再引入一套断言库。安装完成后e2e 测试统一通过以下命令运行这也是迁移完成后验证用例的入口ng e2e如果之后还需要单独生成一个 e2e 测试文件而不是整套脚手架可以执行ng generate puppeteer/ng-schematics:e2e MyTest其中MyTest替换为你自己的测试名称命令会按 Schematic 的模板生成对应的测试文件。二、概念映射Protractor 的 browser 对应 Puppeteer 的 page迁移的第一件事是搞清楚两边的对象模型。Puppeteer 有自己的browser对象它暴露的是浏览器进程而 Protractor 里browser的语义在某个页面上操作更接近 Puppeteer 的page对象。也就是说ProtractorPuppeteer 对应物browser页面操作入口page测试框架的生命周期钩子setupBrowserHooks()提供的beforeAll/beforeEach/afterEach/afterAllSchematic 在安装时会生成一个utils.ts对应模板文件 utils.ts.template它导出两个函数是所有迁移用例的公共入口setupBrowserHooks(path )在beforeAll中调用puppeteer.launch()启动浏览器在beforeEach中通过browser.newPage()新建页面并执行page.goto(${baseUrl}${path})afterEach关闭页面afterAll关闭浏览器。其中baseUrl取自环境变量baseUrl取不到时回退到生成时的默认值。getBrowserState()返回{ browser, page, baseUrl }如果在没有调用setupBrowserHooks()的情况下调用它会抛出No browser state found! Ensure \setupBrowserHooks() is called.。因此一个 Protractor 用例迁移到 Puppeteer 后入口结构固定如下Test Name替换为你的测试名// Testing framework specific imports import {setupBrowserHooks, getBrowserState} from ./utils; describe(Test Name, function () { setupBrowserHooks(); it(is running, async function () { const {page} getBrowserState(); // Query elements await page .locator(my-component) // Click on the element once found .click(); }); });文档同时建议为了更可靠的执行和更少的 flaky 测试优先使用 Puppeteer 的 Locators API文档中标注为 Experimental。三、选择器翻译表Protractor By 换成什么Protractor 用例里最常见的by.css、by.id、by.xpath等写法在 Puppeteer 中各有对应的查询写法。下表来自官方文档的对照表CSS、ID、TEXT、XPATH是占位符迁移时替换成你用例中的实际选择器ByProtractor 代码Puppeteer querySelectorCSS (Single)$(by.css(CSS))page.$(CSS)CSS (Multiple)$$(by.css(CSS))page.$$(CSS)Id$(by.id(ID))page.$(#ID)CssContainingText$(by.cssContainingText(CSS, TEXT))page.$(CSS ::-p-text(TEXT))DeepCss$(by.deepCss(CSS))page.$(:scope CSS)XPath$(by.xpath(XPATH))page.$(::-p-xpath(XPATH)JS$(by.js(document.querySelector(CSS)))page.evaluateHandle(() document.querySelector(CSS))注意这张表没有覆盖 Protractor 全部的By形式例如by.model、by.binding见下文的完整示例——它们依赖 Angular 应用内部状态迁移时需要改写成等价的 CSS 选择器这一点示例部分会具体展示。对于 Protractorby.addLocator这类高级用法官方文档指向的是 Puppeteer 的 Custom selectors 机制属于可选进阶分支不是本次迁移的主路径。四、操作翻译click、sendKeys、clear、getAttributeProtractor 的element(locator)系列操作在 Puppeteer 中通过page.locator(locator)完成官方给出的对照如下locator替换为你的选择器// Click on the element. element(locator).click(); // Puppeteer equivalent await page.locator(locator).click(); // Send keys to the element (usually an input). element(locator).sendKeys(my text); // Puppeteer equivalent await page.locator(locator).fill(my text); // Clear the text in an element (usually an input). element(locator).clear(); // Puppeteer equivalent await page.locator(locator).fill(); // Get the value of an attribute, for example, get the value of an input. element(locator).getAttribute(value); // Puppeteer equivalent const element await page.locator(locator).waitHandle(); const value await element.getProperty(value);读取元素文本这类“取属性”的场景官方推荐的写法是用locator().map(...).wait()等待元素出现并取值// Testing framework specific imports import {setupBrowserHooks, getBrowserState} from ./utils; describe(Test Name, function () { setupBrowserHooks(); it(is running, async function () { const {page} getBrowserState(); // Query elements const elementText await page .locator(.my-component) .map(button button.innerText) // Wait for element to show up .wait(); // Assert via assertion library }); });取值后按你选定的测试框架的断言库做断言即可文档没有指定具体断言写法。五、完整示例把一段 Protractor 用例改写成 Puppeteer官方文档给了一组前后对照的完整用例是迁移时最直接的模板。原始 Protractor 用例describe(Protractor Demo, function () { it(should add one and two, function () { browser.get(https://juliemr.github.io/protractor-demo/); element(by.model(first)).sendKeys(1); element(by.model(second)).sendKeys(2); element(by.id(gobutton)).click(); expect(element(by.binding(latest)).getText()).toEqual(3); }); });对应的 Puppeteer 迁移版本import {setupBrowserHooks, getBrowserState} from ./utils; describe(Puppeteer Demo, function () { setupBrowserHooks(); it(should add one and two, function () { const {page} getBrowserState(); await page.goto(https://juliemr.github.io/protractor-demo/); await page.locator(.form-inline input:nth-child(1)).fill(1); await page.locator(.form-inline input:nth-child(2)).fill(2); await page.locator(#gobutton).fill(2); const result await page .locator(.table tbody td:last-of-type) .map(header header.innerText) .wait(); expect(result).toEqual(3); }); });从这组对照可以归纳出迁移时固定的几个动作browser.get(url)改写为await page.goto(url)by.model(first)、by.model(second)这类绑定模型名的选择器改写为页面上对应的 CSS 选择器示例中分别为.form-inline input:nth-child(1)和.form-inline input:nth-child(2)且sendKeys(1)变为fill(1)传字符串by.id(gobutton)改写为#gobuttonby.binding(latest).getText()改写为对结果区域的 CSS 定位示例为.table tbody td:last-of-type加.map(header header.innerText).wait()。也就是说by.model/by.binding没有一对一的 Puppeteer 等价写法迁移时你需要回到被测页面用 CSS 选择器或上表的 XPath、text 等选择器重新定位同样的元素。六、端口冲突e2e 测试与 ng start 同时运行Schematic 默认让 e2e 测试和ng start使用同一个端口。如果迁移期间你需要一边开着ng start调试、一边跑ng e2e就要在angular.json里给 builder 指定独立端口。把e2e或puppeteer配置取决于你项目的初始安装方式更新为{ e2e: { builder: puppeteer/ng-schematics:puppeteer, options: { commands: [...], devServerTarget: sandbox:serve, testRunner: TestRunner, port: 8080 }, ... }其中TestRunner替换为你在ng add时选择的测试框架jasmine、jest、mocha或nodebuilder 的完整参数定义见 builder schema其中还包括devServerTarget拉起服务器的 Angular target和baseUrl如果提供baseUrl则不会再拉起测试服务器。改完端口后把 e2e 目录utils.ts中的baseUrl同步改成新端口const baseUrl http://localhost:8080;这一步是必做的setupBrowserHooks()的beforeEach会把页面导航到baseUrl指向的地址utils.ts里的baseUrl与angular.json里的端口不一致时测试会访问不到应用。七、验证迁移跑 ng e2e迁移工作的完成标准只有一个ng e2e能执行通过。按上面步骤操作后回到应用目录执行ng e2e文档给出的成功条件就是测试用例按你选定的测试框架正常跑完。迁移过程中如果用例失败按本文前面的映射逐项核对常见出错点集中在两处入口结构确认每个describe都调用了setupBrowserHooks()且页面对象来自getBrowserState()没有调用 hooks 就调用getBrowserState()会直接抛出No browser state found!错误。选择器by.model、by.binding这类没有直接等价物的选择器是否已替换为正确的 CSS / XPath / text 选择器fill的参数是否都是字符串如fill(1)而非fill(1)。另外注意官方文档把 Locators API 标记为 Experimentalpage.locator(...)相关行为以后如有变化以 Puppeteer 的 Locators API 文档为准。参考资料Puppeteer Angular Schematic 指南安装、选项、端口配置与 Protractor 迁移对照表的原始出处ng-schematics 包文档与指南同内容的包内版本生成的 utils.ts 模板setupBrowserHooks/getBrowserState的实际实现builder 参数 schemaangular.json中puppeteer/ng-schematics:puppeteerbuilder 的完整参数定义。【免费下载链接】puppeteerJavaScript API for Chrome and Firefox项目地址: https://gitcode.com/GitHub_Trending/puppeteer1/puppeteer创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表