迭代 138 测试策略

版本: v1.0 | 日期: 2026-02-28


1. 测试目标

1.1 质量目标

| 指标 | 目标 | 说明 |

|——|——|——|

| 单元测试覆盖率 | >= 80% | 核心代码必须覆盖 |

| 集成测试通过率 | 100% | 所有集成测试必须通过 |

| 回归测试通过率 | 100% | 现有 1020 个测试全通过 |

| 性能测试达标率 | 100% | 所有性能指标达标 |

1.2 零回归承诺

  • 关键原则*:新功能不能破坏现有功能

  • 现有 1020 个测试必须全部通过

  • 纯 K 线模式(BAR)行为完全不变

  • 所有现有 API 保持向后兼容


2. 测试金字塔

         /\
        /E2E\         10% - 端到端测试(完整回测场景)
       /------\
      /集成测试\       30% - 集成测试(组件协作)
     /----------\
    /  单元测试  \     60% - 单元测试(独立组件)
   /--------------\

```bash

### 2.1 单元测试(60%)

- *范围**:独立组件的功能验证

| 组件 | 测试文件 | 重点 |

|------|---------|------|

| StreamingEventQueue | `test_streaming_queue.py` | 事件排序、内存控制 |

| DataChannel | `test_data_channel.py` | 数据验证、缓冲管理 |

| TickChannel | `test_tick_channel.py` | Tick 数据加载、验证 |

| OrderBookChannel | `test_orderbook_channel.py` | OB 数据结构、验证 |

| TickBroker | `test_tick_broker.py` | Tick 撮合逻辑 |

| MixBroker | `test_mix_broker.py` | 混合撮合逻辑 |

| Strategy 回调 | `test_strategy_callbacks.py` | 回调触发、参数传递 |

- *示例**:

```python

# tests/unit/test_streaming_queue.py

import pytest
from backtrader.channel import StreamingEventQueue, Event

class TestStreamingEventQueue:

    def test_event_ordering_by_timestamp(self):
        """测试事件按时间戳排序"""
        queue = StreamingEventQueue([], [])

# 乱序插入
        queue._push_event(Event(timestamp=100.0), 'tick', 'BTC')
        queue._push_event(Event(timestamp=50.0), 'tick', 'BTC')
        queue._push_event(Event(timestamp=75.0), 'tick', 'BTC')

# 验证弹出顺序
        assert queue.pop().timestamp == 50.0
        assert queue.pop().timestamp == 75.0
        assert queue.pop().timestamp == 100.0

    def test_event_ordering_by_priority(self):
        """测试同时间戳按优先级排序"""
        queue = StreamingEventQueue([], [])

# 同时间戳,不同优先级
        queue._push_event(Event(timestamp=100.0, priority=30), 'tick', 'BTC')
        queue._push_event(Event(timestamp=100.0, priority=10), 'funding', 'BTC')
        queue._push_event(Event(timestamp=100.0, priority=20), 'orderbook', 'BTC')

# 验证优先级顺序
        assert queue.pop().priority == 10  # funding
        assert queue.pop().priority == 20  # orderbook
        assert queue.pop().priority == 30  # tick

    def test_adaptive_window_shrink(self):
        """测试自适应窗口缩小"""
        queue = StreamingEventQueue(
            [], [],
            preload_window=300.0,
            max_memory_mb=10,
            adaptive=True
        )

# 模拟内存压力

# ... 填充大量事件 ...

# 验证窗口缩小
        assert queue._window < 300.0
        assert queue._adjustment_count > 0

```bash

- --

### 2.2 集成测试(30%)

- *范围**:组件间协作验证

| 场景 | 测试文件 | 重点 |

|------|---------|------|

| Tick 模式回测 | `test_tick_mode_integration.py` | EventQueue + TickBroker + Strategy |

| 混合模式回测 | `test_mixed_mode_integration.py` | Bar + Tick 协作 |

|  Channel 协作 | `test_multi_channel.py` | Tick + OB + Funding |

| 异常处理 | `test_error_handling.py` | 数据异常、策略异常 |

| 通知机制 | `test_notification_flow.py` | Broker 通知 + 策略回调 |

- *示例**:

```python

