コンテンツにスキップ

テストマーカーガイド

[!NOTE] 最新の実装状況は 機能実装ステータス (Remaining Functionality) を参照してください。

概要

EvoSpikeNetプロジェクトでは、pytestのマーカー機能を使用してテストを分類し、必要な依存関係に基づいて自動的にスキップします。これにより、CI環境や依存関係が不足している環境でも安全にテストを実行できます。

利用可能なマーカー

依存関係マーカー

@pytest.mark.requires_torch

  • 説明: PyTorchが必要なテスト
  • 自動スキップ: PyTorchがインストールされていない場合
  • 使用例:
    import pytest
    
    @pytest.mark.requires_torch
    def test_neural_network():
        import torch
        model = torch.nn.Linear(10, 5)
        assert model.out_features == 5
    

@pytest.mark.requires_gpu

  • 説明: GPU/CUDAが必要なテスト
  • 自動スキップ: CUDAが利用できない場合
  • 使用例:
    @pytest.mark.requires_torch
    @pytest.mark.requires_gpu
    def test_cuda_acceleration():
        import torch
        device = torch.device('cuda')
        tensor = torch.randn(100, 100, device=device)
        assert tensor.is_cuda
    

@pytest.mark.requires_milvus

  • 説明: Milvusベクトルデータベースが必要なテスト
  • 使用例:
    @pytest.mark.requires_milvus
    @pytest.mark.integration
    def test_vector_search():
        from pymilvus import connections
        connections.connect()
        # テストコード
    

@pytest.mark.requires_elasticsearch

  • 説明: Elasticsearchが必要なテスト
  • 使用例:
    @pytest.mark.requires_elasticsearch
    @pytest.mark.integration
    def test_text_search():
        from elasticsearch import Elasticsearch
        es = Elasticsearch()
        # テストコード
    

@pytest.mark.requires_zenoh

  • 説明: Zenoh通信ライブラリが必要なテスト
  • 使用例:
    @pytest.mark.requires_zenoh
    @pytest.mark.integration
    def test_distributed_communication():
        import zenoh
        # テストコード
    

テストカテゴリマーカー

@pytest.mark.unit

  • 説明: ユニットテスト(単一コンポーネントの動作検証)
  • 推奨: 外部依存なし、高速実行

@pytest.mark.integration

  • 説明: 統合テスト(複数コンポーネント間の連携検証)
  • 推奨: 必要最小限の外部依存

@pytest.mark.e2e

  • 説明: エンドツーエンドテスト(システム全体の動作検証)
  • 推奨: 実際の運用環境に近い条件

@pytest.mark.slow

  • 説明: 実行時間が長いテスト(通常1秒以上)
  • 使用例:
    @pytest.mark.slow
    @pytest.mark.integration
    def test_long_running_training():
        # 長時間かかるトレーニング処理
        pass
    

@pytest.mark.patent

  • 説明: 特許実装の検証テスト
  • 対象: EvoSpikeNetの特許技術(MT25-EV001〜EV016)の実装検証
  • 使用例:
    @pytest.mark.patent
    def test_chrono_spike_attention():
        """ChronoSpikeAttention (MT25-EV001) の実装検証"""
    
    <!--     from evospikenet.attention import ChronoSpikeAttention -->
        model = ChronoSpikeAttention(embed_dim=256, num_heads=8)
        # テストコード
    

モジュール全体へのマーカー適用

pytestmark変数を使用して、モジュール内の全テストに一括でマーカーを適用できます:

import pytest

# このモジュールの全テストにrequires_torchマーカーを適用
pytestmark = pytest.mark.requires_torch

def test_example_1():
    # このテストにはrequires_torchが自動適用される
    pass

def test_example_2():
    # このテストにもrequires_torchが自動適用される
    pass

複数のマーカーを適用する場合:

pytestmark = [
    pytest.mark.requires_torch,
    pytest.mark.requires_gpu,
    pytest.mark.slow
]

