akbピンボールマシン

RAKUS Developers Blog | ラクス エンジニアブログ

株式会社ラクスのITエンジニアによる技術ブログです。

PHPコードを「テストしない」方法

この記事(shi)は 6日目(mu)の記事(shi)です。

こんにちは、配(pei)配(pei)メール開発エンジニアの takaram です。

私のチームでは、最近行ったやバージョンアップ対応において、あえて修正したコードをテストしないという対応を取ることがありました。この記事(shi)ではこれについてお話(hua)しします。

テストしないでリリースする方法

いきなりネタバレしてしまうと、これはモノタロウさんのテックブログで紹介されていた以下の記(ji)事のn番煎(jian)じです。

要約すると「コードの修正前後(hou)で抽象 (AST) が変化しなければ、コードの動(dong)作(zuo)も変わらないはずなのでテスト不要と判断(duan)できる」ということです。 元(yuan)記事(shi)はでやっていますが、考え方自(zi)体は他の言語でも使えるので、実際にでやってみたという記事(shi)もあります。

上(shang)記2記事(shi)は拡張(zhang)モジュールのを利(li)用していますが、拡張(zhang)モジュールのインストールは面(mian)倒であることが多(duo)いので、今回(hui)はを使うことにします。

なお、これ以降「ファイルの」という表現を「プログラムのASTの」という意味(wei)で使います。

使いどころ

一括コードフォーマット

_CodeSnifferや-cs-fixerでプロジェクト全(quan)体(ti)に自動(dong)修(xiu)正をかけた場合、対象ファイルが数(shu)千を超(chao)えることもあります。これを全(quan)て手動(dong)でテストするのは非(fei)現実的でしょう。

インデントやの周りの空白(bai)の修(xiu)正であればASTには影響がないため、この手法を使うことができます。

${}による文字列補間の修正

PHP8.2で"${var}"形式で文字列に変数を埋め込む文字列補間が非推奨になりました。 まだ使えなくなるわけではないですが、"{$var}"形式に書き換える必要があります。

これら2つの文字(zi)列は同等のASTが出力されるため、ASTのが変わりません。

やり方

まず適当なリに、ファイルのを出力するを作ります。ファイルはこんな感じです。

<?php
declare(strict_types=1);

use PhpParser\NodeDumper;
use PhpParser\ParserFactory;

require_once __DIR__ . '/vendor/autoload.php';

$parser = (new ParserFactory)->create(ParserFactory::PREFER_PHP7);
$dumper = new NodeDumper();
foreach (array_slice($argv, 1) as $file) {
  try {
    $ast = $parser->parse(file_get_contents($file));
  } catch (Error $error) {
    echo "Parse error: {$error->getMessage()}\n";
    exit(1);
  }
  $hash = md5($dumper->dump($ast));
  echo "{$hash}\t{$file}\n";
}

以下では、このファイルを/tmp/php-ast-diff/ast_md5.phpに置いているとして進めます。

次に、nikic/-Parserをインストールします。バージョンはv4.x系を利用(yong)します。

$ cd /tmp/php-ast-diff
$ composer require nikic/php-parser:'^4.17'

ここまでで準備は完了です。試しに、ast_md5.php自身のを出力(li)させてみましょう。 以(yi)下のように出力(li)されると思います。

$ php ast_md5.php ast_md5.php
7042836d533afb828822f59454abb39f    ast_md5.php

これ以降は、を計算したいファイルのあるで作業します。
また、mainブランチからrefactorブランチを切ってコードを修(xiu)正したと仮定(ding)します。

まず、修正したファイルを一覧で出しておきます。

$ git diff --name-only main...refactor > changed_files

次に、修正前のファイルのを出力します。
mainブランチ上(shang)だと、refactorブランチ作成後にマージされた他(ta)の変(bian)更が入(ru)っている場合があるため、ブランチの分岐の根元に当たるコミットにチェックアウトします。

$ git checkout "$(git merge-base main refactor)"
$ xargs php /tmp/php-ast-diff/ast_md5.php < changed_files > hash_before

次に修正後(hou)のファイルのを出(chu)力します。

$ git checkout refactor
$ xargs php /tmp/php-ast-diff/ast_md5.php < changed_files > hash_after

最後にhash_beforehash_afterをdiffコマンド等で比較し、差分(fen)がなければが変(bian)わっていないと分(fen)かります。

最後に

特にが十分にないプロダクトでは、は往々にして大変になりがちです。
今(jin)回紹(shao)介した方法であればすぐにでも取り入れられるので、ぜひ活(huo)用してみてください!

Copyright © RAKUS Co., Ltd. All rights reserved.