Skip to content

Latest commit

 

History

History
463 lines (392 loc) · 12 KB

File metadata and controls

463 lines (392 loc) · 12 KB

🏗️ 架构设计

欢迎来到巧克力测试平台的"内功心法"!这里将揭秘平台的架构设计,让你了解这个测试平台是如何"炼成"的。

🎯 整体架构概览

技术栈选择

巧克力测试平台采用现代化的前后端分离架构:

前端技术栈

  • React 18: 现代化的前端框架
  • TypeScript: 类型安全的JavaScript超集
  • Ant Design Pro: 企业级UI解决方案
  • UmiJS 4: 可扩展的企业级前端应用框架
  • ProComponents: 高级组件库

后端技术栈

  • Flask: 轻量级Python Web框架
  • SQLAlchemy: Python ORM框架
  • Celery: 分布式任务队列
  • Redis: 缓存和消息队列
  • MySQL: 关系型数据库

测试技术栈

  • Pytest: Python测试框架
  • Locust: 性能测试工具
  • Requests: HTTP请求库

架构图

┌─────────────────┐    ┌─────────────────┐    ┌─────────────────┐
│   前端应用       │    │   后端API       │    │   测试引擎       │
│  (React+TS)     │◄──►│   (Flask)       │◄──►│ (Pytest+Locust) │
└─────────────────┘    └─────────────────┘    └─────────────────┘
         │                       │                       │
         │                       │                       │
         ▼                       ▼                       ▼
┌─────────────────┐    ┌─────────────────┐    ┌─────────────────┐
│   静态资源       │    │   数据存储       │    │   任务队列       │
│   (CDN/Nginx)   │    │ (MySQL+Redis)   │    │   (Celery)      │
└─────────────────┘    └─────────────────┘    └─────────────────┘

🎨 前端架构设计

目录结构

src/
├── components/          # 公共组件
│   ├── RightContent/   # 右侧内容组件
│   └── Footer/         # 页脚组件
├── pages/              # 页面组件
│   ├── openapitest/    # 接口测试页面
│   ├── LocustTest/     # 压力测试页面
│   ├── Project/        # 项目管理页面
│   └── User/           # 用户相关页面
├── services/           # API服务层
│   ├── test_case/      # 测试用例服务
│   ├── test_suite/     # 测试套件服务
│   ├── test_plan/      # 测试计划服务
│   └── locust_*/       # Locust相关服务
├── models/             # 数据模型
├── utils/              # 工具函数
└── typings.d.ts        # 类型定义

组件设计原则

单一职责原则

每个组件只负责一个特定的功能:

// 好的设计 - 单一职责
const TestCaseList = () => {
  // 只负责展示测试用例列表
};

const TestCaseForm = () => {
  // 只负责测试用例表单
};

组件复用性

设计可复用的通用组件:

// 通用表格组件
interface ProTableProps<T> {
  columns: ProColumns<T>[];
  request: (params: any) => Promise<any>;
  actionRef?: React.MutableRefObject<ActionType>;
}

状态管理

全局状态

使用UmiJS的初始状态管理全局数据:

// app.tsx
export async function getInitialState() {
  return {
    currentUser: await fetchUserInfo(),
    settings: defaultSettings,
  };
}

页面状态

使用React Hooks管理页面级状态:

const [loading, setLoading] = useState(false);
const [dataSource, setDataSource] = useState([]);
const actionRef = useRef<ActionType>();

路由设计

路由结构

// config/routes.ts
export default [
  {
    path: '/openapitest',
    name: '接口测试',
    icon: 'api',
    routes: [
      {
        path: '/openapitest/case',
        name: '用例管理',
        component: './openapitest/caseList',
      },
      {
        path: '/openapitest/suite',
        name: '套件管理',
        component: './openapitest/caseSuiteList',
      },
    ],
  },
];

权限控制

基于用户角色的路由权限控制:

// access.ts
export default function access(initialState) {
  const { currentUser } = initialState ?? {};
  return {
    canAdmin: currentUser && currentUser.access === 1,
    canTest: currentUser && currentUser.access === 0,
  };
}

🔧 后端架构设计

服务分层架构

┌─────────────────┐
│   Controller    │  # 控制器层 - 处理HTTP请求
├─────────────────┤
│    Service      │  # 服务层 - 业务逻辑处理
├─────────────────┤
│      DAO        │  # 数据访问层 - 数据库操作
├─────────────────┤
│     Model       │  # 模型层 - 数据模型定义
└─────────────────┘

API设计规范

RESTful API设计

# 资源命名规范
GET    /api/auto_pytest/get_case          # 获取测试用例
POST   /api/auto_pytest/create_suite      # 创建测试套件
PUT    /api/auto_pytest/update_plan       # 更新测试计划
DELETE /api/auto_pytest/delete_project    # 删除项目

统一响应格式

{
    "success": true,
    "data": {
        # 具体数据
    },
    "msg": "操作成功",
    "code": 200
}

数据库设计

核心表结构

-- 项目表
CREATE TABLE test_project (
    id INT PRIMARY KEY AUTO_INCREMENT,
    project_name VARCHAR(255) NOT NULL,
    project_desc TEXT,
    project_owners VARCHAR(255),
    add_time DATETIME,
    update_time DATETIME,
    is_deleted BOOLEAN DEFAULT FALSE
);

-- 测试用例表
CREATE TABLE test_case (
    id INT PRIMARY KEY AUTO_INCREMENT,
    case_func VARCHAR(255) NOT NULL,
    case_func_desc TEXT,
    case_sence VARCHAR(255),
    moudle_id INT,
    path_desc TEXT,
    tags VARCHAR(255),
    update_time DATETIME
);