# tests/integration/test_tick_mode_integration.py

import backtrader as bt
from backtrader.channels.tick import TickChannel

class TickStrategy(bt.Strategy):
    def __init__(self):
        self.tick_count = 0
        self.order_count = 0

    def on_tick(self, channel, tick):
        self.tick_count += 1

# 每 100 个 tick 买入
        if self.tick_count % 100 == 0:
            self.buy(size=0.1)

    def notify_order(self, order):
        if order.status == order.Completed:
            self.order_count += 1

def test_tick_mode_basic_flow():
    """测试 Tick 模式基本流程"""
    cerebro = bt.Cerebro()

# 添加 Tick 通道
    cerebro.add_channel(
        TickChannel,
        symbol='BTC/USDT',
        dataname='tests/data/btc_ticks_1day.csv'
    )

# 添加策略
    cerebro.addstrategy(TickStrategy)

# 运行(Tick 模式)
    results = cerebro.run(mode=bt.RunMode.TICK)

    strat = results[0]

# 验证
    assert strat.tick_count > 0, "应该处理了 tick 数据"
    assert strat.order_count > 0, "应该有订单成交"

# 验证 Broker 使用 TickBroker
    assert isinstance(cerebro._broker, bt.brokers.TickBroker)

def test_tick_and_orderbook_coordination():
    """测试 Tick 和 OrderBook 协作"""
    cerebro = bt.Cerebro()

    cerebro.add_channel(TickChannel, symbol='BTC/USDT', dataname='...')
    cerebro.add_channel(OrderBookChannel, symbol='BTC/USDT', dataname='...')

# ... 策略使用 OB 辅助 Tick 交易决策 ...

    results = cerebro.run(mode=bt.RunMode.TICK)

# 验证事件顺序:OB 优先级高于 Tick

# ...

```bash

- --

### 2.3 端到端测试(10%)

- *范围**:完整业务场景验证

| 场景 | 测试文件 | 重点 |

|------|---------|------|

| 完整 Tick 回测 | `test_e2e_tick_backtest.py` | 数据加载→回测→分析 |

| 混合模式回测 | `test_e2e_mixed_backtest.py` | Bar 主时钟 + Tick 辅助 |

| 实盘模拟 | `test_e2e_live_simulation.py` | WebSocket 数据 + 实时撮合 |

| 性能场景 | `test_e2e_performance.py` | 大数据量、长时间 |

- *示例**:

```python

# tests/e2e/test_e2e_tick_backtest.py

def test_complete_tick_backtest_workflow():
    """测试完整 Tick 回测流程"""

# 1. 准备数据
    tick_data = prepare_tick_data('BTC/USDT', days=7)
    ob_data = prepare_orderbook_data('BTC/USDT', days=7)

# 2. 配置 Cerebro
    cerebro = bt.Cerebro()
    cerebro.broker.setcash(100000)

# 3. 添加通道
    cerebro.add_channel(TickChannel, symbol='BTC/USDT', dataname=tick_data)
    cerebro.add_channel(OrderBookChannel, symbol='BTC/USDT', dataname=ob_data)

# 4. 添加策略
    cerebro.addstrategy(AdvancedTickStrategy)

# 5. 添加分析器
    cerebro.addanalyzer(bt.analyzers.SharpeRatio, _name='sharpe')
    cerebro.addanalyzer(bt.analyzers.TradeAnalyzer, _name='trades')

# 6. 运行
    results = cerebro.run(mode=bt.RunMode.TICK)

# 7. 验证结果
    strat = results[0]

    sharpe = strat.analyzers.sharpe.get_analysis()
    trades = strat.analyzers.trades.get_analysis()

    assert sharpe['sharperatio'] is not None
    assert trades['total']['total'] > 0

# 8. 验证性能

# 7 天 tick 数据应该在合理时间内完成

# ...

