SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

PHPカンファレンス実行委員プレゼンツ PHPの最前線

身近なツールで始めるコードリーディング入門~「PHPUnit」の場合

PHPカンファレンス実行委員プレゼンツ PHPの最前線 第2回


  • X ポスト
  • このエントリーをはてなブックマークに追加

どのようにテストが実行されているか

 では、PHPUnitの内部ではどのようにテストが実行されているのでしょうか?

 PHPUnitをインストールすると、プロジェクト内のvendor/binディレクトリにphpunitというスクリプトファイルが配置されます。このファイルを用いてテストを実行するプロジェクトも多いでしょう(実際に私もこのスクリプトファイルを利用しました)。

 まずこのスクリプトファイルはどこに存在し、どのようなロジックが動いているのかを見ていきます。

 ここからはローカルマシンにPHPUnitをGitHubからクローンしてコードを読みます。

json:composer.json
"bin": [
    "phpunit"
]

 上記はPHPUnitのcomposer.jsonの一部です。binセクションの指定により、vendor/bin/phpunitを実行するとPHPUnitのプロジェクト内にあるphpunitスクリプトファイルが呼び出されることになります(参照:Composerのドキュメント)。

 次はこのスクリプトファイルの中で、どのような処理が行われているのかを詳しく見ていきます。

 PHPのバージョンや拡張機能の確認・Composerの依存関係のセットアップなど、さまざまなチェックや準備が行われた後に以下の記述があります。

exit((new PHPUnit\TextUI\Application)->run($_SERVER['argv']));

 つまりvendor/bin/phpunitを実行すると、PHPUnit\TextUI\Applicationクラスのrunメソッドがエントリポイントとして呼び出されます(以後Applicationクラスと表現します)。これにより、runメソッドの中身を読めば実際にどのような処理が行われるのかを把握することができます。

 本記事内でもApplicationクラスを基点にしてコードリーディングをしていきます。

勘所を掴む

 とはいえ、読んでいくといっても全てを網羅して読んでいくのは少々骨が折れます。ある程度アタリをつけてみましょう。

 今回、私は'.'という文字列で検索をかけることにしました。どこかに.Fが文字列として定義されているはずと思ったためです。勘所は当たり、ProgressPrinterクラスのprintProgressForSuccessメソッドを見つけました。

// 「'.'」で文字列検索して見つけたクラス
// PHPUnit\TextUI\Output\Default\ProgressPrinter\ProgressPrinter
private function printProgressForSuccess(): void
{
    $this->printProgress('.');
}

// 1-1
// PHPUnit\TextUI\Output\Default\ProgressPrinter\ProgressPrinter
private function printProgress(string $progress): void
{
    $this->printer->print($progress);

    // ...略...
}

// 1-2
// PHPUnit\TextUI\Output\DefaultPrinter
public function print(string $buffer): void
{
    assert($this->isOpen);

    fwrite($this->stream, $buffer);
}

 中身を辿っていくと、ProgressPrinterクラスのprintProgressメソッドの中で$this->printerprintメソッドを呼び出しています(1-1)。

 $this->printerを生成している箇所を辿ると$this->printerDefaultPrinterクラスになっていそうです。

 そしてDefaultPrinterクラスのprintメソッドの中を見てみると、fwrite関数を見つけました(1-2)。

 これにより検索で見つけたProgressPrinterクラスのprintProgressForSuccessメソッドが、実際に書き込みをしている処理ということが確定しました。

 またProgressPrinterクラスにある以下メソッドたちも、printProgressForSuccessメソッドと同様にDefaultPrinterprintメソッドが呼ばれていました。

  • printProgressForSkipped(「S」をprintする)
  • printProgressForIncomplete(「I」をprintする)
  • printProgressForNotice(「N」をprintする)
  • printProgressForDeprecation(「D」をprintする)
  • printProgressForRisky(「R」をprintする)
  • printProgressForWarning(「W」をprintする)
  • printProgressForFailure(「F」をprintする)
  • printProgressForError(「E」をprintする)

 ということで、実際に標準出力している部分のロジックは見つけることができました。

TestFinishedSubscriberクラスの内部処理

 コードをさらに読むと、TestFinishedSubscriberクラスのnotifyメソッドが呼ばれることで進捗結果の出力処理が行われるようです。単にメソッドが呼び出されるだけではなく、巧妙に設計されていることが伺えます。

 では、TestFinishedSubscriberクラスがどのように使われているのか、紐解いていきましょう。

次のページ
TestFinishedSubscriberクラスの使われ方

関連リンク

この記事は参考になりましたか?

  • X ポスト
  • このエントリーをはてなブックマークに追加
PHPカンファレンス実行委員プレゼンツ PHPの最前線連載記事一覧
この記事の著者

asumikam(アスミ)

 株式会社リンケージのWebアプリケーションエンジニア。PHPカンファレンス小田原 実行委員長。 カンファレンスへの参加をきっかけに、日々の学びや失敗談をアウトプットするのが好きになり、ついにはカンファレンス主催まで至る。主にPHP系やアジャイル系のカンファレンスで登壇。

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

  • X ポスト
  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/20106 2024/09/10 17:59

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング