测试【免费下载链接】protractorE2E test framework for Angular apps项目地址https://gitcode.com/gh_mirrors/pr/protractor点击查看免费下载插件Plugins是 Protractor 用于扩展基础测试能力的机制通过在测试执行生命周期的各个钩子hooks中插入逻辑插件可以采集更多运行数据、对测试输出做二次加工甚至可以改写 Protractor 默认的同步行为。本文以 docs/plugins.md 为骨架结合仓库中的 lib/plugins.ts、lib/runner.ts、lib/browser.ts 与spec/plugins/下的真实配置与测试用例完整讲解如何在配置文件中启用插件、如何从零编写一个符合ProtractorPlugin接口的插件JavaScript 与 TypeScript 两种写法、插件的运行生命周期与底层调度实现并梳理 Protractor 官方及社区插件生态。Protractor 的插件 API 和官方插件目前均为BETA状态接口可能在不提升主版本号的情况下发生变化升级 Protractor 版本时需留意插件兼容性。一、插件机制概览Protractor 自身的核心能力是封装 WebDriver 会话、Angular 同步等待waitForAngular、元素定位与测试框架调度。插件机制解决的是测试执行过程中如何优雅地插入自定义逻辑的问题典型场景包括在每个页面加载完成后自动执行可访问性Accessibility审计收集测试执行时间线timeline数据并以可视化方式呈现定位测试延迟瓶颈在每个测试之后检查浏览器控制台Console日志中的警告与错误在测试运行期间注入自定义断言、向结果对象中追加通过/失败记录用自定义同步逻辑替换或补充 Protractor 默认的 Angular 稳定性检查。插件与测试框架Jasmine、Mocha 等解耦只依赖 Protractor 提供的通用钩子因此同一套插件可以跨框架复用。插件还可以通过返回一个 results 对象来改变 Protractor 的最终输出。二、在配置文件中启用插件插件通过 Protractor 配置文件protractor.conf.js中的plugins数组启用。数组中的每一项是一个插件配置对象必须且只能指定三种加载方式中的一种path、package或inline。2.1 使用path指向本地插件入口脚本// protractor.conf.js exports.config { // ... the rest of your config plugins: [{ // 每个插件唯一必需的字段插件入口脚本的路径 // 路径相对于配置文件所在目录 path: path/to/plugin/index.js, // 插件可以使用这里声明的其他选项具体见各插件文档 option1: foo, option2: bar }] };2.2 使用package引用 npm 安装的插件模块如果插件以 npm 包形式发布可以用package选项引用。例如执行npm install example-protractor-plugin之后plugins: [{ package: example-protractor-plugin, }]2.3 使用inline内联编写小型插件如果插件很小、只服务于当前这一个配置文件可以直接将插件对象内联写在配置里plugins: [{ inline: { setup: function() { ... }, teardown: function() { ... }, ... } }]2.4 配置解析的底层逻辑从源码看lib/plugins.ts 中Plugins构造函数对每个插件配置项按以下优先级解析若存在path调用ConfigParser.resolveFilePatterns(pluginConf.path, true, config.configDir)把相对路径解析为基于配置目录的真实路径解析失败会抛出Invalid path to plugin: pluginConf.path否则取package作为模块路径通过require(path)加载因此package既可以填 npm 包名也可以直接填模块路径否则若存在inline直接使用内联的插件对象三者都不存在时抛出错误Plugin configuration did not contain a valid path or inline definition.。加载成功后annotatePluginObj会为插件对象注入运行时属性详见下文提供的属性与方法并输出调试日志Plugin name loaded.。仓库 spec/plugins/smokeConf.js 中的真实示例同时演示了path与inline两种用法spec/plugins/skipStabilityConf.js 则演示了通过inline定义插件并在setup中操作this绑定到module.exports的对象。三、编写插件ProtractorPlugin接口插件本质上是 Node.js 模块导出module.exports一个实现了ProtractorPlugin接口的对象。完整的钩子列表、每个钩子的参数、返回值语义与调用时机都以 lib/plugins.ts 中ProtractorPlugin接口的 JSDoc 为准。下面逐项说明。3.1 生命周期钩子hooks钩子调用时机说明setup()测试运行前、WebDriver 会话已建立但测试框架尚未初始化时类似最早的初始化可返回 PromiseProtractor 会等待其 resolveonPrepare()测试框架已初始化、测试用例运行之前与配置文件中的onPrepare对应可访问框架特有 API如jasmine.getEnv().addReporter()teardown()测试全部运行完、WebDriver 会话销毁之前执行清理工作postResults()测试结果已最终确定、相关 job 已更新之后太晚以致无法再向测试结果追加失败断言失败只会输出到控制台postTest(passed, testInfo)每个测试块Jasmine 中即每个it块结束后异步返回值不会阻塞下一个测试的执行但 Protractor 会在输出结果前等待onPageLoad(browser)browser.get()内部、页面加载完成后、Angular 启动之前无论 Angular 是否启用都会调用onPageStable(browser)browser.get()内部、Angular 完成 bootstrap/同步之后若browser.waitForAngularEnabled()为false则不会被调用waitForPromise(browser)每个 WebDriver 动作之间waitForAngular()内部返回自定义 Promise让 Protractor 额外等待它 resolvewaitForCondition(browser)每个 WebDriver 动作之间waitForAngular()内部返回布尔值/PromisebooleanProtractor 会重复调用直到 truthy注意除onPageLoad外onPageStable、waitForPromise、waitForCondition都只在waitForAngularEnabled()为true时生效。所有钩子抛异常或返回 rejected Promise 时Protractor 都会把这次失败记录为一条失败断言若结果已上报则输出到控制台而不会让整个测试进程崩溃——这是插件机制健壮性的核心设计。3.2 其他属性与函数name?: string插件名称用于结果报告。若不指定运行时 Protractor 会填入一个合理的默认值详见下文。config?: PluginConfig插件在plugins数组中的那一项配置对象注意不是整个 Protractor 配置运行时注入已有值会被覆盖。skipAngularStability?: boolean设为true可关闭默认的 Angular 稳定性检查但保留插件的waitForPromise/waitForCondition同步逻辑与browser.ignoreSynchronization的全部关闭不同。插件作者常用它来完全接管同步逻辑。addFailure(message?, info?)向测试结果添加一条失败断言。info.specName默认值为插件名 Plugin Tests可附带stackTrace。结果已上报后再调用会抛错。addSuccess(info?)向测试结果添加一条通过断言。addWarning(message?, info?)向控制台输出警告日志。3.3 运行时注入机制Provided properties and functions文档中提到Protractor 加载插件时会为你的module.exports增加额外属性。对应实现位于 lib/plugins.ts 的annotatePluginObj方法名称回退链obj.name || conf.name || conf.path || conf.package || (Plugin # i)注入obj.config conf注入addFailure、addSuccess、addWarning三个方法断言按specName分组存入this.assertions失败断言会携带errorMsg与stackTrace。因此插件内部可以放心使用this.config读取自己的配置项、使用this.addSuccess()等注入方法——它们都是 Protractor 在加载时替你绑定好的。3.4 JavaScript 插件示例一个最简插件只需要导出一个对象// my-plugin/index.js module.exports { // 生命周期钩子 setup: function() { /* ... */ }, onPrepare: function() { /* ... */ }, teardown: function() { /* ... */ }, postResults: function() { /* ... */ }, postTest: function(passed, testInfo) { /* ... */ }, onPageLoad: function(browser) { /* ... */ }, onPageStable: function(browser) { /* ... */ }, // 同步扩展 waitForPromise: function(browser) { /* return Promise */ }, waitForCondition: function(browser) { /* return boolean | Promiseboolean */ }, // 属性 name: my-plugin, skipAngularStability: false };仓库中的真实插件示例参见 spec/plugins/plugins/basic_plugin.jssetup/onPrepare钩子、spec/plugins/plugins/async_plugin.js异步钩子 addSuccess 自定义name以及 spec/plugins/plugins/post_test_plugin.js校验postTest的passed与testInfo字段。postTest收到的testInfo对象包含name与category等字段见 spec/plugins/plugins/post_test_plugin.js 的断言可用于按测试维度记录数据。四、在 TypeScript 中编写插件TypeScript 插件有两种写法最简单的是直接镜像 JavaScript 语法通过this访问注入的方法export function onPageLoad(): void { this.addSuccess({specName: Hello, World!}); };如果需要更强的类型约束可以显式使用ProtractorPlugin接口从protractor包导出并通过declare var module: any支持module.exports赋值import {ProtractorPlugin} from protractor; // creating a var module: any will allow use of module.exports declare var module: any; let myPlugin: ProtractorPlugin { addSuccess(info: {specName: string}) { console.log(on success: info.specName); }, onPageLoad() { this.addSuccess({specName: Hello, World!}); } }; module.exports myPlugin;仓库中完整的 TypeScript 插件示例位于 exampleTypescript/plugins.ts与配套的 exampleTypescript/conf.js、exampleTypescript/spec.ts 组成可运行的示例工程可直接参考其tsconfig.json与package.json进行编译配置。五、插件生命周期与调度源码级执行时序要理解插件何时被调用最直接的依据是 lib/runner.ts 中Runner.run()的九步流程建立环境driverprovider_.setupEnv()创建浏览器并设置全局变量createBrowser(plugins)中会把plugins挂到browser_.plugins_随后setupGlobals_()插件 setupawait plugins.setup()执行测试加载框架jasmine/mocha/custom 等框架运行期间通过事件触发postTestrunner监听testPass/testFail事件分别调用plugins.postTest(true, testInfo)与plugins.postTest(false, testInfo)并把返回的 Promise 存入pluginPostTestPromises数组见 lib/runner.ts——这正是postTest不阻塞下一个测试、但会在输出结果前等待完成的实现细节等待所有 postTest Promise 完成await Promise.all(pluginPostTestPromises)插件 teardownawait plugins.teardown()合并测试结果results joinTestLogs(results, plugins.getResults())插件断言addSuccess/addFailure累积在assertions中此时并入最终结果并决定testPassed插件最终清理await plugins.postResults()退出进程根据testPassed计算退出码0/1。页面级钩子则定义在 lib/browser.tsbrowser.get()中页面加载完成后调用await this.plugins_.onPageLoad(this)即便waitForAngularEnabled()为false也会执行见 lib/browser.tsAngular 完成 bootstrap/同步后再调用await this.plugins_.onPageStable(this)见 lib/browser.ts每次waitForAngular()中先await this.plugins_.waitForPromise(this)再用driver.wait反复轮询this.plugins_.waitForCondition(this)直到所有插件条件均为 truthy 或超时超时消息为Plugins.waitForCondition()见 lib/browser.ts。5.1 调度器的容错设计lib/plugins.ts 的safeCallPluginFun是所有钩子的统一执行入口它对每个插件钩子用 async 包装try/catch捕获同步异常并处理 rejected Promise——失败时若结果尚未上报则pluginObj.addFailure(...)否则把失败打印为一条插件名 Runtime结果。pluginFunFactory见 lib/plugins.ts则把同名钩子批量分发到所有定义了该函数的插件用Promise.all汇总因此多个插件可以同时注册同一个钩子。5.2 结果合并与输出getResults()见 lib/plugins.ts把插件累积的断言按 spec 名组装成{failedCount, specResults}并通过printPluginResults以绿/红颜色输出Pass:/Fail:与失败详情含堆栈缩进。这套结构遵循 lib/frameworks/README.md 中描述的框架结果对象要求因此插件断言能与框架自身的测试结果合并后统一计入退出码。5.3skipAngularStability的运行时判定Plugins.skipAngularStability()见 lib/plugins.ts用some()检测任一已加载插件是否开启该标志供同步逻辑在运行时查询。仓库测试 spec/plugins/skipStabilityConf.js 与 spec/plugins/specs/skip_stability_spec.js 演示了如何在setup中暴露一个全局函数protractor._PluginSetSkipStability来在测试运行中途切换该标志从而在同一套测试里验证关闭同步时不等待$timeout状态停在pending...与开启同步时等待状态变为done两种行为。六、官方First Party插件Protractor 团队维护的官方插件以独立 npm 包 GitHub 仓库形式发布本仓库内不包含其源码Accessibility Plugin可访问性插件protractor-accessibility-plugin。对 Web 应用运行一组可访问性审计把审计结果转化为测试结果。Timeline Plugin时间线插件protractor-timeline-plugin。从多个来源收集测试时间线信息并以可视化方式呈现帮助定位测试中的延迟问题。Console Plugin控制台插件仅 Chromeprotractor-console-plugin。在每个测试之后检查浏览器日志中的警告与错误。ngHint Plugin已停止维护protractor-ng-hint-plugin。基于 Angular Hint 生成运行时提示并把提示转化为 Protractor 测试。官方插件的安装方式即为普通 npm 安装后通过package字段引用npm install protractor-accessibility-pluginplugins: [{ package: protractor-accessibility-plugin }]七、社区插件Community Plugins社区插件不是 Protractor 团队开发或维护的遇到问题应反馈给对应插件的开发者。文档收录的插件包括Protractor testability pluginprotractor-testability-plugin为不是基于 AngularJS 服务开发的功能提供同步测试支持。例如使用 WebSocket 与服务器通信、或使用非 AngularJS 框架构建的 Web 应用借助该插件可避免在测试中额外编写等待代码。protractor-fail-fast允许 Protractor 快速失败——一旦某个测试运行器遇到失败测试就强制所有测试运行器退出。在 CI 等失败即构建失败的场景中可大幅节省时间。protractor-numerator提供可读性更好的取元素函数例如.second()、.third()替代.get(1)、.get(2)。Ng-apimock为 AngularJS 与 Angular 应用增加基于场景scenario的 API mock 能力可用于本地开发与 Protractor 测试。protractor-cucumber-steps提供基于 Protractor 编写的 Cucumber step definitions用于端到端测试。八、最佳实践小结每个插件配置只能指定path、package、inline三者之一path相对配置文件目录package用于 npm 模块。优先使用官方定义的钩子而不是侵入测试框架钩子与框架解耦且自带失败不崩溃的容错失败会变成断言记录。善用this.config与注入方法config是你自己的配置块addSuccess/addFailure/addWarning用于产出结果specName不传时默认是插件名 Plugin Tests。异步钩子返回 PromiseProtractor 会等待setup、teardown等钩子的 PromisepostTest的 Promise 不阻塞下一个测试但会在结果输出前等待。需要接管同步时使用skipAngularStability它只关闭 Angular 稳定性检查保留插件自身的waitForPromise/waitForCondition与全局关闭的ignoreSynchronization不同。TypeScript 插件可直接镜像 JS 写法也可用ProtractorPlugin接口获得完整类型提示参考 exampleTypescript/plugins.ts。关注 BETA 状态插件 API 可能在小版本中变化升级 Protractor 后建议回归验证插件行为。九、进一步阅读插件接口完整定义与 JSDoclib/plugins.ts插件调度与测试生命周期lib/runner.ts重点看run()与runTestPreparer()页面级钩子调用点lib/browser.tsget()、waitForAngular()插件真实测试配置与用例spec/plugins/目录下的smokeConf.js、waitForAngularConf.js、skipStabilityConf.js及对应specs/用例TypeScript 插件示例exampleTypescript/plugins.ts插件结果对象与框架对接约定lib/frameworks/README.md赞分享测试【免费下载链接】protractorE2E test framework for Angular apps项目地址https://gitcode.com/gh_mirrors/pr/protractor点击查看免费下载相关推荐Egg 插件机制完全指南从配置使用到源码级原理剖析Egg 插件机制完全指南从配置使用到源码级原理剖析 本文以 Egg本仓库 egg https://link.gitcode.com/i/3790aa7d9f后端Web框架Datasette 插件系统完全指南从安装配置到源码级原理Datasette 插件系统完全指南从安装配置到源码级原理 本指南以 Datasette 官方文档 docs/plugins.rst https://link数据可视化数据分析数据库后端Docusaurus插件系统深度解析从基础使用到高级配置Docusaurus插件系统深度解析从基础使用到高级配置 前言 Docusaurus作为一个现代化的文档网站构建工具其核心设计理念之一就是插件化架构。本静态站点文档前端上一篇Windows热键侦探揭秘键盘快捷键冲突的神秘面纱下一篇你的Mac也能畅玩iOS游戏吗PlayCover打破苹果生态壁垒创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