```bash

- --

## 3. 回归测试策略

### 3.1 现有测试保护

- *目标**:确保现有 1020 个测试全部通过

- *策略**:
1. 每次提交前运行完整回归测试
2. CI/CD 自动运行回归测试
3. 任何回归失败立即修复

- *命令**:

```bash

# 运行所有现有测试

pytest tests/ -v --tb=short

# 排除新增测试

pytest tests/ -v --ignore=tests/phase0 --ignore=tests/phase1 \

  - -ignore=tests/integration/tick --ignore=tests/e2e/tick

```bash

### 3.2 兼容性测试

- *测试矩阵**:

| 场景 | 预期行为 | 测试方法 |

|------|---------|---------|

|  K 线策略 | 完全不变 | 运行现有策略示例 |

| 不添加 Channel | BAR 模式 | 验证默认行为 |

| 现有 Broker | BackBroker 不变 | 单元测试 |

| 现有 Analyzer | 正常工作 | 集成测试 |

- *示例**:

```python

# tests/regression/test_backward_compatibility.py

def test_existing_strategy_unchanged():
    """测试现有策略行为不变"""

# 使用现有的示例策略
    cerebro = bt.Cerebro()
    cerebro.adddata(bt.feeds.GenericCSVData(dataname='...'))
    cerebro.addstrategy(bt.strategies.SMA_CrossOver)

# 不添加 Channel,应该自动使用 BAR 模式
    results = cerebro.run()

# 验证使用 BackBroker
    assert isinstance(cerebro._broker, bt.brokers.BackBroker)

# 验证结果与历史一致

# ...

def test_no_channel_defaults_to_bar_mode():
    """测试不添加 Channel 时默认 BAR 模式"""
    cerebro = bt.Cerebro()
    cerebro.adddata(...)
    cerebro.addstrategy(...)

    results = cerebro.run()

# 验证运行模式
    assert cerebro._run_mode == bt.RunMode.BAR

```bash

- --

## 4. 性能测试

### 4.1 性能基准

| 指标 | 目标 | 测试方法 |

|------|------|---------|

| 1  Tick 回测 | < 10  | benchmark_tick.py |

| 内存使用 | < 200MB | memory_profiler |

| 事件处理吞吐 | > 10K events/s | performance_test.py |

| CPU 使用率 | < 80% | psutil 监控 |

### 4.2 性能测试用例

```python

# tests/performance/benchmark_tick.py

import time
import psutil
from backtrader.channels.tick import TickChannel

def benchmark_tick_backtest():
    """Tick 回测性能基准"""

    process = psutil.Process()

# 准备 1 天 tick 数据(约 17M 条)
    cerebro = bt.Cerebro()
    cerebro.add_channel(
        TickChannel,
        symbol='BTC/USDT',
        dataname='tests/data/btc_ticks_1day.csv'
    )
    cerebro.addstrategy(SimpleTickStrategy)

# 记录初始状态
    start_time = time.time()
    start_memory = process.memory_info().rss / 1024 / 1024

# 运行
    results = cerebro.run(mode=bt.RunMode.TICK)

# 记录结束状态
    end_time = time.time()
    end_memory = process.memory_info().rss / 1024 / 1024

    elapsed = end_time - start_time
    memory_used = end_memory - start_memory

    print(f"\n=== Performance Benchmark ===")
    print(f"Time: {elapsed:.2f}s")
    print(f"Memory: {memory_used:.1f}MB")
    print(f"Target: < 10s, < 200MB")

# 验证性能目标
    assert elapsed < 10, f"Time {elapsed:.2f}s exceeds 10s target"
    assert memory_used < 200, f"Memory {memory_used:.1f}MB exceeds 200MB target"

def benchmark_event_throughput():
    """事件处理吞吐量基准"""

    queue = StreamingEventQueue(...)

    start = time.time()
    count = 0

    while queue:
        event = queue.pop()
        count += 1

    elapsed = time.time() - start
    throughput = count / elapsed

    print(f"Throughput: {throughput:.0f} events/sec")
    assert throughput > 10000, f"Throughput {throughput:.0f} below 10K target"

```bash

### 4.3 压力测试

```python

# tests/performance/stress_test.py

def test_long_duration_stability():
    """长时间运行稳定性测试"""

# 30 天 tick 数据
    cerebro = bt.Cerebro()
    cerebro.add_channel(TickChannel, dataname='30days_ticks.csv')
    cerebro.addstrategy(...)

# 监控内存增长
    memory_samples = []

    def memory_monitor():
        while True:
            memory_samples.append(psutil.Process().memory_info().rss)
            time.sleep(10)

# 运行
    results = cerebro.run(mode=bt.RunMode.TICK)

# 验证内存不持续增长(排除内存泄漏)
    growth_rate = calculate_memory_growth_rate(memory_samples)
    assert growth_rate < 0.01, "Potential memory leak detected"

def test_high_frequency_events():
    """高频事件处理测试"""

# 模拟极高频 tick(1000/秒)

# 验证系统能否处理

# ...

```bash

- --

## 5. 数据驱动测试

### 5.1 测试数据准备

- *数据集**:

| 数据集 | 说明 | 用途 |

|--------|------|------|

| `btc_ticks_1day.csv` | 1  BTC tick | 基础功能测试 |

| `btc_ticks_7days.csv` | 7  BTC tick | 集成测试 |

| `btc_ticks_30days.csv` | 30  BTC tick | 压力测试 |

| `btc_ob_1day.jsonl` | 1  OrderBook | OB 功能测试 |

| `corrupted_ticks.csv` | 损坏的 tick 数据 | 异常处理测试 |

| `out_of_order_ticks.csv` | 乱序 tick 数据 | 数据验证测试 |

### 5.2 数据生成工具

```python

# tests/data/generate_test_data.py

def generate_tick_data(symbol, days, ticks_per_second=200):
    """生成模拟 tick 数据"""

    import pandas as pd
    import numpy as np

    total_ticks = days *86400*ticks_per_second

    timestamps = np.arange(total_ticks) / ticks_per_second
    prices = 50000 + np.cumsum(np.random.randn(total_ticks)*10)
    volumes = np.random.exponential(0.5, total_ticks)
    directions = np.random.choice(['buy', 'sell'], total_ticks)

    df = pd.DataFrame({
        'timestamp': timestamps,
        'price': prices,
        'volume': volumes,
        'direction': directions,
        'trade_id': [f'T{i}' for i in range(total_ticks)]
    })

    return df

def generate_corrupted_data():
    """生成包含错误的测试数据"""

    df = generate_tick_data('BTC/USDT', days=1)

# 注入各种错误
    df.loc[100, 'price'] = -50000  # 负价格
    df.loc[200, 'volume'] = -1.0   # 负成交量
    df.loc[300, 'direction'] = 'invalid'  # 无效方向
    df.loc[400, 'timestamp'] = df.loc[399, 'timestamp'] - 1  # 乱序

    return df

```bash

- --

## 6. 测试自动化

### 6.1 CI/CD 集成

- *GitHub Actions 配置**:

```yaml

# .github/workflows/test.yml

name: Test Suite

on: [push, pull_request]

jobs:
  test:
    runs-on: ubuntu-latest

    steps:

    - uses: actions/checkout@v2

    - name: Set up Python

      uses: actions/setup-python@v2
      with:
        python-version: 3.8

    - name: Install dependencies

      run: |

        pip install -r requirements.txt
        pip install pytest pytest-cov

    - name: Run unit tests

      run: pytest tests/unit -v --cov=backtrader

    - name: Run integration tests

      run: pytest tests/integration -v

    - name: Run regression tests

      run: pytest tests/ --ignore=tests/phase* -v

    - name: Upload coverage

      uses: codecov/codecov-action@v2

```bash

### 6.2 Pre-commit Hooks

```bash

# .pre-commit-config.yaml

repos:

  - repo: local

    hooks:

      - id: pytest-unit

        name: Run unit tests
        entry: pytest tests/unit -v
        language: system
        pass_filenames: false
        always_run: true

