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

Angular端到端(E2E)测试新手求助:首次编写测试需指导

嘿,作为刚接触Angular和E2E测试的新手,第一次写测试确实会有点无从下手,我结合你给出的组件代码,给你梳理一套实用的E2E测试方案,帮你快速上手~

针对你的Listing组件的E2E测试指导

首先,核心思路要明确:E2E测试是模拟真实用户的操作流程,验证组件在不同场景下的行为是否符合预期。结合你的组件(包含异步数据加载、搜索过滤、选中状态、加载/空状态),我们可以覆盖以下关键测试场景:

第一步:给HTML添加测试友好的标识

为了让测试更稳定(避免因为CSS类或文本变化导致测试失败),建议给关键元素加上data-testid属性,修改后的代码片段如下:

<md-list>
  <div *ngIf="items | async as items; else loading">
    <ng-container *ngIf="items.length; else noItems">
      <div class="item-row" 
           *ngFor="let item of items | search:'LoanNumber,Borrower_LastName,Borrower_FirstName':searchTerm" 
           [class.selected]="selectedItemId === item.ORDER_ID"
           data-testid="item-row"
           [attr.data-order-id]="item.ORDER_ID"
           >
        <list-item [item]="item" data-testid="list-item"></list-item>
      </div>
    </ng-container>
    <ng-template #noItems>
      <p data-testid="no-items-message">没有找到任何项目</p>
    </ng-template>
  </div>
  <ng-template #loading>
    <md-spinner data-testid="loading-indicator"></md-spinner>
  </ng-template>
</md-list>
<!-- 假设你的搜索输入框结构如下,同样加上测试标识 -->
<input type="text" [(ngModel)]="searchTerm" data-testid="search-input" placeholder="搜索贷款号或借款人">

第二步:编写Cypress测试用例(Angular CLI默认推荐)

现在Angular主流的E2E工具是Cypress,下面是针对你的组件的完整测试代码,每个用例对应一个真实场景:

describe('Listing Component E2E Tests', () => {
  beforeEach(() => {
    // 访问组件所在的页面,替换成你的实际路由
    cy.visit('/listings');
  });

  // 测试加载状态流程
  it('显示加载指示器直到异步数据加载完成', () => {
    // 初始状态验证加载指示器可见
    cy.get('[data-testid="loading-indicator"]').should('be.visible');
    
    // 拦截后端API请求,模拟返回测试数据(替换成你的实际API地址)
    cy.intercept('GET', '/api/items', {
      delay: 1000, // 模拟网络延迟,更贴近真实场景
      body: [
        { ORDER_ID: 1, LoanNumber: 'LN-123', Borrower_LastName: 'Smith', Borrower_FirstName: 'John' },
        { ORDER_ID: 2, LoanNumber: 'LN-456', Borrower_LastName: 'Doe', Borrower_FirstName: 'Jane' }
      ]
    }).as('getItems');

    // 等待请求完成,验证加载指示器消失,列表项正确渲染
    cy.wait('@getItems');
    cy.get('[data-testid="loading-indicator"]').should('not.exist');
    cy.get('[data-testid="item-row"]').should('have.length', 2);
  });

  // 测试无数据场景
  it('当没有数据时显示空状态提示', () => {
    // 拦截API返回空数组
    cy.intercept('GET', '/api/items', []).as('getEmptyItems');
    cy.wait('@getEmptyItems');
    
    // 验证空状态提示可见,列表项不存在
    cy.get('[data-testid="no-items-message"]').should('be.visible').and('contain', '没有找到任何项目');
    cy.get('[data-testid="item-row"]').should('not.exist');
  });

  // 测试搜索过滤功能
  it('搜索关键词能正确过滤列表项', () => {
    // 加载测试数据
    cy.intercept('GET', '/api/items', [
      { ORDER_ID: 1, LoanNumber: 'LN-123', Borrower_LastName: 'Smith', Borrower_FirstName: 'John' },
      { ORDER_ID: 2, LoanNumber: 'LN-456', Borrower_LastName: 'Doe', Borrower_FirstName: 'Jane' }
    ]).as('getItems');
    cy.wait('@getItems');

    // 搜索"John",验证只有匹配的项显示
    cy.get('[data-testid="search-input"]').type('John');
    cy.get('[data-testid="item-row"]').should('have.length', 1);
    cy.get('[data-testid="item-row"][data-order-id="1"]').should('be.visible');

    // 搜索"LN-456",验证只有对应的项显示
    cy.get('[data-testid="search-input"]').clear().type('LN-456');
    cy.get('[data-testid="item-row"]').should('have.length', 1);
    cy.get('[data-testid="item-row"][data-order-id="2"]').should('be.visible');

    // 搜索不存在的关键词,验证显示空状态
    cy.get('[data-testid="search-input"]').clear().type('NonExistent');
    cy.get('[data-testid="no-items-message"]').should('be.visible');
  });

  // 测试选中状态
  it('点击列表项后会添加选中样式', () => {
    // 加载单条测试数据
    cy.intercept('GET', '/api/items', [
      { ORDER_ID: 1, LoanNumber: 'LN-123', Borrower_LastName: 'Smith', Borrower_FirstName: 'John' }
    ]).as('getItems');
    cy.wait('@getItems');

    // 点击列表项,验证selected类被添加
    const itemRow = cy.get('[data-testid="item-row"]');
    itemRow.click();
    itemRow.should('have.class', 'selected');
  });
});

新手必备小贴士

  • 定位元素的最佳实践:尽量用data-testid而不是CSS类或文本内容,因为前者不会因为UI样式或文案修改而失效
  • 模拟真实场景:测试时要模拟用户的真实操作流程(比如先加载页面,再输入搜索词,再点击),不要直接操作组件内部变量
  • 运行测试:确保Angular应用处于运行状态,或者用ng e2e命令自动启动应用并运行测试
  • 如果用Protractor:思路和上面一致,只是语法不同,比如用element(by.css('[data-testid="search-input"]')).sendKeys('John');来模拟输入

内容的提问来源于stack exchange,提问作者yugaanks

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 12:33:25