Files
hakorune/docs/development/roadmap/phases/phase-10.7/testing-plan.md
Moe Charm c13d9c045e 📚 Phase 12: Nyashスクリプトプラグインシステム設計と埋め込みVM構想
## 主な成果
- Nyashスクリプトでプラグイン作成可能という革命的発見
- C ABI制約の分析と埋め込みVMによる解決策
- MIR/VM/JIT層での箱引数サポートの詳細分析

## ドキュメント作成
- Phase 12基本構想(README.md)
- Gemini/Codex先生の技術分析
- C ABIとの整合性問題と解決策
- 埋め込みVM実装ロードマップ
- 箱引数サポートの技術詳細

## 重要な洞察
- 制約は「リンク時にC ABI必要」のみ
- 埋め込みVMでMIRバイトコード実行により解決可能
- Nyashスクリプト→C ABIプラグイン変換が実現可能

Everything is Box → Everything is Plugin → Everything is Possible!
2025-08-30 22:52:16 +09:00

7.0 KiB
Raw Blame History

Python Native Testing Plan

🎯 テスト戦略の全体像

「世界中のPythonコードがNyashのテストケース」という思想のもと、CPythonをオラクルとして使用する包括的なテスト戦略。

🧪 テストレベル

1. プラグインレベルテスト

PythonParserBox Tests

// plugins/nyash-python-parser-plugin/tests/parser_tests.rs
#[test]
fn test_parse_simple_function() {
    let parser = create_parser_box();
    let code = "def add(x, y): return x + y";
    let ast = parser.parse(create_string_box(code));
    
    assert_eq!(ast.get_type().to_string(), "Module");
    let functions = ast.get_children();
    assert_eq!(functions.length(), 1);
}

#[test]
fn test_parse_with_telemetry() {
    let parser = create_parser_box();
    parser.enable_telemetry(true);
    
    let code = r#"
def supported(): return 1
async def unsupported(): await foo()
    "#;
    
    parser.parse(create_string_box(code));
    let stats = parser.get_stats();
    
    assert_eq!(stats.get("total_functions"), 2);
    assert_eq!(stats.get("supported_functions"), 1);
}

PythonCompilerBox Tests

#[test]
fn test_compile_arithmetic() {
    let compiler = create_compiler_box();
    let ast = /* ... */;
    
    let mir = compiler.compile(ast);
    assert!(mir.is_ok());
    
    // MIR検証
    let module = mir.unwrap();
    assert!(module.has_function("add"));
}

2. Differential Testing Framework

// tests/differential/framework.nyash
box DifferentialTester {
    init { oracle, implementation, results }
    
    constructor() {
        me.oracle = new PythonRuntimeBox()  // CPython
        me.implementation = new NativeEngine()
        me.results = new ArrayBox()
    }
    
    test(code) {
        local oracle_result, impl_result
        
        // CPythonで実行
        oracle_result = me.oracle.eval(code)
        
        // Native実装で実行
        impl_result = me.implementation.exec(code)
        
        // 結果比較
        return me.compare(oracle_result, impl_result)
    }
    
    compare(expected, actual) {
        // 出力、戻り値、例外を比較
        local match = new MapBox()
        match.set("output", expected.output == actual.output)
        match.set("return", expected.return == actual.return)
        match.set("exception", expected.exception == actual.exception)
        return match
    }
}

3. テストケース生成

基本テストスイート

# tests/suites/phase1_tests.py

# 算術演算
def test_arithmetic():
    assert add(2, 3) == 5
    assert multiply(4, 5) == 20
    assert divide(10, 2) == 5.0  # true division

# 制御フロー
def test_control_flow():
    # if/else
    result = conditional_logic(True, 10, 20)
    assert result == 10
    
    # for/else
    found = search_with_else([1, 2, 3], 5)
    assert found == "not found"  # else節実行

# デフォルト引数の罠
def test_default_args():
    list1 = append_to_default(1)
    list2 = append_to_default(2)
    assert list1 is list2  # 同じリスト!