-- 测试套件表
CREATE TABLE test_suite (
    id INT PRIMARY KEY AUTO_INCREMENT,
    suite_name VARCHAR(255) NOT NULL,
    describe TEXT,
    project_id INT,
    case_ids TEXT,
    test_type VARCHAR(50),
    test_env VARCHAR(50),
    add_time DATETIME,
    update_time DATETIME
);

数据关系设计

Project (1) ──── (N) TestSuite
TestSuite (N) ──── (N) TestCase
TestSuite (1) ──── (N) TestPlan
TestPlan (1) ──── (N) TestResult

🔄 测试引擎架构

Pytest集成架构

# 测试执行流程
class TestExecutor:
    def __init__(self, suite_config):
        self.suite_config = suite_config
        
    def execute(self):
        # 1. 准备测试环境
        self.setup_environment()
        
        # 2. 执行测试用例
        result = self.run_tests()
        
        # 3. 收集测试结果
        self.collect_results(result)
        
        # 4. 生成测试报告
        self.generate_report()

Locust集成架构

# 压力测试执行流程
class LocustExecutor:
    def __init__(self, locust_config):
        self.config = locust_config
        
    def start_test(self):
        # 1. 启动Locust Master
        self.start_master()
        
        # 2. 启动Worker节点
        self.start_workers()
        
        # 3. 开始压力测试
        self.begin_test()
        
        # 4. 监控测试过程
        self.monitor_test()

任务队列架构

# Celery任务定义
@celery.task
def execute_test_suite(suite_id, env):
    """异步执行测试套件"""
    try:
        # 执行测试
        result = TestExecutor(suite_id, env).execute()
        
        # 保存结果
        save_test_result(result)
        
        # 发送通知
        send_notification(result)
        
    except Exception as e:
        # 错误处理
        handle_error(e)

🔐 安全架构设计

认证授权

# JWT Token认证
class AuthMiddleware:
    def __init__(self):
        self.secret_key = config.SECRET_KEY
        
    def verify_token(self, token):
        try:
            payload = jwt.decode(token, self.secret_key)
            return payload['user_id']
        except jwt.ExpiredSignatureError:
            raise AuthError('Token已过期')
        except jwt.InvalidTokenError:
            raise AuthError('无效Token')

权限控制

# 基于角色的权限控制
class PermissionManager:
    PERMISSIONS = {
        'admin': ['read', 'write', 'delete', 'manage'],
        'tester': ['read', 'write'],
        'viewer': ['read']
    }
    
    def check_permission(self, user_role, action):
        return action in self.PERMISSIONS.get(user_role, [])

数据安全

  • SQL注入防护: 使用ORM参数化查询
  • XSS防护: 前端输入验证和转义
  • CSRF防护: 使用CSRF Token
  • 敏感数据加密: 密码和敏感配置加密存储

📊 监控和日志架构

应用监控

# 性能监控
class PerformanceMonitor:
    def __init__(self):
        self.metrics = {}
        
    def record_api_call(self, endpoint, duration):
        if endpoint not in self.metrics:
            self.metrics[endpoint] = []
        self.metrics[endpoint].append(duration)
        
    def get_avg_response_time(self, endpoint):
        times = self.metrics.get(endpoint, [])
        return sum(times) / len(times) if times else 0

日志系统

# 结构化日志
import logging
import json

class StructuredLogger:
    def __init__(self):
        self.logger = logging.getLogger(__name__)
        
    def log_api_request(self, request, response, duration):
        log_data = {
            'timestamp': datetime.now().isoformat(),
            'method': request.method,
            'url': request.url,
            'status_code': response.status_code,
            'duration': duration,
            'user_id': request.user.id if request.user else None
        }
        self.logger.info(json.dumps(log_data))

🚀 部署架构

容器化部署

# Dockerfile示例
FROM node:16-alpine AS frontend-build
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build

FROM python:3.9-slim AS backend
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
EXPOSE 5000
CMD ["python", "app.py"]

微服务架构

# docker-compose.yml
version: '3.8'
services:
  frontend:
    build: ./frontend
    ports:
      - "3000:3000"
      
  backend:
    build: ./backend
    ports:
      - "5000:5000"
    depends_on:
      - mysql
      - redis
      
  mysql:
    image: mysql:8.0
    environment:
      MYSQL_ROOT_PASSWORD: password
      
  redis:
    image: redis:6.2-alpine
    
  celery:
    build: ./backend
    command: celery worker -A app.celery
    depends_on:
      - redis

💡 设计原则和最佳实践

SOLID原则应用

  1. 单一职责原则: 每个类和函数只负责一个功能
  2. 开闭原则: 对扩展开放,对修改关闭
  3. 里氏替换原则: 子类可以替换父类
  4. 接口隔离原则: 使用多个专门的接口
  5. 依赖倒置原则: 依赖抽象而不是具体实现

可扩展性设计

  • 插件化架构: 支持功能插件扩展
  • 配置化驱动: 通过配置文件控制行为
  • 事件驱动: 使用事件机制解耦组件
  • 微服务化: 按业务域拆分服务

性能优化策略

  • 前端优化: 代码分割、懒加载、缓存策略
  • 后端优化: 数据库索引、查询优化、缓存机制
  • 网络优化: CDN、压缩、HTTP/2
  • 系统优化: 负载均衡、集群部署

🎉 架构师! 你已经了解了巧克力测试平台的架构精髓。好的架构不是一蹴而就的,而是在实践中不断演进和优化的!