# バッチ設計書 35-run-tests.py

## 概要

本ドキュメントは、Sparkの統合テストスイートを実行するスクリプト `dev/run-tests.py` のバッチ設計書である。本スクリプトはPython3で記述されており、変更ファイルからテスト対象モジュールを自動判定し、ライセンスチェック、スタイルチェック、プロジェクトビルド、バイナリ互換性チェック、Scala/Python/Rの各テストスイートを包括的に実行する。

### 本バッチの処理概要

本スクリプトは、Apache Sparkプロジェクトの品質保証を包括的に行う統合テストオーケストレータである。

**業務上の目的・背景**：Apache Sparkはmulti-language（Scala/Java/Python/R）かつ多モジュール構成の大規模プロジェクトであり、変更に対する品質保証には多数のテストステップが必要である。本スクリプトは、ライセンスチェック（Apache RAT）、コードスタイルチェック（Scala/Java/Python/R）、プロジェクトビルド、バイナリ互換性チェック（MiMa）、ユニットテスト（Scala/Java）、PySparkテスト、SparkRテストを自動化された一連のワークフローとして実行する。GitHub Actionsとの統合機能を持ち、変更ファイルから影響を受けるモジュールを自動検出してテスト範囲を最適化する機能も備える。

**バッチの実行タイミング**：CI/CDパイプライン（GitHub Actions）でのPRレビュー時、および開発者がローカルでテストを実行する際に使用される。

**主要な処理内容**：
1. コマンドライン引数の解析（並列度、Pythonバージョン、テスト対象モジュール、タグフィルタ）
2. 環境のクリーンアップ（work/ディレクトリ、ivy2キャッシュの削除）
3. Java実行環境の検証
4. SparkRの事前インストール（R存在時）
5. ビルドツール・Scala/Hadoopプロファイルの決定
6. 変更ファイルからのテスト対象モジュール自動判定（GitHub Actions環境時）
7. テスト対象の環境変数設定
8. Scalaバージョン切り替え（SCALA_PROFILE指定時）
9. ライセンスチェック（Apache RAT）
10. コードスタイルチェック（Scala、Java、Python、R）
11. 依存関係テスト（test-dependencies.sh）
12. プロジェクトビルド（Maven/SBT）
13. バイナリ互換性チェック（MiMa、SBTのみ）
14. SBTアセンブリビルド・Unidocビルド
15. Scala/Javaユニットテスト実行
16. PySparkテスト実行（オプションでコードカバレッジ付き）
17. PySparkパッケージングテスト実行
18. SparkRテスト実行

**前後の処理との関連**：本スクリプトは内部的にchange-scala-version.sh（Scalaバージョン切り替え）、test-dependencies.sh（依存関係テスト）、check-license（ライセンスチェック）、lint-scala/lint-python/lint-r（スタイルチェック）等の多数のサブスクリプトを呼び出す。sparktestsupportパッケージのモジュール定義に依存してテスト対象を決定する。

**影響範囲**：ビルド成果物の生成（target/ディレクトリ）、ivy2キャッシュの操作、work/ディレクトリの削除が行われる。テスト実行中は大量のコンピュートリソースを消費する。

## バッチ種別

テスト（統合テストスイート実行オーケストレータ）

## 実行スケジュール

| 項目 | 内容 |
|-----|------|
| 実行頻度 | 随時（PR作成時・更新時 / 手動実行） |
| 実行時刻 | N/A |
| 実行曜日 | N/A |
| 実行日 | N/A |
| トリガー | GitHub Actions / 手動実行 |

## 実行条件

### 前提条件

| 条件 | 説明 |
|-----|------|
| Python3 | Python 3.x インタープリタが必要 |
| Java | JDK がインストール済みであること（JAVA_HOME設定済みまたはjavaがPATH上に存在） |
| Maven/SBT | ビルドツールが利用可能であること |
| sparktestsupport | dev/sparktestsupportパッケージが存在すること |
| R（SparkRテスト時） | Rがインストール済みであること（未インストール時はSparkRテストをスキップ） |

### 実行可否判定

- HOME環境変数が未設定または絶対パスでない場合はexit 1で終了
- javaが見つからない場合はexit 2で終了
- テスト対象モジュールが存在しない場合はテストをスキップして正常終了

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | デフォルト値 | 説明 |
|-------------|-----|-----|-------------|------|
| -p / --parallelism | int | No | 8 | テストスイートの並列実行数 |
| --python-executables | string | No | python3.11 | テストに使用するPythonインタープリタ（カンマ区切り） |
| -m / --modules | string | No | 全モジュール | テスト対象モジュール（カンマ区切り） |
| -e / --excluded-tags | string | No | なし | 除外するテストタグ（カンマ区切り） |
| -i / --included-tags | string | No | なし | 包含するテストタグ（カンマ区切り） |

### 入力データソース

