增加 后端,后台管理系统,uniapp会员端的自动化测试。
This commit is contained in:
Vendored
+152
-259
@@ -1,310 +1,203 @@
|
||||
pipeline {
|
||||
agent any
|
||||
|
||||
|
||||
parameters {
|
||||
choice(
|
||||
name: 'TEST_SCOPE',
|
||||
choices: ['smoke', 'full', 'all', 'miniapp'],
|
||||
description: '测试范围: smoke=仅冒烟测试, full=完整E2E, all=所有测试含性能, miniapp=仅小程序'
|
||||
)
|
||||
choice(
|
||||
name: 'BROWSER',
|
||||
choices: ['chromium', 'all'],
|
||||
description: '目标浏览器: chromium=单浏览器快速, all=全浏览器'
|
||||
)
|
||||
string(
|
||||
name: 'BASE_URL',
|
||||
defaultValue: 'http://localhost:3002',
|
||||
description: '测试目标URL'
|
||||
)
|
||||
}
|
||||
|
||||
environment {
|
||||
// 项目配置
|
||||
PROJECT_NAME = 'gym-manage-system'
|
||||
FRONTEND_DIR = 'gym-manage-web'
|
||||
BACKEND_DIR = 'gym-manage-api'
|
||||
|
||||
// Node.js 配置
|
||||
NODE_VERSION = '20'
|
||||
PNPM_VERSION = '8.15.0'
|
||||
|
||||
// Java 配置
|
||||
JAVA_VERSION = '17'
|
||||
MAVEN_VERSION = '3.9.0'
|
||||
|
||||
// Docker 配置
|
||||
DOCKER_REGISTRY = credentials('docker-registry')
|
||||
DOCKER_IMAGE_FRONTEND = "${PROJECT_NAME}-frontend"
|
||||
DOCKER_IMAGE_BACKEND = "${PROJECT_NAME}-backend"
|
||||
|
||||
// 数据库配置(用于E2E测试)
|
||||
DB_HOST = 'localhost'
|
||||
DB_PORT = '5432'
|
||||
DB_NAME = 'gym_test'
|
||||
DB_USER = credentials('db-user')
|
||||
DB_PASSWORD = credentials('db-password')
|
||||
|
||||
// 测试配置
|
||||
TEST_TIMEOUT = '30'
|
||||
RETRY_COUNT = '2'
|
||||
PLAYWRIGHT_HEADLESS = 'true'
|
||||
CI = 'true'
|
||||
NODE_ENV = 'test'
|
||||
JEST_JUNIT_OUTPUT_DIR = 'test-results'
|
||||
JEST_JUNIT_OUTPUT_NAME = 'junit.xml'
|
||||
}
|
||||
|
||||
tools {
|
||||
nodejs "NodeJS-${NODE_VERSION}"
|
||||
maven "Maven-${MAVEN_VERSION}"
|
||||
jdk "JDK-${JAVA_VERSION}"
|
||||
}
|
||||
|
||||
|
||||
stages {
|
||||
|
||||
stage('环境准备') {
|
||||
parallel {
|
||||
stage('安装Web端依赖') {
|
||||
steps {
|
||||
dir('gym-manage-web') {
|
||||
bat 'npm ci'
|
||||
bat 'npx playwright install chromium --with-deps'
|
||||
}
|
||||
}
|
||||
}
|
||||
stage('安装小程序端依赖') {
|
||||
steps {
|
||||
dir('gym-manage-uniapp') {
|
||||
bat 'npm ci'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
stage('启动后端服务') {
|
||||
steps {
|
||||
echo '🔧 准备构建环境...'
|
||||
sh '''
|
||||
# 安装 pnpm
|
||||
npm install -g pnpm@${PNPM_VERSION}
|
||||
|
||||
# 验证工具版本
|
||||
node --version
|
||||
pnpm --version
|
||||
java -version
|
||||
mvn --version
|
||||
'''
|
||||
}
|
||||
}
|
||||
|
||||
stage('代码检查') {
|
||||
parallel {
|
||||
stage('前端代码检查') {
|
||||
steps {
|
||||
dir(FRONTEND_DIR) {
|
||||
echo '🔍 执行前端代码检查...'
|
||||
sh '''
|
||||
pnpm install
|
||||
pnpm run lint
|
||||
pnpm run type-check
|
||||
'''
|
||||
}
|
||||
}
|
||||
dir('gym-manage-api') {
|
||||
bat 'mvn spring-boot:run -pl manage-app -DskipTests &'
|
||||
bat 'mvn spring-boot:run -pl manage-gateway -DskipTests &'
|
||||
}
|
||||
|
||||
stage('后端代码检查') {
|
||||
steps {
|
||||
dir(BACKEND_DIR) {
|
||||
echo '🔍 执行后端代码检查...'
|
||||
sh 'mvn clean compile -DskipTests'
|
||||
// 等待后端健康检查
|
||||
script {
|
||||
retry(10) {
|
||||
sleep(10)
|
||||
try {
|
||||
def response = httpRequest 'http://localhost:8084/actuator/health'
|
||||
print "后端健康状态: ${response.content}"
|
||||
} catch (err) {
|
||||
error "后端尚未就绪: ${err.message}"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
stage('单元测试') {
|
||||
parallel {
|
||||
stage('前端单元测试') {
|
||||
steps {
|
||||
dir(FRONTEND_DIR) {
|
||||
echo '🧪 执行前端单元测试...'
|
||||
sh 'pnpm run test:unit'
|
||||
}
|
||||
}
|
||||
post {
|
||||
always {
|
||||
dir(FRONTEND_DIR) {
|
||||
// 发布测试报告
|
||||
publishHTML(target: [
|
||||
allowMissing: false,
|
||||
alwaysLinkToLastBuild: true,
|
||||
keepAll: true,
|
||||
reportDir: 'coverage',
|
||||
reportFiles: 'index.html',
|
||||
reportName: '前端单元测试覆盖率报告'
|
||||
])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
stage('后端单元测试') {
|
||||
steps {
|
||||
dir(BACKEND_DIR) {
|
||||
echo '🧪 执行后端单元测试...'
|
||||
sh 'mvn test'
|
||||
}
|
||||
}
|
||||
post {
|
||||
always {
|
||||
dir(BACKEND_DIR) {
|
||||
// 发布测试报告
|
||||
junit '**/target/surefire-reports/*.xml'
|
||||
|
||||
// 发布代码覆盖率报告
|
||||
publishHTML(target: [
|
||||
allowMissing: false,
|
||||
alwaysLinkToLastBuild: true,
|
||||
keepAll: true,
|
||||
reportDir: 'target/site/jacoco',
|
||||
reportFiles: 'index.html',
|
||||
reportName: '后端单元测试覆盖率报告'
|
||||
])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
stage('构建') {
|
||||
parallel {
|
||||
stage('前端构建') {
|
||||
steps {
|
||||
dir(FRONTEND_DIR) {
|
||||
echo '📦 构建前端项目...'
|
||||
sh '''
|
||||
pnpm run build:prod
|
||||
|
||||
# 创建构建产物归档
|
||||
tar -czf frontend-dist.tar.gz dist/
|
||||
'''
|
||||
}
|
||||
}
|
||||
post {
|
||||
success {
|
||||
archiveArtifacts artifacts: "${FRONTEND_DIR}/frontend-dist.tar.gz", fingerprint: true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
stage('后端构建') {
|
||||
steps {
|
||||
dir(BACKEND_DIR) {
|
||||
echo '📦 构建后端项目...'
|
||||
sh '''
|
||||
mvn clean package -DskipTests
|
||||
|
||||
# 创建构建产物归档
|
||||
tar -czf backend-jars.tar.gz */target/*.jar
|
||||
'''
|
||||
}
|
||||
}
|
||||
post {
|
||||
success {
|
||||
archiveArtifacts artifacts: "${BACKEND_DIR}/backend-jars.tar.gz", fingerprint: true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
stage('E2E测试') {
|
||||
|
||||
stage('冒烟测试') {
|
||||
steps {
|
||||
echo '🎭 执行E2E测试...'
|
||||
dir(FRONTEND_DIR) {
|
||||
sh '''
|
||||
# 安装Playwright浏览器
|
||||
pnpm exec playwright install --with-deps chromium
|
||||
|
||||
# 执行E2E测试
|
||||
pnpm run test:e2e:journeys
|
||||
'''
|
||||
dir('gym-manage-web') {
|
||||
bat 'npm run test:e2e:smoke'
|
||||
}
|
||||
}
|
||||
post {
|
||||
always {
|
||||
dir(FRONTEND_DIR) {
|
||||
// 发布E2E测试报告
|
||||
publishHTML(target: [
|
||||
allowMissing: false,
|
||||
alwaysLinkToLastBuild: true,
|
||||
keepAll: true,
|
||||
reportDir: 'test-results',
|
||||
reportFiles: 'custom-report.html',
|
||||
reportName: 'E2E测试报告'
|
||||
])
|
||||
|
||||
// 归档测试失败截图和视频
|
||||
archiveArtifacts artifacts: 'test-results/**/*.png, test-results/**/*.webm', allowEmptyArchive: true
|
||||
failure {
|
||||
echo '冒烟测试失败,跳过后续测试'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
stage('Web E2E 测试') {
|
||||
when {
|
||||
expression { params.TEST_SCOPE != 'smoke' }
|
||||
}
|
||||
steps {
|
||||
dir('gym-manage-web') {
|
||||
script {
|
||||
def projectFilter = params.TEST_SCOPE == 'all'
|
||||
? ''
|
||||
: '--project=root --project=journeys'
|
||||
bat "npx playwright test ${projectFilter}"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
stage('构建Docker镜像') {
|
||||
|
||||
stage('性能测试') {
|
||||
when {
|
||||
branch 'develop'
|
||||
expression { params.TEST_SCOPE == 'all' }
|
||||
}
|
||||
steps {
|
||||
echo '🐳 构建Docker镜像...'
|
||||
|
||||
// 构建前端镜像
|
||||
dir(FRONTEND_DIR) {
|
||||
sh """
|
||||
docker build -t ${DOCKER_REGISTRY}/${DOCKER_IMAGE_FRONTEND}:${BUILD_NUMBER} .
|
||||
docker tag ${DOCKER_REGISTRY}/${DOCKER_IMAGE_FRONTEND}:${BUILD_NUMBER} ${DOCKER_REGISTRY}/${DOCKER_IMAGE_FRONTEND}:latest
|
||||
"""
|
||||
}
|
||||
|
||||
// 构建后端镜像
|
||||
dir(BACKEND_DIR) {
|
||||
sh """
|
||||
docker build -t ${DOCKER_REGISTRY}/${DOCKER_IMAGE_BACKEND}:${BUILD_NUMBER} .
|
||||
docker tag ${DOCKER_REGISTRY}/${DOCKER_IMAGE_BACKEND}:${BUILD_NUMBER} ${DOCKER_REGISTRY}/${DOCKER_IMAGE_BACKEND}:latest
|
||||
"""
|
||||
dir('gym-manage-web') {
|
||||
bat 'npm run test:e2e:perf'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
stage('推送Docker镜像') {
|
||||
|
||||
stage('角色边界测试') {
|
||||
when {
|
||||
branch 'develop'
|
||||
expression { params.TEST_SCOPE == 'all' }
|
||||
}
|
||||
steps {
|
||||
echo '📤 推送Docker镜像到仓库...'
|
||||
sh """
|
||||
docker push ${DOCKER_REGISTRY}/${DOCKER_IMAGE_FRONTEND}:${BUILD_NUMBER}
|
||||
docker push ${DOCKER_REGISTRY}/${DOCKER_IMAGE_FRONTEND}:latest
|
||||
docker push ${DOCKER_REGISTRY}/${DOCKER_IMAGE_BACKEND}:${BUILD_NUMBER}
|
||||
docker push ${DOCKER_REGISTRY}/${DOCKER_IMAGE_BACKEND}:latest
|
||||
"""
|
||||
dir('gym-manage-web') {
|
||||
bat 'npx playwright test --grep "权限|角色|边界|boundary"'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
stage('部署到测试环境') {
|
||||
|
||||
stage('小程序编译') {
|
||||
when {
|
||||
branch 'develop'
|
||||
anyOf {
|
||||
expression { params.TEST_SCOPE == 'all' }
|
||||
expression { params.TEST_SCOPE == 'miniapp' }
|
||||
}
|
||||
}
|
||||
steps {
|
||||
echo '🚀 部署到测试环境...'
|
||||
sh """
|
||||
# 这里可以添加部署脚本
|
||||
# 例如:使用docker-compose或kubernetes部署
|
||||
|
||||
echo "部署前端镜像: ${DOCKER_REGISTRY}/${DOCKER_IMAGE_FRONTEND}:${BUILD_NUMBER}"
|
||||
echo "部署后端镜像: ${DOCKER_REGISTRY}/${DOCKER_IMAGE_BACKEND}:${BUILD_NUMBER}"
|
||||
"""
|
||||
dir('gym-manage-uniapp') {
|
||||
bat 'npm run build:mp-weixin'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
stage('部署到生产环境') {
|
||||
|
||||
stage('小程序 E2E 测试') {
|
||||
when {
|
||||
branch 'main'
|
||||
anyOf {
|
||||
expression { params.TEST_SCOPE == 'all' }
|
||||
expression { params.TEST_SCOPE == 'miniapp' }
|
||||
}
|
||||
}
|
||||
environment {
|
||||
WECHAT_DEVTOOLS_CLI = 'D:\\微信web开发者工具\\cli.bat'
|
||||
}
|
||||
steps {
|
||||
echo '🚀 部署到生产环境...'
|
||||
input message: '确认部署到生产环境?', ok: '确认部署'
|
||||
|
||||
sh """
|
||||
# 这里可以添加生产环境部署脚本
|
||||
# 例如:使用kubernetes进行滚动更新
|
||||
|
||||
echo "部署前端镜像: ${DOCKER_REGISTRY}/${DOCKER_IMAGE_FRONTEND}:${BUILD_NUMBER}"
|
||||
echo "部署后端镜像: ${DOCKER_REGISTRY}/${DOCKER_IMAGE_BACKEND}:${BUILD_NUMBER}"
|
||||
"""
|
||||
dir('gym-manage-uniapp') {
|
||||
script {
|
||||
try {
|
||||
// 使用一键脚本:自动启动 IDE → 运行测试 → 关闭 IDE
|
||||
bat 'node e2e/run-tests.js --close --verbose'
|
||||
} catch (err) {
|
||||
echo "小程序 E2E 测试失败:${err.message}"
|
||||
// 失败也继续(IDE 可能不可用)
|
||||
unstable('小程序 E2E 测试未通过')
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
post {
|
||||
always {
|
||||
echo '🧹 清理工作空间...'
|
||||
cleanWs()
|
||||
// 归档测试报告
|
||||
dir('gym-manage-web') {
|
||||
archiveArtifacts artifacts: 'test-results/**/*', allowEmptyArchive: true
|
||||
archiveArtifacts artifacts: 'playwright-report/**', allowEmptyArchive: true
|
||||
junit 'test-results/junit.xml'
|
||||
}
|
||||
// 归档小程序测试报告
|
||||
dir('gym-manage-uniapp') {
|
||||
archiveArtifacts artifacts: 'test-results/**/*', allowEmptyArchive: true
|
||||
}
|
||||
}
|
||||
|
||||
success {
|
||||
echo '✅ 流水线执行成功!'
|
||||
// 可以添加通知,例如发送邮件或Slack消息
|
||||
}
|
||||
|
||||
failure {
|
||||
echo '❌ 流水线执行失败!'
|
||||
// 可以添加失败通知
|
||||
// 失败通知
|
||||
script {
|
||||
def failedTests = currentBuild.rawBuild.getLog(50)
|
||||
emailext(
|
||||
subject: "[测试失败] ${env.JOB_NAME} - Build #${env.BUILD_NUMBER}",
|
||||
body: """
|
||||
<h2>UI 自动化测试失败</h2>
|
||||
<p><b>Job:</b> ${env.JOB_NAME}</p>
|
||||
<p><b>Build:</b> #${env.BUILD_NUMBER}</p>
|
||||
<p><b>分支:</b> ${env.BRANCH_NAME}</p>
|
||||
<p><b>日志:</b> <a href="${env.BUILD_URL}">${env.BUILD_URL}</a></p>
|
||||
<h3>最后 50 行日志:</h3>
|
||||
<pre>${failedTests}</pre>
|
||||
""",
|
||||
mimeType: 'text/html',
|
||||
to: 'dev-team@gym-manage.com'
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
unstable {
|
||||
echo '⚠️ 流水线执行不稳定!'
|
||||
// 可以添加不稳定状态通知
|
||||
success {
|
||||
echo "全部 UI 测试通过!"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user