Files
JiangCheng 1d1df9235b feat(i18n): Add Japanese (ja/) translation (#105)
- Translate all 101 markdown files: P1 core, all 10 modules, examples,
  auxiliary docs (CONTRIBUTING, CODE_OF_CONDUCT, SECURITY, CLAUDE.md, etc.),
  peripheral docs (.github/, docs/, resources/, scripts/)
- Translate comments and user-facing messages in 06-hooks/*.sh examples
- Copy 05-mcp/*.json examples (standard JSON, no comments)
- Update root README.md language switcher to include 日本語
- Add ja/TRANSLATION_NOTES.md (glossary + style guide)

All translations pass pre-commit quality gates (markdown-lint,
cross-references, mermaid-syntax, link-check, build-epub).
2026-04-30 00:16:46 +02:00

9.6 KiB
Raw Permalink Blame History

テストガイド

本ドキュメントは Claude How To のテスト基盤について説明する。

概要

本プロジェクトは GitHub Actions を使い、すべてのプッシュとプルリクエストで自動的にテストを実行する。テスト内容:

  • ユニットテスト: pytest による Python テスト
  • コード品質: Ruff によるリンティングとフォーマット
  • セキュリティ: Bandit による脆弱性スキャン
  • 型チェック: mypy による静的型解析
  • ビルド検証: EPUB 生成テスト

ローカルでテストを実行する

前提条件

# Install uv (fast Python package manager)
pip install uv

# Or on macOS with Homebrew
brew install uv

環境セットアップ

# Clone the repository
git clone https://github.com/luongnv89/claude-howto.git
cd claude-howto

# Create virtual environment
uv venv

# Activate it
source .venv/bin/activate  # macOS/Linux
# or
.venv\Scripts\activate     # Windows

# Install development dependencies
uv pip install -r requirements-dev.txt

テスト実行

# Run all unit tests
pytest scripts/tests/ -v

# Run tests with coverage
pytest scripts/tests/ -v --cov=scripts --cov-report=html

# Run specific test file
pytest scripts/tests/test_build_epub.py -v

# Run specific test function
pytest scripts/tests/test_build_epub.py::test_function_name -v

# Run tests in watch mode (requires pytest-watch)
ptw scripts/tests/

リンティング実行

# Check code formatting
ruff format --check scripts/

# Auto-fix formatting issues
ruff format scripts/

# Run linter
ruff check scripts/

# Auto-fix linter issues
ruff check --fix scripts/

セキュリティスキャン実行

# Run Bandit security scan
bandit -c pyproject.toml -r scripts/ --exclude scripts/tests/

# Generate JSON report
bandit -c pyproject.toml -r scripts/ --exclude scripts/tests/ -f json -o bandit-report.json

型チェック実行

# Check types with mypy
mypy scripts/ --ignore-missing-imports --no-implicit-optional

GitHub Actions ワークフロー

トリガー

  • main または develop ブランチへの プッシュscripts が変更されたとき)
  • main への プルリクエストscripts が変更されたとき)
  • 手動の workflow dispatch

ジョブ

1. ユニットテスト(pytest

  • 実行環境: Ubuntu latest
  • Python バージョン: 3.10、3.11、3.12
  • 内容:
    • requirements-dev.txt から依存関係をインストール
    • カバレッジレポート付きで pytest を実行
    • カバレッジを Codecov へアップロード
    • テスト結果とカバレッジ HTML をアーカイブ

結果: テストが 1 つでも失敗するとワークフロー失敗(クリティカル)

2. コード品質(Ruff

  • 実行環境: Ubuntu latest
  • Python バージョン: 3.11
  • 内容:
    • ruff format でコードフォーマットを確認
    • ruff check でリンターを実行
    • 問題を報告するがワークフローは失敗させない

結果: ノンブロッキング(警告のみ)

3. セキュリティスキャン(Bandit)

  • 実行環境: Ubuntu latest
  • Python バージョン: 3.11
  • 内容:
    • セキュリティ脆弱性をスキャン
    • JSON レポートを生成
    • レポートをアーティファクトとしてアップロード

結果: ノンブロッキング(警告のみ)

4. 型チェック(mypy

  • 実行環境: Ubuntu latest
  • Python バージョン: 3.11
  • 内容:
    • 静的型解析を実行
    • 型不一致を報告
    • 早期にバグを検出する助けになる

結果: ノンブロッキング(警告のみ)

5. EPUB ビルド

  • 実行環境: Ubuntu latest
  • 依存ジョブ: pytest、lint、security(すべてパスする必要がある)
  • 内容:
    • scripts/build_epub.py を使い EPUB ファイルをビルド
    • EPUB が正常に生成されたか検証
    • EPUB をアーティファクトとしてアップロード

結果: ビルドが失敗するとワークフロー失敗(クリティカル)

6. サマリ

  • 実行環境: Ubuntu latest
  • 依存ジョブ: 上記すべて
  • 内容:
    • ワークフローサマリを生成
    • すべてのアーティファクトを一覧表示
    • 全体ステータスを報告

テストの書き方

テスト構造

テストは scripts/tests/ 配下に test_*.py のような名前で配置する:

# scripts/tests/test_example.py
import pytest
from scripts.example_module import some_function

def test_basic_functionality():
    """Test that some_function works correctly."""
    result = some_function("input")
    assert result == "expected_output"

def test_error_handling():
    """Test that some_function handles errors gracefully."""
    with pytest.raises(ValueError):
        some_function("invalid_input")

@pytest.mark.asyncio
async def test_async_function():
    """Test async functions."""
    result = await async_function()
    assert result is not None

テストのベストプラクティス

  • 記述的な名前を使う: test_function_returns_correct_value()
  • テスト 1 つにつきアサート 1 つ(可能な限り): 失敗のデバッグが容易
  • 再利用可能なセットアップにフィクスチャを使う: scripts/tests/conftest.py を参照
  • 外部サービスをモックする: unittest.mock または pytest-mock を使う
  • エッジケースをテストする: 空入力、None 値、エラー
  • テストを高速に保つ: sleep() と外部 I/O を避ける
  • pytest マーカーを使う: 遅いテストには @pytest.mark.slow

フィクスチャ

共通フィクスチャは scripts/tests/conftest.py に定義する:

# Use fixtures in your tests
def test_something(tmp_path):
    """tmp_path fixture provides temporary directory."""
    test_file = tmp_path / "test.txt"
    test_file.write_text("content")
    assert test_file.read_text() == "content"

カバレッジレポート

ローカルカバレッジ

# Generate coverage report
pytest scripts/tests/ --cov=scripts --cov-report=html

# Open the coverage report in your browser
open htmlcov/index.html

カバレッジ目標

  • 最低カバレッジ: 80%
  • ブランチカバレッジ: 有効
  • 重点領域: コア機能とエラー経路

pre-commit フック

本プロジェクトは pre-commit フックでコミット前に自動チェックを実行する:

# Install pre-commit hooks
pre-commit install

# Run hooks manually
pre-commit run --all-files

# Skip hooks for a commit (not recommended)
git commit --no-verify

.pre-commit-config.yaml で設定済みのフック:

  • Ruff フォーマッター
  • Ruff リンター
  • Bandit セキュリティスキャナ
  • YAML 検証
  • ファイルサイズチェック
  • マージコンフリクト検出

トラブルシューティング

ローカルでパスするが CI で失敗する

よくある原因:

  1. Python バージョンの違い: CI は 3.10、3.11、3.12 を使う
  2. 依存関係の不足: requirements-dev.txt を更新する
  3. プラットフォーム差異: パス区切り、環境変数
  4. 不安定なテスト: タイミングや順序に依存するテスト

解決策:

# Test with the same Python versions
uv python install 3.10 3.11 3.12

# Test with clean environment
rm -rf .venv
uv venv
uv pip install -r requirements-dev.txt
pytest scripts/tests/

Bandit が誤検知を出す

セキュリティ警告の中には誤検知がある場合もある。pyproject.toml で設定する:

[tool.bandit]
exclude_dirs = ["scripts/tests"]
skips = ["B101"]  # Skip assert_used warning

型チェックが厳しすぎる

特定ファイルで型チェックを緩める:

# Add at the top of file
# type: ignore

# Or for specific lines
some_dynamic_code()  # type: ignore

継続的インテグレーションのベストプラクティス

  1. テストを高速に保つ: 各テストは 1 秒以内で完了する
  2. 外部 API をテストしない: 外部サービスをモックする
  3. 隔離してテストする: 各テストは独立しているべき
  4. 明確なアサートを使う: assert x ではなく assert x == 5
  5. 非同期テストを扱う: @pytest.mark.asyncio を使う
  6. レポートを生成する: カバレッジ、セキュリティ、型チェック

リソース

テストへの貢献

PR を提出する際:

  1. 新機能には テストを書く
  2. ローカルでテストを実行: pytest scripts/tests/ -v
  3. カバレッジを確認: pytest scripts/tests/ --cov=scripts
  4. リンティングを実行: ruff check scripts/
  5. セキュリティスキャン: bandit -r scripts/ --exclude scripts/tests/
  6. テストが変わる場合は ドキュメントを更新

すべての PR にはテストが必要!🧪


テストに関する質問や問題は、GitHub Issue または Discussion を開いてほしい。