UI覆盖率高级解决方案
结果API
@cypress/extract-cloud-results
模块提供了getUICoverageResults
工具,用于在CI环境中以编程方式获取运行时的UI覆盖率结果。这使您能在合并代码变更前确定测试覆盖率是否满足要求。
支持的CI提供商
该工具支持以下CI提供商。设置详情请参考链接指南:
- Azure (需要Cypress v13.13.1)
- CircleCI
- GitHub Actions
- GitLab
- Jenkins
对于其他CI提供商,请联系Cypress支持团队申请支持。
安装
在CI的安装步骤中安装@cypress/extract-cloud-results
模块。
npm install --force https://cdn.cypress.io/extract-cloud-results/v1/extract-cloud-results.tgz
caution
不要将此模块作为依赖项签入。我们建议您在常规模块安装之外单独安装它。使用--force
获取最新版本。
如果将其作为依赖项签入,当我们更新包时您的安装会失败。
使用
1. 获取UI覆盖率结果
编写脚本获取UI覆盖率结果并断言测试覆盖率标准。该脚本将在CI中执行。
scripts/verifyUICoverageResults.js
const { getUICoverageResults } = require('@cypress/extract-cloud-results')
getUICoverageResults({
projectId: process.env.CYPRESS_PROJECT_ID, // 可选,如果从环境变量设置
recordKey: process.env.CYPRESS_RECORD_KEY, // 可选,如果从环境变量设置
runTags: [process.env.RUN_TAGS], // 如果记录多个运行则必需
}).then((results) => {
const { runNumber, uiCoverageReportUrl, summary, views } = results
console.log(
`收到${summary.isPartialReport ? '部分' : ''}运行#${runNumber}的结果。`
)
console.log(`完整报告见${uiCoverageReportUrl}。`)
// 验证总体覆盖率
if (summary.coverage < 80) {
throw new Error(
`项目覆盖率为${summary.coverage},低于80%的最低阈值。`
)
}
const criticalViews = [/login/, /checkout/]
// 验证关键视图覆盖率
views.forEach((view) => {
const { displayName, coverage, uiCoverageReportUrl } = view
if (
criticalViews.some((pattern) => pattern.test(displayName)) &&
coverage < 95
) {
throw new Error(
`关键视图"${displayName}"覆盖率为${coverage}%,低于要求的95%。查看:${uiCoverageReportUrl}`
)
}
})
console.log('UI覆盖率高于最低阈值。')
})
getUICoverageResults
参数
getUICoverageResults
接受以下参数:
getUICoverageResults({
// Cypress项目ID。
// 如果设置了CYPRESS_PROJECT_ID环境变量则为可选
projectId: string
// 项目的记录密钥。
// 如果设置了CYPRESS_RECORD_KEY环境变量则为可选
recordKey: string
// 与运行关联的运行标签。
// 如果从单个CI构建记录多个Cypress运行则为必需。
// 传递每个运行时使用的运行标签
runTags: string[]
})
结果详情
getUICoverageResults
工具返回以下数据:
{
// 识别构建的运行编号。
runNumber: number
// 识别构建的运行URL。
runUrl: 'https://cloud.cypress.io/projects/:project_id/runs/:run_number'
// 识别构建的状态。
runStatus: 'passed' | 'failed' | 'errored' | 'timedOut' | 'cancelled' | 'noTests'
// 链接到识别构建的UI覆盖率报告的URL。
uiCoverageReportUrl: 'https://cloud.cypress.io/[...]'
summary: {
// 指示是否生成了完整的UI覆盖率报告。
// 例如,如果运行被取消且报告预期运行20个规范,但只运行了10个,这将导致部分报告。
isPartialReport: boolean
// 报告覆盖率,0-100,精度为2位小数(如92.45)。
coverage: number
// 测试和分析的视图数量。
viewCount: number
// 测试的交互元素数量。
testedElementsCount:number
// 未测试的交互元素数量。
untestedElementsCount: number
}
// 测试视图列表及每个页面的覆盖率。
views: [{
// 报告中显示的清理后的URL模式。
displayName: string
// 视图覆盖率,0-100,精度为2位小数(如92.45)。
coverage: number
// 此视图上测试的交互元素数量。
testedElementsCount:number
// 此视图上未测试的交互元素数量。
untestedElementsCount: number
// 链接到此视图报告的URL。
uiCoverageReportUrl: 'https://cloud.cypress.io/[...]'
}]
}
2. 添加到CI工作流
在运行Cypress测试的CI工作流中:
- 更新安装作业以安装
@cypress/extract-cloud-results
模块。 - 向
getUICoverageResults
传递必要的参数。 - 向运行Cypress测试的作业添加新步骤以验证UI覆盖率结果。
info
如果在单个CI构建中记录多个运行,必须使用--tag
参数记录这些运行,然后为每个运行使用runTags
参数调用getUICoverageResults
。
这对于识别每个唯一运行并返回相应的结果集是必要的。标签是识别每个运行的方式。
示例
- 假设在单个CI构建中多次调用
cypress run --record
,因为您正在针对staging
环境运行一组测试,然后是production
环境。 - 在此场景中,您向每个cypress运行传递不同的
--tag
cypress run --record --tag staging
cypress run --record --tag production
- 调用
getUICoverageResults
时,您将传递这些相同的标签以获取每个运行的唯一结果集getUICoverageResults({ runTags: ['staging']})
getUICoverageResults({ runTags: ['production']})
示例作业工作流更新:
- GitHub Actions
- GitLab
- Jenkins
- Azure
- CircleCI
test_cypress.yaml
name: 我的工作流
on: push
env:
CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }}
jobs:
run-cypress:
runs-on: ubuntu-24.04
steps:
- name: 检出
uses: actions/checkout@v4
- name: 安装
run: npm install
- name: 运行
run: npx cypress run --record
+ - name: 验证UI覆盖率结果
+ run: |
+ npm install --force https://cdn.cypress.io/extract-cloud-results/v1/extract-cloud-results.tgz
+ node ./scripts/verifyUICoverageResults.js
.git-ci.yml
name: 运行Cypress测试
image: node:latest
stages:
- test
run-cypress:
stage: test
secrets:
CYPRESS_RECORD_KEY:
vault: vault/cypressRecordKey
script:
- npm install
- npx cypress run --record
+ - npm install --force https://cdn.cypress.io/extract-cloud-results/v1/extract-cloud-results.tgz
+ - node ./scripts/verifyUICoverageResults.js
pipeline {
agent {
docker {
image 'cypress/base:22.15.0'
}
}
environment {
CYPRESS_PROJECT_ID: 'xxxx'
CYPRESS_RECORD_KEY = credentials('cypress-record-key')
}
stages {
stage('构建和测试') {
steps {
sh 'npm ci'
sh 'npx cypress run --record'
}
}
+ stage('验证UI覆盖率结果') {
+ steps {
+ sh 'npm install --force https://cdn.cypress.io/extract-cloud-results/v1/extract-cloud-results.tgz'
+ sh 'node ./scripts/verifyUICoverageResults.js'
+ }
+ }
}
}
jobs:
- job: 运行测试
pool:
vmImage: 'ubuntu-latest'
steps:
- task: NodeTool@0
inputs:
versionSpec: '20.x'
displayName: '安装Node.js'
- script: npm i
displayName: '安装npm依赖'
- script: npx cypress run --record
displayName: '运行Cypress测试'
env:
# 避免终端警告
TERM: xterm
CYPRESS_RECORD_KEY: $(CYPRESS_RECORD_KEY)
+ - script: |
+ npm install --force https://cdn.cypress.io/extract-cloud-results/v1/extract-cloud-results.tgz
+ node ./scripts/verifyUICoverageResults.js
+ displayName: '验证UI覆盖率结果'
+ env:
+ CYPRESS_PROJECT_ID: $(CYPRESS_PROJECT_ID)
+ CYPRESS_RECORD_KEY: $(CYPRESS_RECORD_KEY)
version: 2.1
jobs:
linux-test:
docker:
- image: cypress/base:22.15.0
working_directory: ~/repo
steps:
- checkout
- run: npm install
- run: npx run cypress:run --record
+ - run: npm install --force https://cdn.cypress.io/extract-cloud-results/beta/v1/extract-cloud-results.tgz
+ - run: node ./scripts/verifyUICoverageResults.js
workflows:
version: 2
tests:
jobs:
- run-cypress