Files
everything-is-suitable/everything-is-suitable-test/docs/plans/2026-03-07-test-suite-improvement.md
T
张翔 08ea5fbe98 feat(admin): 添加用户管理相关文件
添加用户管理视图、API和状态管理文件
2026-03-28 14:37:29 +08:00

30 KiB
Raw Blame History

测试套件改进计划

For Claude: REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.

Goal: 将测试套件从当前77.8%覆盖率提升到金融级90%-95%标准,建立完整的测试金字塔,实现全生命周期质量保障

Architecture: 采用分层测试策略,优先补充高优先级覆盖率缺口,建立稳定可执行的测试基础设施,逐步引入性能、安全和集成测试

Tech Stack: Python (pytest, coverage), Playwright (TypeScript), Spring Boot (Java), Maven, Docker, CI/CD


改进阶段划分

阶段1: 高优先级修复(1-2周)- 覆盖率提升至85%+

阶段2: 中期优化(1-2个月)- 建立完整测试金字塔

阶段3: 长期建设(3-6个月)- 达到金融级合规标准


阶段1: 高优先级修复(1-2周)

Task 1: 补充main.py测试

Files:

  • Create: api/tests/unit/test_main.py
  • Test: api/tests/unit/test_main.py

Step 1: 分析main.py功能

Read: api/src/apitest/main.py

Expected: 识别CLI入口点、参数解析、主流程

Step 2: Write failing tests

# api/tests/unit/test_main.py
import pytest
from unittest.mock import patch, MagicMock
from apitest.main import main
import sys

def test_main_with_no_arguments():
    """测试无参数时显示帮助信息"""
    with patch('sys.argv', ['main']):
        with patch('builtins.print') as mock_print:
            main()
            # 验证调用了print
            assert mock_print.called

def test_main_with_valid_command():
    """测试有效命令执行"""
    with patch('sys.argv', ['main', 'run', '--config', 'test.yaml']):
        with patch('apitest.main.TestEngine') as mock_engine:
            with patch('apitest.main.load_config') as mock_config:
                mock_config.return_value = {'test': 'config'}
                main()
                # 验证创建了TestEngine
                assert mock_engine.called

def test_main_with_invalid_command():
    """测试无效命令处理"""
    with patch('sys.argv', ['main', 'invalid']):
        with pytest.raises(SystemExit):
            main()

def test_main_with_config_file_not_found():
    """测试配置文件不存在"""
    with patch('sys.argv', ['main', 'run', '--config', 'nonexistent.yaml']):
        with patch('builtins.open', side_effect=FileNotFoundError):
            with pytest.raises(SystemExit):
                main()

Step 3: Run test to verify it fails

Run: cd api && python -m pytest tests/unit/test_main.py -v

Expected: FAIL with "module 'apitest.main' not found" or import errors

Step 4: Implement minimal main.py structure

Read: api/src/apitest/main.py

If file is minimal, add basic structure:

# api/src/apitest/main.py
import sys
from apitest.cli_module import CLICommand

def main():
    """主入口函数"""
    if len(sys.argv) < 2:
        print("Usage: python -m apitest.main <command> [options]")
        print("Commands: run, test, report")
        sys.exit(1)
    
    command = sys.argv[1]
    cli = CLICommand()
    
    if command == 'run':
        cli.run_tests()
    elif command == 'test':
        cli.run_specific_test()
    elif command == 'report':
        cli.generate_report()
    else:
        print(f"Unknown command: {command}")
        sys.exit(1)

if __name__ == '__main__':
    main()

Step 5: Run test to verify it passes

Run: cd api && python -m pytest tests/unit/test_main.py -v

Expected: PASS

Step 6: Commit

git add api/tests/unit/test_main.py api/src/apitest/main.py
git commit -m "test: add main.py unit tests and basic CLI structure"

Task 2: 提升cli_module.py覆盖率到80%+

Files:

  • Modify: api/tests/unit/test_cli.py
  • Test: api/tests/unit/test_cli.py

Step 1: 分析未覆盖代码行

Run: cd api && python -m pytest tests/unit/test_cli.py --cov=src/apitest/cli_module --cov-report=term-missing