| データソース | 形式 | 説明 |
|-------------|------|------|
| SCALA_PROFILE（環境変数） | string | Scalaバージョンプロファイル（例: scala2.13） |
| HADOOP_PROFILE（環境変数） | string | Hadoopバージョンプロファイル（デフォルト: hadoop3） |
| GITHUB_ACTIONS（環境変数） | string | GitHub Actions環境の検出 |
| APACHE_SPARK_REF（環境変数） | string | フォークリポジトリ時の差分基準ref |
| GITHUB_PREV_SHA（環境変数） | string | メインリポジトリビルド時の差分基準SHA |
| GITHUB_SHA（環境変数） | string | 現在のコミットSHA |
| SKIP_PYTHON（環境変数） | string | Pythonテストスキップフラグ |
| SKIP_R（環境変数） | string | Rテストスキップフラグ |
| SKIP_MIMA（環境変数） | string | MiMaチェックスキップフラグ |
| SKIP_UNIDOC（環境変数） | string | Unidocビルドスキップフラグ |
| SKIP_PACKAGING（環境変数） | string | パッケージングテストスキップフラグ |
| PYSPARK_CODECOV（環境変数） | string | PySparkコードカバレッジ有効化（"true"で有効） |
| dev/sparktestsupport/modules.py | Python | テストモジュール定義 |

## 出力仕様

### 出力データ

| 出力先 | 形式 | 説明 |
|-------|------|------|
| 標準出力 | テキスト | テスト実行ログ・結果 |
| target/ | ディレクトリ | ビルド成果物・テストレポート |

### 出力ファイル仕様

直接的なファイル出力はないが、ビルドツール（Maven/SBT）によりtarget/ディレクトリ配下にビルド成果物およびテストレポートが生成される。

## 処理フロー

### 処理シーケンス

```
1. コマンドライン引数解析
   └─ parallelism, python-executables, modules, excluded-tags, included-tags
2. 環境クリーンアップ
   └─ work/ディレクトリ削除
   └─ ivy2キャッシュ（org.apache.spark）削除
3. Java実行環境検証
   └─ JAVA_HOME/bin/java または PATH上のjavaを検出
4. SparkRインストール
   └─ Rが存在する場合、R/install-dev.shを実行
5. ビルド環境決定
   └─ ビルドツール: sbt（固定）
   └─ Scalaプロファイル: SCALA_PROFILE環境変数
   └─ Hadoopプロファイル: HADOOP_PROFILE環境変数（デフォルト: hadoop3）
   └─ テスト環境: github_actions または local
6. テスト対象モジュール決定
   └─ --modules指定時: 指定モジュールをフィルタ
   └─ GitHub Actions時: git diff から変更ファイルを検出し影響モジュールを判定
   └─ 未指定時: rootモジュール（全モジュール）
7. テスト環境変数設定
   └─ 変更モジュールの環境変数を設定
8. [SCALA_PROFILE指定時] Scalaバージョン切り替え
   └─ change-scala-version.sh呼び出し
9. [全モジュールテスト時] ライセンスチェック
   └─ Apache RATチェック（dev/check-license）
10. [全モジュールテスト時] スタイルチェック
    └─ Scala: dev/lint-scala
    └─ Java: dev/sbt-checkstyle
    └─ Python: dev/lint-python
    └─ R: dev/lint-r
11. [該当モジュール時] 依存関係テスト
    └─ dev/test-dependencies.sh
12. プロジェクトビルド
    └─ Maven: clean package -DskipTests
    └─ SBT: Test/package, connect/assembly
13. [SBTビルド時] バイナリ互換性チェック
    └─ dev/mima
14. [SBTビルド時] アセンブリビルド・Unidocビルド
    └─ assembly/package, unidoc
15. Scala/Javaユニットテスト実行
    └─ テストモジュールのsbt_test_goalsを実行
16. [Python変更あり] PySparkテスト
    └─ python/run-tests（コードカバレッジ対応）
    └─ PySparkパッケージングテスト（dev/run-pip-tests）
17. [R変更あり] SparkRテスト
    └─ R/run-tests.sh
```

### フローチャート

```mermaid
flowchart TD
    A[バッチ開始] --> B[引数解析・環境クリーンアップ]
    B --> C{Java検出OK?}
    C -->|いいえ| D[exit 2]
    C -->|はい| E[SparkRインストール]
    E --> F[ビルド環境・テスト対象決定]
    F --> G{テスト対象モジュールあり?}
    G -->|いいえ| H[テストスキップ・正常終了]
    G -->|はい| I{Scalaバージョン切替必要?}
    I -->|はい| J[change-scala-version.sh]
    I -->|いいえ| K{全モジュールテスト?}
    J --> K
    K -->|はい| L[ライセンスチェック]
    L --> M[スタイルチェック]
    K -->|いいえ| N[依存関係テスト]
    M --> N
    N --> O[プロジェクトビルド]
    O --> P[MiMa・アセンブリビルド]
    P --> Q[Scala/Javaテスト]
    Q --> R{Pythonテスト対象?}
    R -->|はい| S[PySparkテスト]
    R -->|いいえ| T{Rテスト対象?}
    S --> T
    T -->|はい| U[SparkRテスト]
    T -->|いいえ| V[バッチ終了]
    U --> V
```

## データベース操作仕様