```bash

- --

## 7. 测试报告

### 7.1 报告模板

```markdown

# 测试报告 - Phase X

## 测试概况

- 测试日期:YYYY-MM-DD
- 测试人员:XXX
- 测试环境:Python 3.8, Ubuntu 20.04

## 测试结果

### 单元测试

- 总数:XXX
- 通过:XXX
- 失败:XXX
- 覆盖率:XX%

### 集成测试

- 总数:XXX
- 通过:XXX
- 失败:XXX

### 回归测试

- 总数:1020
- 通过:XXX
- 失败:XXX

### 性能测试

- 1  Tick 回测:X.XX  (目标<10 )
- 内存使用:XXX MB (目标<200MB)
- 事件吞吐:XXXXX events/s (目标>10K)

## 失败用例分析

### 失败用例 1

- 用例名称:test_xxx
- 失败原因:...
- 修复计划:...

## 风险评估

- 高风险问题:X 个
- 中风险问题:X 个
- 低风险问题:X ## 结论

- [ ] 通过验收标准
- [ ] 需要修复后重测

```bash

- --

## 8. 测试工具

### 8.1 推荐工具

| 工具 | 用途 | 安装 |

|------|------|------|

| pytest | 测试框架 | `pip install pytest` |

| pytest-cov | 覆盖率 | `pip install pytest-cov` |

| pytest-xdist | 并行测试 | `pip install pytest-xdist` |

| memory_profiler | 内存分析 | `pip install memory_profiler` |

| psutil | 系统监控 | `pip install psutil` |

| faker | 测试数据生成 | `pip install faker` |

### 8.2 自定义测试工具

```python

# tests/utils/test_helpers.py

import backtrader as bt
from contextlib import contextmanager

@contextmanager
def assert_no_regression():
    """确保测试不影响现有功能"""

# 运行现有测试套件
    before = run_regression_tests()

    yield

# 再次运行
    after = run_regression_tests()

    assert before == after, "Regression detected!"

def create_test_cerebro(**kwargs):
    """创建测试用 Cerebro"""
    cerebro = bt.Cerebro()
    cerebro.broker.setcash(100000)
    cerebro.broker.setcommission(commission=0.001)
    return cerebro

class MockTickChannel:
    """Mock Tick 通道用于测试"""

    def __init__(self, events):
        self._events = events
        self._index = 0

    def load(self):
        for event in self._events:
            yield event

```bash

- --

## 9. 测试检查清单

### 9.1 Phase 完成前检查

- [ ] 所有单元测试通过
- [ ] 所有集成测试通过
- [ ] 回归测试 100%通过
- [ ] 代码覆盖率 >= 80%
- [ ] 性能测试达标
- [ ] 内存泄漏检查通过
- [ ] 文档更新完成
- [ ] 代码审查通过

### 9.2 发布前检查

- [ ] 所有 Phase 测试通过
- [ ] E2E 测试通过
- [ ] 压力测试通过
- [ ] 兼容性测试通过
- [ ] 性能基准达标
- [ ] 安全审计通过
- [ ] 文档完整
- [ ] 示例代码可运行

- --

## 10. 附录

### A. 测试命令速查

```bash

# 运行所有测试

pytest tests/ -v

# 运行单元测试

pytest tests/unit -v

# 运行集成测试

pytest tests/integration -v

# 运行回归测试

pytest tests/ --ignore=tests/phase* -v

# 运行性能测试

pytest tests/performance -v

# 生成覆盖率报告

pytest tests/ --cov=backtrader --cov-report=html

# 并行运行测试

pytest tests/ -n auto

# 运行特定测试

pytest tests/unit/test_streaming_queue.py::test_event_ordering -v

```bash

### B. 测试数据路径

```bash
tests/
├── data/
│   ├── btc_ticks_1day.csv
│   ├── btc_ticks_7days.csv
│   ├── btc_ticks_30days.csv
│   ├── btc_ob_1day.jsonl
│   ├── corrupted_ticks.csv
│   └── out_of_order_ticks.csv

```bash