You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用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);
  });
});

关键注意事项

  1. 显式等待是核心:browser.wait()会轮询判断元素是否显示,超时后直接抛出错误,这才是触发超时断言的关键。
  2. 清除缓存:每次测试前删除Cookie和缓存,避免用本地缓存结果干扰性能数据。
  3. 恢复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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 07:09:44