テスト実行例

全テストを実行

pytest tests/

ユニットテストのみ実行

pytest -m unit tests/

GPU必須テスト以外を実行

pytest -m "not requires_gpu" tests/

PyTorch必須テストのみ実行

pytest -m requires_torch tests/

統合テストとE2Eテストを除外

pytest -m "not integration and not e2e" tests/

遅いテストを除外

pytest -m "not slow" tests/

複数条件の組み合わせ

# ユニットテストかつPyTorch必須テスト
pytest -m "unit and requires_torch" tests/

# 統合テストでGPU不要なもの
pytest -m "integration and not requires_gpu" tests/

特定のマーカーを持つテストをリスト表示

pytest --collect-only -m requires_gpu tests/

CI/CD環境での使用

CPU専用環境

# GPU必須テストをスキップ
pytest -m "not requires_gpu" tests/

軽量環境(依存関係最小限)

# 外部依存が必要なテストをスキップ
pytest -m "not requires_milvus and not requires_elasticsearch and not requires_zenoh" tests/

高速テストのみ

# 遅いテストをスキップ
pytest -m "not slow" tests/

ベストプラクティス

1. 適切なマーカーの選択

# ✅ 良い例: 明確で具体的なマーカー
@pytest.mark.unit
@pytest.mark.requires_torch
def test_lif_neuron():
    pass

# ❌ 悪い例: マーカーなし(依存関係が不明確)
def test_something():
    import torch  # 突然失敗する可能性
    pass

2. 依存関係の明示

# ✅ 良い例: GPU必須を明示
@pytest.mark.requires_torch
@pytest.mark.requires_gpu
def test_cuda_kernel():
    device = torch.device('cuda')
    # GPU処理

# ❌ 悪い例: CUDA可用性チェックをテスト内で実施
def test_maybe_cuda():
    if torch.cuda.is_available():
        # GPU処理
    else:
        pytest.skip("CUDA not available")

3. テストの階層化

# ユニットテスト: 高速、依存少
@pytest.mark.unit
@pytest.mark.requires_torch
def test_neuron_activation():
    pass

# 統合テスト: 中速、複数コンポーネント
@pytest.mark.integration
@pytest.mark.requires_torch
def test_network_training():
    pass

# E2Eテスト: 低速、全システム
@pytest.mark.e2e
@pytest.mark.slow
@pytest.mark.requires_torch
@pytest.mark.requires_gpu
def test_full_pipeline():
    pass

4. 特許テストの管理

@pytest.mark.patent
@pytest.mark.integration
@pytest.mark.requires_torch
def test_patent_implementation_mt25_ev001():
    """特許MT25-EV001の実装を検証"""
    pass

自動スキップの仕組み

tests/conftest.pyで定義されたpytest_collection_modifyitemsフックが、テスト収集時に自動的にスキップマーカーを追加します:

def pytest_collection_modifyitems(config, items):
    skip_torch = pytest.mark.skip(reason="PyTorch not available")
    skip_gpu = pytest.mark.skip(reason="GPU/CUDA not available")

    for item in items:
        if "requires_torch" in item.keywords and not _HAS_TORCH:
            item.add_marker(skip_torch)

        if "requires_gpu" in item.keywords:
            if not _HAS_TORCH or not torch.cuda.is_available():
                item.add_marker(skip_gpu)

トラブルシューティング

マーカーが認識されない

# 利用可能なマーカーを確認
pytest --markers

# strict-markersモードで未登録マーカーを検出
pytest --strict-markers tests/

スキップされるべきテストが実行される

  • conftest.pyの自動スキップロジックを確認
  • マーカーが正しく適用されているか確認: pytest --collect-only -m requires_gpu

予期しないテストがスキップされる

  • マーカーの組み合わせを確認
  • -vオプションでスキップ理由を表示: pytest -v tests/

参考リンク