ARTICLE DETAIL

资讯详情

深耕商务建站与企业官网运营的一线实战洞察。

Protractor 被测系统(System Under Test)搭建指南:URL 驱动的端到端测试与 onPrepare 全局准备实战

Protractor 被测系统(System Under Test)搭建指南:URL 驱动的端到端测试与 onPrepare 全局准备实战 测试【免费下载链接】protractorE2E test framework for Angular apps项目地址https://gitcode.com/gh_mirrors/pr/protractor点击查看免费下载本文基于本仓库 docs/system-setup.md 展开系统讲解 Protractor 端到端测试中被测系统的选择与准备方式为什么只需一个 URL 即可测试任意环境本地开发、内网预发布乃至公网生产、手动 bootstrap 与轮询型页面两类特殊场景的规避方案以及通过onPrepare完成登录等全局预置的正确姿势。读完本文你将能够为任意 Protractor 项目正确配置被测系统并写出同步可靠、无竞态条件的测试启动流程。一、被测系统的本质真实浏览器 一个 URLProtractor 与许多基于 mock 的单元测试框架最大的不同在于它使用真实浏览器执行测试。浏览器能访问什么Protractor 就能测试什么因此你在决定测什么这件事上拥有极大的自由度一个跑在localhost上的本地开发服务器内网中的预发布staging服务器甚至公网上直接面向用户的正式production服务器。对 Protractor 而言它唯一真正需要的东西就是URL。测试启动时通过browser.get(url)加载被测页面后续所有查找元素、断言、点击等操作都发生在真实浏览器渲染出的页面中。这一点也让 Protractor 与 WebDriver 生态天然对齐底层连接的可以是本地 Selenium Server、远程 Selenium 服务或直连浏览器驱动具体连接方式由配置文件中的seleniumAddress、seleniumServerJar、directConnect等选项决定详见 lib/config.ts。不过在只要给 URL 就行的宽松背后文档明确警告了三类必须小心的情况下面逐一展开。二、注意事项一手动 bootstrap 的页面 —— 请使用browser.driver.get正常情况下browser.get会在页面加载后主动等待 Angular 完成引导bootstrap并进入稳定状态。但如果你的页面不是由 Angular 自动引导而是采用手动 bootstrap例如在代码中显式调用angular.bootstrap()或使用ngUpgrade之外的定制引导流程Protractor 将无法识别并加载该页面。文档给出的解决方案是放弃browser.get改用基础 WebDriver 实例browser.driver.get// 手动 bootstrap 页面无法用 browser.get 加载 // browser.get(/ng1/login.html); // ❌ 不可靠 // 改用基础 webdriver 实例 await browser.driver.get(http://localhost:8080/login.html);browser.driver是 Protractor 对外暴露的原生WebDriver实例在 lib/browser.ts 中构造它完全绕过 Angular 同步机制直接把命令交给浏览器执行。这带来一个连锁后果Protractor 不再知道页面何时加载完成你需要自行添加wait语句否则测试容易产生竞态条件race condition——元素尚未渲染就开始点击/断言导致偶发失败。这正是仓库登录测试配置 spec/withLoginConf.js 中的做法登录页是非 Angular 手动引导页面因此先用browser.driver.get打开再配合browser.driver.wait显式等待登录跳转完成详见下文第四节。何时用browser.driver.get的经验法则页面完全不依赖 Angular或 Angular 引导由自定义逻辑触发页面是纯 WebDriver 流程的一部分如测试前的登录页只要使用了browser.driver.get就应当配套显式等待逻辑不能依赖 Protractor 的自动同步。三、注意事项二用$timeout轮询的页面 —— 改用$intervalProtractor 的核心同步机制是执行任何操作前它会等待 Angular 应用没有待处理pending的异步任务。如果你在 AngularJS 应用中使用$timeout做持续轮询那么同一时刻永远有未完成的异步任务Protractor 会一直等待下去直到触发超时。文档明确给出建议把轮询用的$timeout换成$interval。// ❌ 持续轮询 $timeoutProtractor 永远等不到稳定 // $timeout(poll, 1000); // ✅ 持续轮询请使用 $intervalAngularJS 1.2rc3 起提供 $interval(poll, 1000);这一论断在 docs/timeouts.md 中有更详细的佐证如果 AngularJS 应用持续轮询$timeout或$httpProtractor 会无限等待并超时轮询场景应使用$interval。对于使用 Zone.js 的 Angular2应用类似的思路是把长期运行的异步任务放到 Angular Zone 之外执行避免阻塞测试继续。从底层看Protractor 通过注入脚本装饰$timeout/$interval来追踪待处理任务配置项untrackOutstandingTimeouts与此相关见 lib/config.ts。因此被测应用能否被正确同步本质上取决于应用侧异步 API 的选择——这也是设置被测系统环节需要重点审查的代码层面因素。四、注意事项三全局测试准备 ——onPrepare的三种形态如果测试前需要做全局准备最典型的场景是登录文档要求你把它放进配置文件的onPrepare属性中。onPrepare是一个多态polymorphic属性既可以是函数也可以是文件名函数形态直接内联在配置文件里例如 spec/onPrepareConf.jsexports.config { framework: jasmine, specs: [onPrepare/*_spec.js], baseUrl: env.baseUrl /ng1/, onPrepare: () { browser.params.password 12345; // 预设一个全局参数 } };文件形态传入相对路径字符串Protractor 会用 Node.js 的require加载该文件并执行其内容。例如 spec/onPrepareFileConf.js 与对应的 spec/onPrepare/startup.js// onPrepareFileConf.js exports.config { specs: [onPrepare/*_spec.js], baseUrl: env.baseUrl /ng1/, onPrepare: onPrepare/startup.js // 字符串 → 文件路径 };// onPrepare/startup.js —— 文件内容即为要执行的准备逻辑 browser.params.password 12345;文件形态下路径是相对于配置文件所在目录解析的——这一点在 lib/configParser.ts 中有明确实现onPrepare与其他文件路径类配置如seleniumServerJar、chromeDriver、firefoxPath一起被统一转换为相对于当前配置文件的路径。验证这两种形态等价性的测试见 spec/onPrepare/onPrepare_spec.js其中的断言expect(browser.params.password).toEqual(12345)证明onPrepare中写入的browser.params确实在测试用例中生效。4.1onPrepare可以返回 Promise —— 时序保证的关键文档强调了一个容易被忽略但至关重要的细节onPrepare可以返回一个 PromiseProtractor 会等待它完成后再继续执行。当准备过程涉及异步调用例如与浏览器交互时必须这样做否则 Protractor 无法保证执行顺序可能在准备完成前就开始跑测试。也就是说如果onPrepare里有异步操作却不返回 Promise测试与准备之间就会出现竞态。正确写法是让onPrepare变成async函数或显式返回 Promise例如 spec/onPreparePromiseConf.jsonPrepare: async() { browser.params.password 12345; return await new Promise(resolve { setTimeout(resolve, 1000); // 模拟耗时准备 }); }文件形态同样支持返回 Promise——文件导出一个async函数即可见 spec/onPreparePromiseFileConf.js 对应的 spec/onPrepare/asyncstartup.jsmodule.exports async() { browser.params.password 12345; return await new Promise((resolve) { setTimeout(resolve, 1000); }); }4.2 源码级验证onPrepare到底怎么被执行的onPrepare的函数或文件名二选一语义由 lib/util.ts 中的内部助手runFilenameOrFn_统一实现若传入的是字符串则以configDir为基准执行require(path.resolve(configDir, filenameOrFn))加载文件加载结果若为函数则await filenameOrFn.apply(null, args)调用它await保证了返回的 Promise 会被等待——这正是Protractor 会等 onPrepare 的 Promise 完成这一行为的技术根基。调用链上lib/runner.ts 在setTestPreparer(config.onPrepare)约 L61注册准备函数随后在真正执行用例前先运行插件准备、再执行runFilenameOrFn_(this.config_.configDir, this.preparer_)约 L92-L94。结合 lib/config.ts 对onPrepare的注释还可以确认当使用 multiCapabilities 并行跑多个浏览器时onPrepare会对每个 capability 各执行一次且此时 Protractor 全局对象与测试框架全局如 Jasmine都可用你可以利用browser.getProcessedConfig()读取当前正在执行的 capability。五、实战案例用onPrepare完成登录完整可复制仓库在 spec/withLoginConf.js 中提供了一个完整的测试前登录配置是系统设置文档直接推荐的范例。完整解读如下const env require(./environment.js); exports.config { seleniumAddress: env.seleniumAddress, // 连接已运行的 Selenium Server SELENIUM_PROMISE_MANAGER: false, // 关闭 WebDriver 控制流改用 async/await framework: jasmine, specs: [login/login_spec.js], // 待运行的测试 capabilities: env.capabilities, // 浏览器能力 baseUrl: env.baseUrl /ng1/, // 被测应用基地址 onPrepare: async() { // 1) 登录页是非 Angular 手动 bootstrap 页面必须用 browser.driver.get await browser.driver.get(env.baseUrl /ng1/login.html); // 2) 直接通过 WebDriver 原生 API 填写表单 await browser.driver.findElement(by.id(username)).sendKeys(Jane); await browser.driver.findElement(by.id(password)).sendKeys(1234); await browser.driver.findElement(by.id(clickme)).click(); // 3) 登录需要时间显式等待跳转到 index.html 才继续 return await browser.driver.wait(async() { const url await browser.driver.getCurrentUrl(); return /index/.test(url); }, 10000); } };这个例子把本文第二、四节的要点全部落地登录页不可用browser.get→ 用browser.driver.get打开并全程使用browser.driver.findElement而非element(...)操作表单准备是异步的→onPrepare声明为async并返回 Promisereturn await browser.driver.wait(...)显式等待消除竞态→ 用browser.driver.wait轮询当前 URL 是否包含index超时上限 10 秒确认登录跳转完成后才放行测试。配套的测试用例见 spec/login/login_spec.js登录态通过 cookie 保持测试直接browser.get(baseUrl /ng1/index.html)进入主页面断言登录后的 cookietestcookie值为Jane-1234从而验证onPrepare建立的会话确实在整个测试过程中有效。六、为被测系统补齐配套配置除了onPrepare与baseUrl搭建被测系统时通常还会涉及以下配置均出自 lib/config.ts 的完整注释配置项作用说明baseUrl被测应用基地址browser.get()传入相对路径时会基于它解析url.resolve语义见 lib/config.tsgetPageTimeout页面加载超时毫秒默认 10 秒超时错误形如Timed out waiting for page to load after 10000ms可全局配置或按次传参browser.get(address, timeout)见 docs/timeouts.mdallScriptsTimeoutAngular 同步超时毫秒默认约 11 秒若应用异步任务迟迟不结束会触发见 docs/timeouts.mdcapabilities/multiCapabilities单/多浏览器能力可附加count、shardTestFiles、maxInstances等并行参数见 lib/config.tsspecs/suites指定要跑的测试specs为相对当前配置文件的路径模式见 lib/config.ts两个直接的工程建议为被测应用准备多种环境地址由于被测系统只需 URL可在配置中按环境切换baseUrl如http://localhost:4200与https://staging.example.com配合params甚至命令行参数--params.xxx见 lib/config.ts实现一套配置多环境复用把页面是否由 Angular 引导、是否持续轮询当作被测系统的验收标准上线测试前先检查应用侧这两类代码特征能从根本上避免同步超时与竞态远比在测试侧打补丁可靠。小结设置被测系统对 Protractor 来说本质是回答三个问题被测页面能不能被browser.get正常加载应用会不会让 Protractor 永远等不到稳定进入主流程前需要做什么全局准备本文从 docs/system-setup.md 出发结合仓库源码与配置示例给出了完整答案手动 bootstrap 页面用browser.driver.get 显式等待轮询用$interval替代$timeout登录等全局准备放进onPrepare函数或文件皆可异步时必须返回 Promise。沿着这三条主线即可在任意环境上搭建出稳定、可复现的端到端测试被测系统。赞分享测试【免费下载链接】protractorE2E test framework for Angular apps项目地址https://gitcode.com/gh_mirrors/pr/protractor点击查看免费下载相关推荐微信QQ防撤回补丁教程4步装好补丁让对方撤回无效微信QQ防撤回补丁教程4步装好补丁让对方撤回无效 晚上十一点四十客户在群里发来发票金额没错按这个走几秒后这条消息变成一行灰字。第二天早上你追问时桌面应用即时通讯STF 测试指南基于 Karma 与 Protractor 的前端单元测试和端到端测试实战STF 测试指南基于 Karma 与 Protractor 的前端单元测试和端到端测试实战 本文以 Smartphone Test FarmSTF仓库的测试后端前端json.lua 错误处理完全指南如何精准定位 JSON 解析问题json.lua 错误处理完全指南如何精准定位 JSON 解析问题 JSON 解析是应用开发中常见的任务但错误处理往往被忽视。本文将深入探讨 Lua 轻量级序列化上一篇ComfyUI Florence2模型加载深度解析与实战指南下一篇Haystack 与 MongoDB Atlas 集成实战MongoDBAtlasDocumentStore 与双检索器Embedding / Full-Text完全指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表
PREV
查看更多资讯
NEXT
返回资讯列表