Expected: 识别未覆盖的代码行(52, 61-93, 96-100, 131, 134-136, 158, 160, 162, 164, 167-170, 196-198, 223

Step 2: Write tests for missing branches

# api/tests/unit/test_cli.py - 补充测试
def test_cli_run_with_invalid_config():
    """测试无效配置文件"""
    cli = CLICommand()
    with pytest.raises(Exception):
        cli.run_tests(config='invalid.yaml')

def test_cli_run_with_missing_test_cases():
    """测试缺少测试用例"""
    cli = CLICommand()
    with patch('os.path.exists', return_value=False):
        with pytest.raises(FileNotFoundError):
            cli.run_tests()

def test_cli_report_generation():
    """测试报告生成功能"""
    cli = CLICommand()
    with patch('apitest.cli_module.ReportManager') as mock_report:
        cli.generate_report()
        assert mock_report.generate.called

def test_cli_error_handling():
    """测试错误处理逻辑"""
    cli = CLICommand()
    with patch.object(cli, 'run_tests', side_effect=Exception("Test error")):
        with pytest.raises(Exception):
            cli.run_tests()

Step 3: Run test to verify coverage improvement

Run: cd api && python -m pytest tests/unit/test_cli.py --cov=src/apitest/cli_module --cov-report=term-missing

Expected: Coverage increases from 72.6% to 80%+

Step 4: Commit

git add api/tests/unit/test_cli.py
git commit -m "test: improve cli_module.py coverage to 80%+"

Task 3: 修复API服务启动问题

Files:

  • Modify: everything-is-suitable-api/everything-is-suitable-app/src/main/resources/application.yml
  • Modify: everything-is-suitable-api/everything-is-suitable-app/pom.xml
  • Test: Manual verification

Step 1: 分析bean冲突原因

Run: cd everything-is-suitable-api && mvn dependency:tree | grep jacksonConfig

Expected: 识别哪个模块定义了jacksonConfig bean

Step 2: 检查Spring Boot配置

Read: everything-is-suitable-api/everything-is-suitable-app/src/main/resources/application.yml

Look for bean configuration and component scanning

Step 3: 解决bean名称冲突

Option A: 重命名冲突的bean

// everything-is-suitable-api/everything-is-suitable-base/src/main/java/.../JacksonConfig.java
@Configuration
public class BaseJacksonConfig {  // 重命名
    // configuration
}

Option B: 使用@Primary注解

@Configuration
@Primary
public class AppJacksonConfig {  // 标记为首选
    // configuration
}

Step 4: 验证服务启动

Run: cd everything-is-suitable-api/everything-is-suitable-app && mvn spring-boot:run -Dspring-boot.run.profiles=dev

Expected: Service starts successfully on port 8080

Step 5: Commit

git add everything-is-suitable-api/
git commit -m "fix: resolve jacksonConfig bean name conflict"

Task 4: 修复E2E测试模块引用问题

Files:

  • Modify: e2e/examples/admin-role-management.spec.ts
  • Modify: e2e/examples/admin-user-management.spec.ts
  • Test: e2e/integration/login-mock.spec.ts

Step 1: 分析fixtures路径错误

Read: e2e/examples/admin-role-management.spec.ts:1

Expected: import { test, expect } from './fixtures/test-fixtures';

Step 2: 修复import路径

// e2e/examples/admin-role-management.spec.ts
// 修改为正确的相对路径
import { test, expect } from '../fixtures/test-fixtures';

Step 3: 验证所有测试文件

Run: cd e2e && grep -r "from './fixtures/test-fixtures'" examples/

Expected: 找到所有需要修复的文件

Step 4: 批量修复

Run: cd e2e && find examples/ -name "*.spec.ts" -exec sed -i '' "s|from './fixtures/test-fixtures'|from '../fixtures/test-fixtures'|g" {} \;

Step 5: 验证测试可执行

Run: cd e2e && ADMIN_BASE_URL=http://localhost:5173 npx playwright test examples/ --list

Expected: No module import errors

Step 6: Commit

git add e2e/examples/
git commit -m "fix: correct fixtures import paths in example tests"

Task 5: 建立测试环境管理脚本

Files:

  • Create: scripts/start-test-env.sh
  • Create: scripts/stop-test-env.sh
  • Create: scripts/check-services.sh

Step 1: 创建服务启动脚本

# scripts/start-test-env.sh
#!/bin/bash
set -e

echo "========================================="
echo "  启动测试环境"
echo "========================================"

# 检查端口占用
check_port() {
    local port=$1
    if lsof -Pi :$port -sTCP:LISTEN -t >/dev/null 2>&1; then
        echo "端口 $port 已被占用"
        return 1
    fi
    return 0
}

# 启动API服务
echo "----------------------------------------"
echo "  启动 API 服务..."
echo "----------------------------------------"
if check_port 8080; then
    echo "API服务已在运行"
else
    cd everything-is-suitable-api/everything-is-suitable-app
    nohup mvn spring-boot:run -Dspring-boot.run.profiles=dev > /tmp/api.log 2>&1 &
    echo "API服务启动中..."
    sleep 30
fi

# 启动Admin服务
echo "----------------------------------------"
echo "  启动 Admin 服务..."
echo "----------------------------------------"
if check_port 5173; then
    echo "Admin服务已在运行"
else
    cd everything-is-suitable-admin
    nohup npm run dev > /tmp/admin.log 2>&1 &
    echo "Admin服务启动中..."
    sleep 10
fi

# 验证服务健康
echo "----------------------------------------"
echo "  验证服务健康..."
echo "----------------------------------------"
bash scripts/check-services.sh

echo "========================================="
echo "  ✅ 所有服务启动成功!"
echo "========================================="

Step 2: 创建服务停止脚本

# scripts/stop-test-env.sh
#!/bin/bash
set -e

echo "========================================="
echo "  停止测试环境"
echo "========================================"

# 停止API服务
echo "停止 API 服务..."
pkill -f "everything-is-suitable-app"
echo "API服务已停止"

# 停止Admin服务
echo "停止 Admin 服务..."
pkill -f "vite.*5173"
echo "Admin服务已停止"

echo "========================================="
echo "  ✅ 所有服务已停止"
echo "========================================="

Step 3: 创建服务检查脚本

# scripts/check-services.sh
#!/bin/bash
set -e

echo "========================================="
echo "  服务状态检查"
echo "========================================="

# 检查API服务
echo "API 服务:"
if curl -s http://localhost:8080/api/health > /dev/null 2>&1; then
    echo "  ✅ 运行中 (http://localhost:8080/api/health)"
else
    echo "  ❌ 未运行"
fi

# 检查Admin服务
echo "Admin 服务:"
if curl -s http://localhost:5173 > /dev/null 2>&1; then
    echo "  ✅ 运行中 (http://localhost:5173)"
else
    echo "  ❌ 未运行"
fi

echo "========================================="

Step 4: 添加执行权限

Run: chmod +x scripts/start-test-env.sh scripts/stop-test-env.sh scripts/check-services.sh

Step 5: 测试脚本

Run: bash scripts/check-services.sh

Expected: 显示服务状态

Step 6: Commit

git add scripts/
git commit -m "feat: add test environment management scripts"

阶段2: 中期优化(1-2个月)

Task 6: 增加集成测试覆盖

Files:

  • Create: api/tests/integration/
  • Create: api/tests/integration/test_api_integration.py

Step 1: 设计集成测试场景

# api/tests/integration/test_api_integration.py
import pytest
import requests
from apitest.client.api_client import APIClient
from apitest.client.auth_manager import AuthManager

@pytest.fixture(scope="module")
def api_client():
    """API客户端fixture"""
    return APIClient("http://localhost:8080")

@pytest.fixture(scope="module")
def auth_manager():
    """认证管理器fixture"""
    return AuthManager(
        "http://localhost:8080",
        {"username": "admin", "password": "admin123"},
        None
    )

def test_api_integration_full_workflow(api_client, auth_manager):
    """测试完整API集成工作流"""
    # 1. 登录
    login_result = auth_manager.login()
    assert login_result["data"]["token"]
    
    # 2. 使用token访问受保护资源
    api_client.set_auth_token(auth_manager._token)
    result = api_client.get("/sys/user/list")
    assert result["status_code"] == 200
    
    # 3. 登出
    auth_manager.logout()
    assert auth_manager._token is None

Step 2: 创建集成测试配置

# api/tests/integration/conftest.py
import pytest

def pytest_configure(config):
    """集成测试配置"""
    config.addinivalue_marker(
        "integration",
        "标记为集成测试,需要真实服务"
    )

Step 3: 运行集成测试

Run: cd api && python -m pytest tests/integration/ -v -m integration

Expected: PASS (需要服务运行)

Step 4: Commit

git add api/tests/integration/
git commit -m "test: add API integration tests"

Task 7: 补充E2E业务流程测试

Files:

  • Create: e2e/integration/user-workflow.spec.ts
  • Create: e2e/integration/role-workflow.spec.ts

Step 1: 设计用户管理工作流测试

// e2e/integration/user-workflow.spec.ts
import { test, expect } from '@playwright/test';

const BASE_URL = process.env.ADMIN_BASE_URL || 'http://localhost:5173';

test.describe('用户管理工作流E2E测试', () => {
  
  test('完整用户生命周期', async ({ page }) => {
    await page.goto(`${BASE_URL}/login`);
    
    // 登录
    await page.fill('[data-testid="username-input"]', 'admin');
    await page.fill('[data-testid="password-input"]', 'admin123');
    await page.click('[data-testid="login-button"]');
    await expect(page).toHaveURL(/.*\//);
    
    // 创建用户
    await page.goto(`${BASE_URL}/system/user`);
    await page.click('button:has-text("新增")');
    await page.fill('[data-testid="username-input"]', 'testuser');
    await page.fill('[data-testid="email-input"]', 'test@example.com');
    await page.click('button:has-text("保存")');
    await expect(page.locator('text=保存成功')).toBeVisible();
    
    // 编辑用户
    await page.click('td:has-text("testuser") button:has-text("编辑")');
    await page.fill('[data-testid="email-input"]', 'updated@example.com');
    await page.click('button:has-text("保存")');
    await expect(page.locator('text=保存成功')).toBeVisible();
    
    // 删除用户
    await page.click('td:has-text("testuser") button:has-text("删除")');
    await page.click('button:has-text("确认")');
    await expect(page.locator('text=删除成功')).toBeVisible();
  });
});

Step 2: 运行工作流测试

Run: cd e2e && ADMIN_BASE_URL=http://localhost:5173 npx playwright test integration/user-workflow.spec.ts --headed

Expected: PASS (需要完整服务)

Step 3: Commit

git add e2e/integration/
git commit -m "test: add user and role workflow E2E tests"

Task 8: 建立测试数据管理

Files:

  • Create: api/tests/factories/test_data_factory.py
  • Modify: api/tests/conftest.py

Step 1: 创建测试数据工厂

# api/tests/factories/test_data_factory.py
from faker import Faker

fake = Faker('zh_CN')

class TestDataFactory:
    """测试数据工厂"""
    
    @staticmethod
    def create_user():
        """创建测试用户数据"""
        return {
            "username": fake.user_name(),
            "email": fake.email(),
            "phone": fake.phone_number(),
            "password": fake.password(length=12),
        }
    
    @staticmethod
    def create_role():
        """创建测试角色数据"""
        return {
            "roleName": fake.job(),
            "description": fake.sentence(),
            "permissions": ["user:read", "user:write"],
        }
    
    @staticmethod
    def create_menu():
        """创建测试菜单数据"""
        return {
            "menuName": fake.word(),
            "menuType": "directory",
            "path": f"/{fake.word()}",
            "icon": fake.word(),
        }

Step 2: 集成到conftest

# api/tests/conftest.py
import pytest
from tests.factories.test_data_factory import TestDataFactory

@pytest.fixture
def test_user():
    """测试用户数据fixture"""
    return TestDataFactory.create_user()

@pytest.fixture
def test_role():
    """测试角色数据fixture"""
    return TestDataFactory.create_role()

Step 3: 使用测试数据工厂

# 在测试中使用
def test_create_user_with_factory(test_user):
    """使用工厂创建测试用户"""
    result = api_client.post("/sys/user", body=test_user)
    assert result["status_code"] == 201

Step 4: Commit

git add api/tests/factories/
git commit -m "feat: add test data factory for better test maintainability"

阶段3: 长期建设(3-6个月)

Task 9: 引入性能测试

Files:

  • Create: performance/load-test.jmx
  • Create: performance/run-load-test.sh

Step 1: 创建JMeter负载测试计划

<?xml version="1.0" encoding="UTF-8"?>
<jmeterTestPlan version="1.2">
  <hashTree>
    <TestPlan guiclass="TestPlan" testclass="TestPlan" testname="API Load Test">
      <elementProp name="TestPlan.user_define_classpath" elementType="TestPlan" 
                 guiclass="TestPlan" testclass="TestPlan" testname="TestPlan.user_define_classpath">
        <stringProp name="TestPlan.user_define_classpath" value=""/>
      </elementProp>
      
      <hashTree>
        <ThreadGroup guiclass="ThreadGroup" testclass="ThreadGroup" 
                    testname="Thread Group" sampler="LoopController">
          <stringProp name="ThreadGroup.num_threads" value="100"/>
          <stringProp name="ThreadGroup.ramp_time" value="10"/>
          <stringProp name="ThreadGroup.duration" value="60"/>
          
          <HTTPSamplerProxy guiclass="HTTPSamplerProxy" testclass="HTTPSamplerProxy" 
                        testname="Login Request">
            <stringProp name="HTTPSampler.domain" value="localhost"/>
            <stringProp name="HTTPSampler.port" value="8080"/>
            <stringProp name="HTTPSampler.path" value="/api/sys/auth/login"/>
            <stringProp name="HTTPSampler.method" value="POST"/>
            <elementProp name="HTTPsampler.Arguments" elementType="HTTPArguments">
              <collectionProp name="HTTPsampler.Arguments.arguments">
                <elementProp name="HTTPArgument" elementType="HTTPArgument">
                  <stringProp name="Argument.name" value="username"/>
                  <stringProp name="Argument.value" value="admin"/>
                </elementProp>
                <elementProp name="HTTPArgument" elementType="HTTPArgument">
                  <stringProp name="Argument.name" value="password"/>
                  <stringProp name="Argument.value" value="admin123"/>
                </elementProp>
              </collectionProp>
            </elementProp>
          </HTTPSamplerProxy>
        </ThreadGroup>
      </hashTree>
    </hashTree>
  </hashTree>
</jmeterTestPlan>

Step 2: 创建性能测试执行脚本

# performance/run-load-test.sh
#!/bin/bash
set -e

echo "========================================="
echo "  运行负载测试"
echo "========================================="

# 检查JMeter安装
if ! command -v jmeter &> /dev/null; then
    echo "JMeter未安装,请先安装JMeter"
    exit 1
fi

# 运行负载测试
jmeter -n -t performance/load-test.jmx \
    -l performance/results.jtl \
    -e -o performance/report \
    -Jusers=100 \
    -Jrampup=10 \
    -Jduration=60

echo "========================================="
echo "  负载测试完成"
echo "========================================="
echo "报告位置: performance/report/index.html"

Step 3: Commit

git add performance/
git commit -m "feat: add performance testing with JMeter"

Task 10: 添加安全测试

Files:

  • Create: security/security-test.py
  • Create: security/run-security-scan.sh

Step 1: 创建安全测试脚本

# security/security-test.py
import requests
import pytest

class TestSecurity:
    """安全测试套件"""
    
    BASE_URL = "http://localhost:8080"
    
    def test_sql_injection_protection(self):
        """测试SQL注入防护"""
        malicious_payloads = [
            "' OR '1'='1",
            "admin'--",
            "' UNION SELECT * FROM users--",
        ]
        
        for payload in malicious_payloads:
            response = requests.post(
                f"{self.BASE_URL}/api/sys/auth/login",
                json={"username": payload, "password": "test"}
            )
            # 应该返回401或400,而不是500
            assert response.status_code in [400, 401]
    
    def test_xss_protection(self):
        """测试XSS防护"""
        xss_payloads = [
            "<script>alert('xss')</script>",
            "<img src=x onerror=alert('xss')>",
            "javascript:alert('xss')",
        ]
        
        for payload in xss_payloads:
            response = requests.post(
                f"{self.BASE_URL}/api/sys/user",
                json={"username": payload}
            )
            # 应该过滤或转义
            assert response.status_code in [400, 403]
    
    def test_authentication_bypass(self):
        """测试认证绕过"""
        # 测试无token访问
        response = requests.get(f"{self.BASE_URL}/api/sys/user/list")
        assert response.status_code == 401
        
        # 测试过期token
        response = requests.get(
            f"{self.BASE_URL}/api/sys/user/list",
            headers={"Authorization": "Bearer expired_token"}
        )
        assert response.status_code == 401
    
    def test_sensitive_data_exposure(self):
        """测试敏感数据暴露"""
        # 测试错误响应不应包含敏感信息
        response = requests.post(
            f"{self.BASE_URL}/api/sys/auth/login",
            json={"username": "wrong", "password": "wrong"}
        )
        assert response.status_code == 401
        # 验证不暴露数据库错误、堆栈信息等
        assert "database" not in response.text.lower()
        assert "stack" not in response.text.lower()

Step 2: 创建安全扫描脚本

# security/run-security-scan.sh
#!/bin/bash
set -e

echo "========================================="
echo "  运行安全扫描"
echo "========================================="

# 检查OWASP ZAP安装
if ! command -v zap-cli &> /dev/null; then
    echo "OWASP ZAP未安装,请先安装ZAP"
    exit 1
fi

# 运行ZAP扫描
zap-cli quick-scan \
    -t http://localhost:5173 \
    -r security/zap-report.html \
    -x

echo "========================================="
echo "  安全扫描完成"
echo "========================================="
echo "报告位置: security/zap-report.html"

Step 3: Commit

git add security/
git commit -m "feat: add security testing suite"

Task 11: 实施AI辅助测试

Files:

  • Create: ai/test-generator.py
  • Create: ai/defect-predictor.py

Step 1: 创建测试用例生成器

# ai/test-generator.py
import openai
from typing import List, Dict

class TestGenerator:
    """AI辅助测试用例生成器"""
    
    def __init__(self, api_key: str):
        self.client = openai.OpenAI(api_key=api_key)
    
    def generate_test_cases(self, function_code: str) -> List[Dict]:
        """基于函数代码生成测试用例"""
        prompt = f"""
        基于以下函数代码,生成全面的测试用例:
        
        {function_code}
        
        要求:
        1. 生成正常路径测试
        2. 生成边界条件测试
        3. 生成异常情况测试
        4. 每个测试用例包含:测试名称、输入、预期输出
        
        返回JSON格式的测试用例列表。
        """
        
        response = self.client.chat.completions.create(
            model="gpt-4",
            messages=[{"role": "user", "content": prompt}],
            temperature=0.7
        )
        
        content = response.choices[0].message.content
        return eval(content)  # 简化,实际应使用JSON解析
    
    def generate_test_code(self, test_case: Dict) -> str:
        """生成测试代码"""
        prompt = f"""
        基于以下测试用例,生成pytest测试代码:
        
        测试名称: {test_case['name']}
        输入: {test_case['input']}
        预期输出: {test_case['expected']}
        
        要求:
        1. 使用pytest框架
        2. 包含适当的断言
        3. 添加必要的mock
        """
        
        response = self.client.chat.completions.create(
            model="gpt-4",
            messages=[{"role": "user", "content": prompt}],
            temperature=0.3
        )
        
        return response.choices[0].message.content

Step 2: 创建缺陷预测器

# ai/defect-predictor.py
from sklearn.ensemble import RandomForestClassifier
from sklearn.feature_extraction.text import TfidfVectorizer
import pandas as pd

class DefectPredictor:
    """基于历史数据的缺陷预测器"""
    
    def __init__(self):
        self.model = RandomForestClassifier(n_estimators=100)
        self.vectorizer = TfidfVectorizer(max_features=1000)
    
    def train(self, historical_data: pd.DataFrame):
        """训练模型"""
        X = self.vectorizer.fit_transform(historical_data['code_changes'])
        y = historical_data['has_defect']
        self.model.fit(X, y)
    
    def predict(self, code_changes: str) -> float:
        """预测缺陷概率"""
        X = self.vectorizer.transform([code_changes])
        probability = self.model.predict_proba(X)[0][1]
        return probability
    
    def get_risk_level(self, probability: float) -> str:
        """获取风险等级"""
        if probability > 0.7:
            return "高风险"
        elif probability > 0.4:
            return "中风险"
        else:
            return "低风险"

Step 3: Commit

git add ai/
git commit -m "feat: add AI-assisted testing tools"

Task 12: 建立CI/CD集成

Files:

  • Create: .github/workflows/test.yml
  • Create: .github/workflows/quality-gate.yml

Step 1: 创建测试工作流

# .github/workflows/test.yml
name: Test Suite

on:
  push:
    branches: [ main, develop ]
  pull_request:
    branches: [ main ]

jobs:
  api-tests:
    runs-on: ubuntu-latest
    
    steps:
    - uses: actions/checkout@v3
    
    - name: Set up Python
      uses: actions/setup-python@v4
      with:
        python-version: '3.13'
    
    - name: Install dependencies
      run: |
        cd everything-is-suitable-test/api
        pip install -r requirements.txt
    
    - name: Run API tests
      run: |
        cd everything-is-suitable-test/api
        python -m pytest tests/ --cov=src/apitest --cov-report=xml
    
    - name: Upload coverage
      uses: codecov/codecov-action@v3
      with:
        files: ./everything-is-suitable-test/api/coverage.xml
    
    - name: Check coverage threshold
      run: |
        coverage=$(python -c "import json; print(json.load(open('coverage.json'))['totals']['percent_covered'])")
        if (( $(echo "$coverage < 85" | bc -l) )); then
          echo "Coverage $coverage% is below threshold 85%"
          exit 1
        fi

  e2e-tests:
    runs-on: ubuntu-latest
    
    steps:
    - uses: actions/checkout@v3
    
    - name: Set up Node.js
      uses: actions/setup-node@v3
      with:
        node-version: '18'
    
    - name: Install dependencies
      run: |
        cd everything-is-suitable-test/e2e
        npm ci
    
    - name: Install Playwright
      run: npx playwright install --with-deps
    
    - name: Run E2E tests
      run: |
        cd everything-is-suitable-test/e2e
        npx playwright test
    
    - name: Upload test results
      uses: actions/upload-artifact@v3
      if: always()
      with:
        name: playwright-report
        path: everything-is-suitable-test/e2e/playwright-report/

Step 2: 创建质量门禁工作流

# .github/workflows/quality-gate.yml
name: Quality Gate

on:
  pull_request:
    branches: [ main ]

jobs:
  quality-check:
    runs-on: ubuntu-latest
    
    steps:
    - uses: actions/checkout@v3
    
    - name: Run linting
      run: |
        cd everything-is-suitable-test/api
        flake8 src/apitest --max-line-length=100
    
    - name: Run type checking
      run: |
        cd everything-is-suitable-test/api
        mypy src/apitest --strict
    
    - name: Check coverage
      run: |
        cd everything-is-suitable-test/api
        python -m pytest tests/ --cov=src/apitest --cov-fail-under=85
    
    - name: Security scan
      run: |
        bandit -r src/apitest -f json -o security-report.json
    
    - name: Upload reports
      uses: actions/upload-artifact@v3
      with:
        name: quality-reports
        path: |
          everything-is-suitable-test/api/security-report.json

Step 3: Commit

git add .github/workflows/
git commit -m "ci: add CI/CD pipelines with quality gates"

执行检查清单

阶段1完成标准

  • main.py测试覆盖率 > 80%
  • cli_module.py测试覆盖率 > 80%
  • 整体API测试覆盖率 > 85%
  • API服务可正常启动
  • 所有E2E测试可执行
  • 测试环境管理脚本可用

阶段2完成标准

  • 集成测试覆盖核心业务流程
  • E2E测试覆盖完整用户场景
  • 测试数据工厂投入使用
  • 测试类型分布均衡

阶段3完成标准

  • 性能测试可执行
  • 安全测试可执行
  • AI辅助工具可用
  • CI/CD流水线运行
  • 质量门禁生效
  • 整体覆盖率 > 90%

风险与缓解

风险1: API服务bean冲突

缓解: 优先解决Task 3,使用@Primary注解或重命名bean

风险2: E2E测试依赖后端

缓解: 使用Mock测试先行,真实后端测试作为补充

风险3: 性能测试环境要求

缓解: 使用轻量级负载测试,避免影响开发环境

风险4: AI工具成本

缓解: 使用开源模型或限制API调用次数


成功指标

阶段1指标

  • 整体覆盖率: 77.8% → 85%+
  • 测试通过率: 100% (保持)
  • E2E可执行性: 8/87 → 87/87

阶段2指标

  • 集成测试: 0 → 20+
  • E2E业务流程: 8 → 30+
  • 测试数据工厂: 0 → 1

阶段3指标

  • 性能测试: 0 → 1个套件
  • 安全测试: 0 → 1个套件
  • AI辅助工具: 0 → 2个工具
  • CI/CD: 0 → 2个流水线
  • 整体覆盖率: 85% → 90%+

计划创建时间: 2026-03-07
计划创建人: 张翔(资深金融级高级自动化测试工程师)
预计完成时间: 6个月
执行方法: TDD + 频繁提交 + 持续验证