GitHub Actions中Cypress登录限制测试未按预期失效排查
问题概述
使用GitHub Actions构建CI流程,拆分两个Cypress spec测试登录限制:
- 第一个spec执行多次登录尝试,预期触发10分钟的登录拦截限制
- 第二个spec验证拦截是否生效
本地无头模式测试正常,但GitHub Actions中始终无法触发拦截,仅显示正常登录提示,怀疑与IP有关。
现有配置问题
首先看你的Jobs配置,存在一个明显错误:
第一个Job中的Wait for 10 minutes步骤实际执行的是sleep 3,仅等待3秒,远未达到10分钟的限制时间要求,这会导致第二个Job运行时,要么限制还未生效,要么逻辑上不符合测试预期(如果是要在限制有效期内验证拦截,反而不需要等待10分钟)。
核心原因分析
1. GitHub Actions Runner IP动态性
GitHub托管的Runner每次运行Job时,会分配不同的公网IP。如果你的登录限制是基于IP地址触发的,那么:
- 第一个Job用IP A触发了限制
- 第二个Job用IP B执行验证,IP B不在限制列表中,自然不会触发拦截
这是最可能导致问题的原因,本地测试时IP固定,所以能正常触发限制。
2. 等待时间配置错误
如前所述,sleep 3完全不符合10分钟等待的需求,若你的测试逻辑是“触发限制后,在限制有效期内验证拦截”,则不需要等待10分钟;若逻辑是“等待限制过期后验证恢复”,则需要改为sleep 600(10分钟=600秒)。
解决方案
方案一:合并两个测试到同一个Job
将两个spec放在同一个Job中执行,确保全程使用同一个Runner IP,避免IP不一致的问题:
login_test_combined: name: Login Cypress run - Combined runs-on: ubuntu-22.04 steps: - name: Checkout uses: actions/checkout@v4 - name: Run login limit trigger and validation tests uses: cypress-io/github-action@v6 with: record: true parallel: false group: "Login Limit Test" spec: "cypress/e2e/loginTentativa_1.cy.js,cypress/e2e/loginTentativa_2.cy.js" env: CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
如果需要在两个spec之间等待一段时间(比如触发限制后等待几秒再验证),可以在第一个spec的末尾添加Cypress内置的cy.wait(),或者在测试脚本中处理等待逻辑,无需依赖Job级别的sleep。
方案二:固定Runner IP(适合自托管Runner)
如果必须拆分两个Job,可以使用自托管Runner,确保两个Job都在同一个固定IP的Runner上执行。但GitHub托管Runner无法固定IP,此方案仅适用于自行部署的Runner。
方案三:调整测试逻辑(基于用户账号而非IP)
如果你的登录限制逻辑支持基于用户账号锁定,可以修改测试用例,确保两次测试使用同一个账号,即使IP不同也能触发拦截。这需要后端限制逻辑配合调整。
调试建议
- 在每个Job中添加IP打印步骤,确认两个Job的IP是否不同:
- name: Print current IP run: curl ifconfig.me - 在Cypress测试中添加请求日志,查看服务器返回的响应内容,确认是否真的触发了限制:
cy.intercept('POST', '/login').as('loginRequest'); cy.get('form').submit(); cy.wait('@loginRequest').then((interception) => { console.log('Login response:', interception.response.body); }); - 统一Cypress的User-Agent,避免服务器因UA不同识别为不同客户端:
在cypress.config.js中添加:module.exports = defineConfig({ e2e: { setupNodeEvents(on, config) { on('before:browser:launch', (browser = {}, launchOptions) => { launchOptions.args.push('--user-agent="Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36"'); return launchOptions; }); }, }, });
内容的提问来源于stack exchange,提问作者Luiz Henrique