### 操作別データベース影響一覧

データベース操作なし。本スクリプトはビルド・テスト実行のオーケストレーションのみを行う。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 1 | HOME未設定 | HOME環境変数が未設定または絶対パスでない | HOME環境変数を正しく設定する |
| 2 | Java不在 | javaが見つからない | JDKをインストールしJAVA_HOMEを設定する |
| 10 | 一般エラー | BLOCK_GENERAL | テスト実行ログを確認する |
| 11 | RATチェック失敗 | BLOCK_RAT | ライセンスヘッダを追加する |
| 12 | Scalaスタイル失敗 | BLOCK_SCALA_STYLE | Scalaコードのスタイルを修正する |
| 13 | Pythonスタイル失敗 | BLOCK_PYTHON_STYLE | Pythonコードのスタイルを修正する |
| 14 | Rスタイル失敗 | BLOCK_R_STYLE | Rコードのスタイルを修正する |
| 15 | ドキュメントビルド失敗 | BLOCK_DOCUMENTATION | bundler/jekyll環境を確認する |
| 16 | ビルド失敗 | BLOCK_BUILD | コンパイルエラーを修正する |
| 17 | MiMa失敗 | BLOCK_MIMA | バイナリ互換性の問題を解消する |
| 18 | Scala/Javaテスト失敗 | BLOCK_SPARK_UNIT_TESTS | テスト失敗の原因を調査・修正する |
| 19 | PySparkテスト失敗 | BLOCK_PYSPARK_UNIT_TESTS | PySparkテストの失敗を調査・修正する |
| 20 | SparkRテスト失敗 | BLOCK_SPARKR_UNIT_TESTS | SparkRテストの失敗を調査・修正する |
| 21 | Javaスタイル失敗 | BLOCK_JAVA_STYLE | Javaコードのスタイルを修正する |
| 22 | ビルドテスト失敗 | BLOCK_BUILD_TESTS | 依存関係テストの問題を解消する |
| 23 | pip テスト失敗 | BLOCK_PYSPARK_PIP_TESTS | パッケージングテストの問題を解消する |
| 24 | Scalaバージョン切替失敗 | BLOCK_SCALA_VERSION | change-scala-version.shの実行環境を確認する |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | 0（リトライなし） |
| リトライ間隔 | N/A |
| リトライ対象エラー | N/A |

### 障害時対応

各テストブロックにはERROR_CODESで定義されたユニークなエラーコードが割り当てられており、CURRENT_BLOCK環境変数で現在実行中のブロックを追跡できる。テスト失敗時はエラーコードから失敗したフェーズを特定し、対応する修正を行う。

## トランザクション仕様

| 項目 | 内容 |
|-----|------|
| トランザクション範囲 | N/A（テスト実行のみ） |
| コミットタイミング | N/A |
| ロールバック条件 | N/A |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定処理件数 | プロジェクト全体のテストスイート（モジュール指定時は部分的） |
| 目標処理時間 | 環境依存（全テスト実行で数時間、モジュール限定で数十分） |
| メモリ使用量上限 | ビルドツール・テスト実行の設定に依存 |

## 排他制御

同一SPARK_HOME上での同時実行は非対応。ビルド成果物やキャッシュディレクトリの操作が競合する可能性がある。

## ログ出力

| ログ種別 | 出力タイミング | 出力内容 |
|---------|--------------|---------|
| 開始ログ | 各テストブロック開始時 | ブロック名を区切り線付きで表示（72文字の=線） |
| 環境情報ログ | テスト環境設定時 | ビルドツール、プロファイル、テスト環境 |
| モジュール情報ログ | テスト対象決定後 | 変更検出されたモジュール一覧 |
| ビルドコマンドログ | ビルド実行時 | Maven/SBTの引数一覧 |
| テスト結果ログ | テスト実行中 | Maven/SBT/Pythonテストの出力 |

## 監視・アラート

| 監視項目 | 閾値 | アラート先 |
|---------|-----|----------|
| テスト終了コード | 0以外 | GitHub Actions / CI/CDシステム |
| テスト実行時間 | 環境依存 | GitHub Actions / CI/CDシステム |

## 備考

- ビルドツールはsbtに固定されている（build_tool = "sbt"）
- Hadoopプロファイルのデフォルトは"hadoop3"
- SBTビルド時のテスト出力フィルタにより、Resolving/Merging/Includingのログ行は非表示にされる
- PySparkテストでコードカバレッジが有効な場合（PYSPARK_CODECOV=true）、並列度が1に制限される
- GitHub Actions環境では、APACHE_SPARK_REFまたはGITHUB_PREV_SHAを使用してgit diffから変更ファイルを特定し、影響を受けるモジュールのみをテスト対象とする最適化が行われる
- rootモジュールが変更モジュールに含まれる場合は、全モジュールをテスト対象とする
- Scalaバージョン切り替えはSCALA_PROFILE環境変数が設定されている場合のみ実行される
- SBTでのMiMa実行後、アセンブリビルドが必要（SPARK-13294対応）
- doctestが_test()関数で実行され、失敗時はexit -1で終了する
