Commit 93e5410e authored by liguangyu06's avatar liguangyu06
Browse files

Publish Allure reports and email a read-only report viewer account instead of...

Publish Allure reports and email a read-only report viewer account instead of the Jenkins build URL.
parent 26a5d4e4
...@@ -43,3 +43,6 @@ playwright.agent.config.ts ...@@ -43,3 +43,6 @@ playwright.agent.config.ts
# 扫描快照与知识库截图:生成定位器用,运行用例不依赖 # 扫描快照与知识库截图:生成定位器用,运行用例不依赖
data/scan/ data/scan/
knowledge-base/ knowledge-base/
# Jenkins 插件包不入库,内网 update center 不可达时由本地安装
tools/*.hpi
...@@ -18,8 +18,8 @@ def sendReportEmail() { ...@@ -18,8 +18,8 @@ def sendReportEmail() {
? readFile(encoding: 'UTF-8', file: 'reports/latest/email-summary.html') ? readFile(encoding: 'UTF-8', file: 'reports/latest/email-summary.html')
: """<p>构建 ${currentBuild.currentResult},未生成详细摘要。</p> : """<p>构建 ${currentBuild.currentResult},未生成详细摘要。</p>
<p>测试范围:${params.SUITE}</p> <p>测试范围:${params.SUITE}</p>
<p>Playwright 报告:<a href='${env.BUILD_URL}Playwright_20Report/'>${env.BUILD_URL}Playwright_20Report/</a></p> <p>Playwright 报告:<a href='${env.BUILD_URL}Playwright_20Report/'>打开 Playwright 报告</a></p>
<p>Jenkins 构建:<a href='${env.BUILD_URL}'>${env.BUILD_URL}</a></p>""" <p>Allure 报告:<a href='${env.BUILD_URL}allure'>打开 Allure 报告</a></p>"""
if (cc) { if (cc) {
to = [to, cc].findAll { it }.join(',') to = [to, cc].findAll { it }.join(',')
} }
...@@ -102,6 +102,7 @@ pipeline { ...@@ -102,6 +102,7 @@ pipeline {
RUN_FULL = "${params.RUN_FULL ? '1' : '0'}" RUN_FULL = "${params.RUN_FULL ? '1' : '0'}"
PLAYWRIGHT_BROWSERS_PATH = "${WORKSPACE}/.playwright-browsers" PLAYWRIGHT_BROWSERS_PATH = "${WORKSPACE}/.playwright-browsers"
SPD_CREDENTIALS_ID = "${env.SPD_CREDENTIALS_ID ?: 'spd-ui-test-account'}" SPD_CREDENTIALS_ID = "${env.SPD_CREDENTIALS_ID ?: 'spd-ui-test-account'}"
JAVA_HOME = "${env.JAVA_HOME ?: 'E:/Program Files/Java/jdk-11'}"
} }
stages { stages {
...@@ -218,20 +219,27 @@ pipeline { ...@@ -218,20 +219,27 @@ pipeline {
echo "跳过 HTML 报告:${err}" echo "跳过 HTML 报告:${err}"
} }
try { try {
if (fileExists('reports/latest/allure-report/index.html')) { if (fileExists('reports/latest/allure-results')) {
publishHTML([ allure includeProperties: false, jdk: '', results: [[path: 'reports/latest/allure-results']]
allowMissing: true,
alwaysLinkToLastBuild: true,
keepAll: true,
reportDir: 'reports/latest/allure-report',
reportFiles: 'index.html',
reportName: 'Allure Report'
])
} else { } else {
echo '未生成 Allure HTML(节点未装 Java/Allure 插件),以 Playwright 报告为准。' echo '无 allure-results,跳过 Allure 插件报告。'
}
} catch (Throwable err) {
echo "Allure 插件不可用,回退 HTML:${err}"
try {
if (fileExists('reports/latest/allure-report/index.html')) {
publishHTML([
allowMissing: true,
alwaysLinkToLastBuild: true,
keepAll: true,
reportDir: 'reports/latest/allure-report',
reportFiles: 'index.html',
reportName: 'Allure Report'
])
}
} catch (Throwable ignored) {
echo "跳过 Allure HTML:${ignored}"
} }
} catch (err) {
echo "跳过 Allure:${err}"
} }
try { try {
withEnv(["BUILD_RESULT=${currentBuild.currentResult}"]) { withEnv(["BUILD_RESULT=${currentBuild.currentResult}"]) {
......
...@@ -92,7 +92,7 @@ git --version ...@@ -92,7 +92,7 @@ git --version
## 第五步:把测试报告用邮件发给同事 ## 第五步:把测试报告用邮件发给同事
流水线跑完会自动发信,不用再加「构建后操作」。 流水线跑完会自动发信,不用再加「构建后操作」。
邮件里是:**测试范围、执行用例数、成功/失败、通过率、Playwright 报告链接**,以及失败用例列表;并带上附件 `email-summary.html` 邮件里是:**测试范围、执行用例数、成功/失败、通过率、Playwright/Allure 报告链接、报告只读账号**,以及失败用例列表。不附 Jenkins 构建页地址
完整截图/Trace 请同事点邮件里的链接打开(整包报告太大,邮箱会拒收,所以不当附件)。 完整截图/Trace 请同事点邮件里的链接打开(整包报告太大,邮箱会拒收,所以不当附件)。
### 5.1 确认插件 ### 5.1 确认插件
......
...@@ -141,7 +141,8 @@ Default user e-mail suffix: @公司域名 ...@@ -141,7 +141,8 @@ Default user e-mail suffix: @公司域名
- 测试范围(套件说明) - 测试范围(套件说明)
- 执行用例数、成功、失败、通过率 - 执行用例数、成功、失败、通过率
- 失败用例前 30 条 - 失败用例前 30 条
- 链接:Playwright 报告、Jenkins 构建、Allure(装了插件才有效) - 链接:Playwright 报告、Allure 报告(不附 Jenkins 构建页)
- 报告只读账号(邮件内写明,仅能打开 SPD 报告)
点 Playwright 报告即可看截图和 trace。若公司 Jenkins 需登录,请给领导开只读权限,或把 Jenkins 配在内网 SSO 后发信。 点 Playwright 报告即可看截图和 trace。若公司 Jenkins 需登录,请给领导开只读权限,或把 Jenkins 配在内网 SSO 后发信。
......
...@@ -121,24 +121,35 @@ function main() { ...@@ -121,24 +121,35 @@ function main() {
const failed = parseFailedTests(path.join(LATEST, 'junit.xml')); const failed = parseFailedTests(path.join(LATEST, 'junit.xml'));
const moreFail = failTotal > failed.length ? failTotal - failed.length : 0; const moreFail = failTotal > failed.length ? failTotal - failed.length : 0;
const pwReportUrl = buildUrl ? `${buildUrl}Playwright_20Report/` : ''; const pwReportUrl = buildUrl ? `${buildUrl}Playwright_20Report/` : '';
const jenkinsUrl = buildUrl;
const allureUrl = buildUrl ? `${buildUrl}allure` : ''; const allureUrl = buildUrl ? `${buildUrl}allure` : '';
const viewUser = process.env.REPORT_VIEW_USER || '';
const viewPass = process.env.REPORT_VIEW_PASSWORD || '';
const metric = (title, value, color) => `<td style="padding:10px 8px;text-align:center;width:25%;"> const metric = (title, value, color) => `<td style="padding:10px 8px;text-align:center;width:25%;">
<div style="font-size:12px;color:#6b7280;">${title}</div> <div style="font-size:12px;color:#6b7280;">${title}</div>
<div style="font-size:26px;font-weight:700;color:${color};margin-top:4px;line-height:1.2;">${value}</div> <div style="font-size:26px;font-weight:700;color:${color};margin-top:4px;line-height:1.2;">${value}</div>
</td>`; </td>`;
const accountBox = viewUser
? `<div style="margin:0 0 14px;padding:12px 14px;background:#fffbeb;border:1px solid #f59e0b;border-radius:8px;font-size:13px;line-height:1.7;">
<div style="font-weight:700;color:#92400e;margin-bottom:4px;">查看报告请用只读账号登录</div>
<div>账号:<strong>${escapeHtml(viewUser)}</strong></div>
<div>密码:<strong>${escapeHtml(viewPass)}</strong></div>
<div style="color:#92400e;">此账号只能查看 SPD 测试报告,不能执行构建或修改配置。</div>
</div>`
: '';
const reportButtons = buildUrl const reportButtons = buildUrl
? `<p style="margin:0 0 10px;"> ? `${accountBox}
<a href="${escapeHtml(pwReportUrl)}" style="display:inline-block;padding:10px 16px;background:#047857;color:#fff;text-decoration:none;border-radius:6px;font-weight:600;">打开 Playwright 测试报告</a> <p style="margin:0 0 10px;">
<a href="${escapeHtml(pwReportUrl)}" style="display:inline-block;padding:10px 16px;background:#047857;color:#fff;text-decoration:none;border-radius:6px;font-weight:600;margin-right:8px;">打开 Playwright 报告</a>
<a href="${escapeHtml(allureUrl)}" style="display:inline-block;padding:10px 16px;background:#1d4ed8;color:#fff;text-decoration:none;border-radius:6px;font-weight:600;">打开 Allure 报告</a>
</p> </p>
<p style="margin:0;font-size:13px;line-height:1.8;"> <p style="margin:0;font-size:13px;line-height:1.8;">
Playwright 报告:<a href="${escapeHtml(pwReportUrl)}">${escapeHtml(pwReportUrl)}</a><br> Playwright 报告:<a href="${escapeHtml(pwReportUrl)}">${escapeHtml(pwReportUrl)}</a><br>
Jenkins 构建:<a href="${escapeHtml(jenkinsUrl)}">${escapeHtml(jenkinsUrl)}</a><br> Allure 报告:<a href="${escapeHtml(allureUrl)}">${escapeHtml(allureUrl)}</a>
Allure 报告:<a href="${escapeHtml(allureUrl)}">${escapeHtml(allureUrl)}</a>(未装插件时可能打不开)
</p>` </p>`
: `<p style="margin:0;font-size:13px;">本地报告:reports/latest/playwright-report/index.html</p>`; : `${accountBox}<p style="margin:0;font-size:13px;">本地报告:reports/latest/playwright-report/index.html</p>`;
const failRows = failed.length const failRows = failed.length
? failed ? failed
...@@ -201,8 +212,10 @@ function main() { ...@@ -201,8 +212,10 @@ function main() {
`通过率: ${passRate}`, `通过率: ${passRate}`,
skipped ? `跳过: ${skipped}` : '', skipped ? `跳过: ${skipped}` : '',
`耗时: ${duration}`, `耗时: ${duration}`,
viewUser ? `报告只读账号: ${viewUser}` : '',
viewPass ? `报告只读密码: ${viewPass}` : '',
pwReportUrl ? `Playwright 报告: ${pwReportUrl}` : '', pwReportUrl ? `Playwright 报告: ${pwReportUrl}` : '',
jenkinsUrl ? `Jenkins 构建: ${jenkinsUrl}` : '', allureUrl ? `Allure 报告: ${allureUrl}` : '',
'', '',
] ]
.filter(Boolean) .filter(Boolean)
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment