如何用Protractor检查加载性能?Angular搜索补全性能断言排查
解决Angular搜索框性能测试的两个核心问题
咱们先搞定你遇到的超时断言不生效的坑,再聊聊如何用Protractor做加载性能检查。
一、为什么你的超时断言没起作用?
你提到设置waitForAngularEnabled(false)后,哪怕把超时设为0测试仍通过,核心原因是:禁用Angular自动等待后,你没有显式等待搜索结果元素出现,也没正确绑定计时逻辑。如果只是简单调用元素的isDisplayed(),它会直接返回false但不会触发超时;或者测试时搜索结果可能来自缓存,根本没触发真实API请求。
正确的实现方式
下面是调整后的代码示例,核心是用browser.wait()强制等待元素出现,并在计时后断言耗时:
home.po.ts(页面对象)
import { ElementFinder, element, by, browser } from 'protractor'; export class HomePage { private searchInput: ElementFinder = element(by.css('input#search-input')); private searchResultList: ElementFinder = element(by.css('.search-results-container')); async searchAndMeasureTime(query: string): Promise<number> { // 禁用Angular自动等待(因为搜索依赖第三方API,不需要等Angular稳定) await browser.waitForAngularEnabled(false); // 记录搜索开始时间戳 const startTime = Date.now(); // 输入搜索关键词 await this.searchInput.clear(); await this.searchInput.sendKeys(query); // 强制等待结果出现,超时时间设为1000ms(1秒) try { await browser.wait( () => this.searchResultList.isDisplayed(), 1000, `搜索结果未在1秒内加载完成` ); } catch (timeoutErr) { // 捕获超时错误,同时计算实际耗时 const elapsedTime = Date.now() - startTime; throw new Error(`搜索超时!实际耗时${elapsedTime}ms`); } // 计算总耗时 const elapsedTime = Date.now() - startTime; // 恢复Angular自动等待(避免影响后续测试) await browser.waitForAngularEnabled(true); return elapsedTime; } }
home.e2e-spec.ts(测试用例)
import { HomePage } from './home.po'; describe('搜索框性能测试', () => { let homePage: HomePage; beforeEach(() => { homePage = new HomePage(); browser.get('/'); // 清除缓存和Cookie,确保每次测试都是全新请求 browser.driver.manage().deleteAllCookies(); }); it('搜索结果展示耗时不应超过1秒', async () => { const elapsedTime = await homePage.searchAndMeasureTime('测试关键词'); expect(elapsedTime).toBeLessThanOrEqual(1000); }); });
关键注意事项
- 显式等待是核心:
browser.wait()会轮询判断元素是否显示,超时后直接抛出错误,这才是触发超时断言的关键。 - 清除缓存:每次测试前删除Cookie和缓存,避免用本地缓存结果干扰性能数据。
- 恢复Angular等待:测试结束后记得开启
waitForAngularEnabled(true),防止影响其他依赖Angular的测试用例。
二、用Protractor检查加载性能的几种方法
除了测量搜索结果的展示耗时,你还可以从以下几个维度做性能检查:
1. 测量API请求耗时
通过Chrome DevTools Protocol(CDP)监听网络请求,精准获取搜索API的响应时间:
it('搜索API请求耗时不应超过800ms', async () => { // 启用网络日志监听 await browser.driver.sendCommand('Network.enable', {}); let apiRequestTime = 0; // 监听请求完成事件,匹配你的搜索API地址 browser.driver.on('Network.responseReceived', (params) => { if (params.response.url.includes('/api/search')) { const timing = params.response.timing; // 计算请求从发送到接收响应的耗时 apiRequestTime = timing.responseEnd - timing.requestStart; } }); // 执行搜索操作 await homePage.searchAndMeasureTime('测试关键词'); // 断言API耗时 expect(apiRequestTime).toBeLessThanOrEqual(800); // 关闭网络监听 await browser.driver.sendCommand('Network.disable', {}); });
2. 页面整体加载性能检查
利用浏览器的performance.timing API,获取页面从导航到完全加载的耗时:
it('页面整体加载耗时不应超过3秒', async () => { await browser.get('/'); const timingData = await browser.executeScript(() => { return window.performance.timing; }); // 计算页面从开始导航到加载完成的总时间 const totalLoadTime = timingData.loadEventEnd - timingData.navigationStart; expect(totalLoadTime).toBeLessThanOrEqual(3000); });
3. 渲染性能检查
如果需要关注搜索结果的渲染耗时,可以结合requestAnimationFrame测量DOM渲染完成时间:
it('搜索结果渲染耗时不应超过200ms', async () => { await browser.waitForAngularEnabled(false); await homePage.searchInput.sendKeys('测试关键词'); const renderTime = await browser.executeScript(() => { const startTime = performance.now(); return new Promise(resolve => { // 等待下一帧渲染完成 requestAnimationFrame(() => { const endTime = performance.now(); resolve(endTime - startTime); }); }); }); expect(renderTime).toBeLessThanOrEqual(200); await browser.waitForAngularEnabled(true); });
内容的提问来源于stack exchange,提问作者Gabriel Araujo
相关产品推荐
相关产品推荐

