React项目Cypress E2E测试在Github Actions超时失败求助
问题:Github Actions中Cypress E2E测试无法找到添加的任务内容
- 本地所有Cypress E2E测试均可正常通过
- 在Github Actions中执行时全部失败,报错为
AssertionError: Timed out retrying after ...ms: Expected to find content: 'Do the laundry' but never did.,疑似测试无法验证添加的数据
测试运行结果
Add task 1) Should add a task 0 passing (22s) 1 failing 1) Add task Should add a task: AssertionError: Timed out retrying after 20000ms: Expected to find content: 'Do the laundry' but never did. at Context.eval (webpack:///./cypress/e2e/addTask.cy.ts:7:36) (Results) ┌────────────────────────────────────────────────────────────────────────────────────────────────┐ │ Tests: 1 │ │ Passing: 0 │ │ Failing: 1 │ │ Pending: 0 │ │ Skipped: 0 │ │ Screenshots: 1 │ │ Video: true │ │ Duration: 22 seconds │ │ Spec Ran: addTask.cy.ts │ └────────────────────────────────────────────────────────────────────────────────────────────────┘
相关代码
测试用例(addTask.cy.ts)
describe("Add task", () => { it("Should add a task", () => { cy.visit("/"); cy.fixture("taskList").then((taskList) =>{ cy.get("[data-cy='add-task']").type(taskList[0].task); cy.get("[data-cy='submit']").click(); cy.contains(taskList[0].task).should("exist"); }) }); });
测试数据(taskList.json)
[ { "task": "Do the laundry" }, { "task": "Call Mark" }, { "task": "Do the dinner" }, { "task": "Do the lunch" }, { "task": "Buy cinema tickets" }, { "task": "Go to the supermarket" } ]
Cypress配置(cypress.config.ts)
import { defineConfig } from "cypress"; export default defineConfig({ e2e: { baseUrl: "http://localhost:3000", defaultCommandTimeout: 20000, setupNodeEvents(on, config) { // implement node event listeners here }, }, });
Github Actions配置
name: CI on: push jobs: cypress-run: runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v3 - name: Setup Node.js uses: actions/setup-node@v3 with: node-version: 18 - name: Install dependencies run: npm install working-directory: ./front-end - name: Cypress run uses: cypress-io/github-action@v5 with: working-directory: ./front-end build: npm run build start: npm start wait-on: http://127.0.0.1:3000 wait-on-timeout: 180 browser: chrome
已尝试的方案
- 在
cypress.config.ts中设置defaultCommandTimeout为20000ms - 在测试命令中添加
{ timeout: 20000 }配置 - 优化Github Actions的YAML配置,增加等待时间和指定浏览器
可行解决方案
1. 确保应用在CI中完全就绪
wait-on仅检查端口开放状态,无法保证应用完成初始化。可以:
- 在Action的
cypress-run步骤前添加额外等待:- name: Wait for app to fully load run: sleep 10 working-directory: ./front-end - 或者修改
wait-on命令,结合应用的健康检查端点(如果有):wait-on: http://127.0.0.1:3000/health
2. 优化测试断言逻辑
任务提交后可能存在异步DOM更新,不要直接断言内容,先等待交互完成:
describe("Add task", () => { it("Should add a task", () => { cy.visit("/"); cy.fixture("taskList").then((taskList) =>{ const taskText = taskList[0].task; cy.get("[data-cy='add-task']").type(taskText); // 等待提交按钮可点击,避免过早触发 cy.get("[data-cy='submit']").should("be.enabled").click(); // 用更精准的选择器定位任务项 cy.get("[data-cy='task-item']").contains(taskText).should("exist"); }) }); });
注:需要给任务列表项添加data-cy="task-item"属性,提升选择器可靠性
3. 排查CI环境的数据存储问题
如果任务依赖localStorage或内存存储,CI环境可能有不同配置:
- 在测试前重置应用状态:
beforeEach(() => { cy.visit("/"); cy.clearLocalStorage(); cy.reload(); }); - 确认Cypress在CI中未禁用本地存储,检查
cypress.config.ts是否有相关限制。
4. 调整Chrome浏览器配置
Ubuntu环境下运行Chrome需启用无头模式,修改Action配置:
- name: Cypress run uses: cypress-io/github-action@v5 with: working-directory: ./front-end build: npm run build start: npm start wait-on: http://127.0.0.1:3000 wait-on-timeout: 180 browser: chrome browser-options: --headless=new --disable-gpu --no-sandbox
5. 利用CI生成的截图/视频排查
Github Actions会保存Cypress的截图和视频,在Artifacts中下载查看,可直观确认任务是否真的未被添加到页面。
内容的提问来源于stack exchange,提问作者Sabevi
相关产品推荐
相关产品推荐

