コンテンツへスキップ

テストと git オラクル

Pitmasterは正式なgitバイナリをオラクルとして扱います。gitがPitmasterの書き込み内容を受け入れ、Pitmasterがgitの書き込み内容を読み取れれば、動作は正しいと判断できます。テスト基盤はPitmasterリポジトリにあります。Composer パッケージに含まれるのはsrc/とbin/pitmasterのみです。以下のすべてを実行するには、composer installの後にクローンから実行してください。

テストスイート

コマンド 実行内容 gitが必要
composer test:unit PHPUnit unitスイート:独立したコンポーネントテスト いいえ
composer test:integration PHPUnit integrationスイート:同じリポジトリでPitmasterとgitを動作させる はい
composer test:oracle bin/test-regression:すべてのオラクルシナリオ はい
composer test PHPUnit(両スイート)とオラクル回帰テスト はい
./bin/verify-all composer verify:サポートの根拠、上流との差分、証明アーティファクト、ミューテーションのスモークテスト、composer audit、PHPStan、コーディング規約、composer test はい

CI では複数のPHPバージョンでユニットテストを実行し、統合テスト、オラクル回帰テスト(PITMASTER_TEST_JOBS=4)、サポート根拠と上流との差分のチェックも行います。

オラクルシナリオ

各シナリオはscenarios/<category>/配下のディレクトリです(合計761件。Pitmaster用に作成したものが156件、他の Git 実装から取り込んだものが605件)。

コード
scenarios/diff/diff-add-lines/
  scenario.json   # commands and expectations
  setup.sh        # builds the starting repository
  oracle/         # outputs captured from git

scenario.jsonには、gitと同等のPitmasterで実行するコマンドと、一致すべき内容が記載されています。

JSON
{
    "name": "diff-add-lines",
    "category": "diff",
    "operations": ["diff"],
    "oracle_commands": { "diff": "git -c color.ui=never diff" },
    "actual_commands": { "diff": "php \"{{ROOT}}/bin/pitmaster\" diff | perl -pe 's/\\e\\[[0-9;]*m//g'" },
    "expectations": { "exact_match": ["diff"], "fsck_clean": true }
}

実行時には、setup.shが構築したリポジトリをコピーし、別々のコピーでオラクルとPitmasterコマンドを実行して、出力、オブジェクト、参照、ログを比較します。さらにfsck_cleanでは、Pitmasterが書き込んだリポジトリをgit fsckが受け入れることも確認します。オラクルの出力がない場合や更新する場合はgitから取得し、それ以外の場合はコミット済みのoracle/ファイルを使います。

各シナリオが対象とするのは、セットアップで構築されたケースだけです。たとえば diff シナリオでは変更済みファイルを比較するため、Diffに記載された新規、削除済み、バイナリファイルの diff 出力の違いは検出されません。

シナリオの操作

シェル
./bin/test-scenario <name>                 # oracle, actual, compare for one scenario
./bin/test-regression                      # all scenarios
./bin/test-regression --jobs 4             # in parallel (or PITMASTER_TEST_JOBS=4)
./bin/test-regression --category diff      # one category
./bin/test-regression --fast               # pass/fail only, no reports

./bin/oracle <name>                        # capture git output for a scenario
./bin/oracle --refresh <name>              # re-capture, for example after a git upgrade
./bin/actual <name>                        # run Pitmaster and capture its output
./bin/compare <name>                       # compare oracle and actual output

複数の git バージョンを確認するには、PITMASTER_TEST_GIT_BINARIESに一覧を記載してスモークテストを実行します。

シェル
PITMASTER_TEST_GIT_BINARIES=/path/to/git-2.45:/path/to/git-2.46 \
  vendor/bin/phpunit --filter MultiGitVersionSmokeTest

上流テストコーパス

scenarios/upstream/配下のシナリオは、他の実装のテストスイートから取り込んだものです。内訳は git 独自のテストスイートが412件、isomorphic-git が71件、libgit2 が63件、go-git が46件、JGit が7件、dulwich が6件です。必要なフィクスチャツリーはfixtures/upstream/に同梱されているため、ネットワーク接続やマシン固有のパスがなくても、新規チェックアウトからコーパス全体を実行できます。セットアップスクリプトはPITMASTER_ROOT環境変数を通じてフィクスチャを見つけます。

composer verify:drift(bin/audit-upstream-drift)は、同梱された上流ケースすべてがシナリオに対応していることを確認します。

サポートマトリクス

リポジトリ内のSUPPORT_MATRIX.mdには、対象範囲内の git 機能とそのステータスがすべて記載されています。

ステータス 意味
DONE 宣言された互換性の範囲内で実装され、オラクルで検証済み
PART 一部実装済み
TODO 対象範囲内だが、未実装
DEFER 現時点では予定なし
N/A 対象範囲外

ファイルはconfig/support-matrix.jsonをもとにbin/support-matrixが生成します。config/support-evidence.jsonはDONEとPARTの各項目を具体的なテストとオラクルシナリオに紐付け、根拠のない項目があるとcomposer verify:evidenceが失敗します。CI はマトリクスを再生成し、コミット済みファイルと異なる場合は失敗します。

DONEの項目は、記録されたシナリオで git と一致することを意味します。これらのシナリオ以外では動作が異なる場合があり、既知の差異は課題トラッカーで管理されています。

ベンチマーク

パフォーマンス改善には、bench/配下のハーネスを使います。

シェル
composer bench -- --suite=smoke --runs=1 --warmups=0   # quick check
composer bench:baseline                                # full report
composer bench:compare -- <before.json> <after.json>   # compare two reports
composer bench:verify -- <report.json> bench/reports/smoke-thresholds.json

CI はスモークレポートをコミット済みのしきい値と照合します。