Fuzzing with Hypothesis

# tests/fuzzing/property_tests.py
from hypothesis import given, strategies as st

@given(st.integers(), st.integers())
def test_arithmetic_properties(x, y):
    """算術演算の性質をテスト"""
    # Commutativity
    assert add(x, y) == add(y, x)
    
    # Identity
    assert add(x, 0) == x
    
    # Differential testing
    native_result = native_add(x, y)
    cpython_result = x + y
    assert native_result == cpython_result

4. ベンチマークスイート

// benchmarks/numeric_suite.nyash
box NumericBenchmark {
    run() {
        local suite = new BenchmarkSuite()
        
        // Fibonacci
        suite.add("fibonacci", {
            "cpython": { return me.runCPython("fib.py") },
            "native": { return me.runNative("fib.py") }
        })
        
        // Matrix multiplication
        suite.add("matrix_mult", {
            "cpython": { return me.runCPython("matrix.py") },
            "native": { return me.runNative("matrix.py") }
        })
        
        return suite.execute()
    }
}

// 実行結果例
// fibonacci:
//   CPython: 1.234s
//   Native:  0.123s (10.0x faster)
// matrix_mult:
//   CPython: 5.678s
//   Native:  0.456s (12.4x faster)

5. 回帰テスト

# .github/workflows/python-native-tests.yml
name: Python Native Tests

on: [push, pull_request]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - name: Differential Tests
        run: |
          cargo test --package nyash-python-parser-plugin
          cargo test --package nyash-python-compiler-plugin
          
      - name: Coverage Report
        run: |
          ./tools/measure_compilation_coverage.sh
          # Expected output:
          # Phase 1 compatible files: 15%
          # Phase 2 functions: 40% compilable
          # Phase 3 functions: 10% compilable

📊 メトリクス収集

コンパイル成功率

// 自動計測ツール
box CoverageAnalyzer {
    analyze(directory) {
        local parser = new PythonParserBox()
        local compiler = new PythonCompilerBox()
        local stats = new MapBox()
        
        for file in directory.glob("*.py") {
            local ast = parser.parseFile(file)
            local result = compiler.compile(ast)
            
            stats.increment("total")
            if result.isOk() {
                stats.increment("success")
            } else {
                stats.increment("not_compilable")
                stats.record("unsupported", result.getError())
            }
        }
        
        return stats
    }
}

パフォーマンス追跡

-- メトリクスDB
CREATE TABLE benchmark_results (
    id SERIAL PRIMARY KEY,
    test_name VARCHAR(255),
    implementation VARCHAR(50),  -- 'cpython' or 'native'
    execution_time FLOAT,
    memory_usage BIGINT,
    timestamp TIMESTAMP,
    git_hash VARCHAR(40)
);

🚨 失敗時の診断

デバッグ情報収集

// コンパイル失敗時の詳細情報
compiler.enableDebug(true)
result = compiler.compile(ast)

if result.isErr() {
    local diag = compiler.getDiagnostics()
    print("Failed at: " + diag.get("location"))
    print("Reason: " + diag.get("reason"))
    print("AST node: " + diag.get("node_type"))
    print("Suggestion: " + diag.get("suggestion"))
}

トレース機能

NYASH_PYTHON_TRACE=1 ./target/release/nyash test.py
[Parser] Parsing function 'compute' at line 5
[Compiler] Compiling BinOp: Add at line 7
[Compiler] Unsupported: YieldFrom at line 15
[Error] Cannot compile function 'generator_func' - yield not supported

受け入れ基準

Phase 1完了

  • 基本テストスイート100%パス
  • Differential testing 100%一致
  • Phase 1対応コードの100%コンパイル成功
  • 10x性能向上数値計算ベンチマーク

各PR必須

  • 新機能の単体テスト
  • Differential testケース追加
  • ベンチマーク結果(該当する場合)
  • カバレッジ低下なし