ホームページ  >  記事  >  バックエンド開発  >  Web サイド PHP コード関数カバレッジ テスト ソリューション、php Coverage_PHP チュートリアル

Web サイド PHP コード関数カバレッジ テスト ソリューション、php Coverage_PHP チュートリアル

WBOY
WBOYオリジナル
2016-07-12 09:05:40908ブラウズ

Web側PHPコード関数カバレッジテストソリューション、phpカバレッジ

1. コードカバレッジについて

コード カバレッジの測定には、行カバレッジ、関数/メソッド カバレッジ、クラス カバレッジ、ブランチ カバレッジなど、さまざまなレベルがあります。コード カバレッジは、テストの品質を測定するための重要な基準でもあります。ブラック ボックス テストの場合、テスト ケースがシステム内のコードのすべての行を実際に実行したかどうかがわからない場合は、常にテストの整合性を無視する必要があります。 。したがって、業界には、ほぼすべてのプログラミング言語に対して独自のコード カバレッジ ソリューション セットがあります。世界で最も美しい言語である PHP も例外ではありません。 PHPUnit と Spike PHPCoverage は、xdebug に基づいたコード カバレッジ テスト ソリューションのセットを提供します。この記事では、私が遭遇した特定のビジネス シナリオに基づいて、PHP コード関数カバレッジ テストのための私独自のソリューションについて説明します。

2. 事業背景

オンラインで Web サイトを開発し、それを機能テストのためにビジネス テストの同僚に引き渡すとします。では、どうやってテストしたのでしょうか?通常、開発者が Web サイトを展開し、その後テスターが異常な使用状況を含むすべてのオンライン機能を試します。ビジネステストの場合、すべての機能ポイントをテストし、異常な使用状況をすべて検出できれば完了です。しかし、開発に関しては、私が書いたすべてのコードが実行されたかどうかのほうが気になります。非常に特殊な状況でのみトリガーできるコードがあり、そのような状況を測定したことがないのでしょうか?この時点で、コード カバレッジが役立つ必要がある場合があります。

実際、私は最初にカバレッジをテストするために xdebug を考えましたが、これには次のように 2 つまたは 3 つの関数しか必要としません:

リーリー

xdebug が提供するインターフェイスは、ライン カバレッジをテストするために使用できます。これは要件を満たしていますか?実際、行カバレッジの粒度は、実際のプロジェクトでは、開発者がコードを微調整する可能性があります。たとえば、このテストでは A.php ファイルの 10 行目までを実行しましたが、ある日、A.php を微調整して、A.php の 9 行目と 10 行目にさらに 2 行のコードを追加しました。その結果、元の10行目は12行目になってしまい、xdebugの行カバレッジ情報には行番号しか記録されていませんでした…前のデータは不正確ではないでしょうか? 。 。慎重に検討した結果、機能範囲は適切な粒度であると思います。比較的成熟したプロジェクトでは、大規模な機能変更が行われることはほとんどありません。しかし、問題は、xdebug が関数カバレッジのためのインターフェイスを提供していないことです。

つまり、私たちが今遭遇しているシーンは次のとおりです:

【1】あるテストでカバーされているすべての機能のリストを測定し、このプロジェクトにどれだけの機能があるかを知り、カバー率が十分に高いかどうかを計算したいと考えています。

【2】テストが完了したら、コードカバレッジを視覚化するためにカバレッジレポートを生成する必要があります。

【3】完全なテストプロセスは次のとおりです:

インストルメンテーションとは、テスト実行前の準備作業を意味します。

3. 機能カバレッジソリューション

(1)原則

xdebug は本質的にライン カバレッジのサポートを提供するため、関数カバレッジを自分で計算する必要があります。関数カバレッジには 2 つのデータが必要です。1 つは実行される関数、もう 1 つはファイル内の関数の総数です。

ファイル内の関数の総数。すべての関数を実行することは不可能であるため、この部分はコードの静的スキャンによってのみ実現できます。 C++ や Java の場合は、字句解析ツールが必要になるかもしれませんが、最も美しい言語である PHP の前では、それほど複雑なことはまったく必要ありません。 PHP4.3 以降、PHP Zend Engine には、開発者がソース コードの字句解析を実行できるようにするトークナイザー機能が組み込まれています。 PHP で関数を定義するときに、対応する字句規則を見つけるだけでよく、指定された PHP ファイル内のすべての関数を簡単に取得できます。

トークナイザーによって定義されたインターフェースも非常にシンプルです:

リーリー

この関数はファイル解析を実行し、PHP ソース コードをトークンで構成される配列に分割します。

リーリー

整数形式のトークンを文字列形式に変換します。 C言語のstrerror関数に似ています。 トークナイザーを使用すると、PHP 関数で定義されたルールと形式に従って有限状態マシンを設計し、すべての関数の分析を完了できます。コードのこの部分の比較的単純なバージョンを作成し、参照のみのために個別に取り出しました: PHPFunctionParser

求函数覆盖率的另外一个难点在于获取被执行的函数列表。这地方让我们走了一些弯路。一开始一个最简单的办法,我们既然通过xdebug拿到被执的行,可以通过行号来反推此行属于哪一个函数。然而每一次的请求获取的行号信息量是非常大的,如果一个求情执行了1000行,那就要进行1000次判断,效率上会比较差。调研了一番之后,发现xdebug提供了function trace的功能,可以把一次请求中的函数调用关系获取到,只不过拿到了函数名字,却没办法得到它所在的文件。于是,再次调研一番,发现了Reflection,给定方法名和类名,可以反推出来它在哪个文件中定义。于是我们使用function trace把函数调用关系暂存在一个临时文件中,然后通过文件解析,拿到执行的函数名(如果是类方法,则是“类名::函数名”的形式),再通过reflection机制反推出定义这个函数的文件即可。再次体会到了世界上最美语言的强大之处。

(2)插桩

为了降低使用门槛,我们尽可能少地改变PHP源代码为好。xdebug收集信息的原理是分别调用xdebug_start_code_coverage和xdebug_stop_code_coverage来控制覆盖率信息收集的开始和结束,因此不可避免地要改变源代码。此处我们的解决办法是,将xdebug_stop_code_coverage通过register_shutdown_function注册为php程序结束前必须要跑的一段程序(类似C语言的atexit函数),将其封装到一个文件中,然后在源代码第一行require这个文件即可。如果你的PHP框架是CodeIgniter这种所有请求都有一个统一入口index.php的框架,那就只需要改变这一个文件即可,对源代码只有一行的改动!实际上,目前基本上所有的PHP框架,都是以一个index.php文件作为所有请求的入口。

我们对源代码的改动只有入口文件index.php的第一行加入了一句话:

<?php <span>require_once</span> "/file/path/to/phpcoverage.php"; ?>

而phpcoverage.php核心代码逻辑大致如下:

<?<span>php
 &hellip;&hellip;</span>
<span>function</span><span> xdebugPhpcoverageBeforeShutdown(){
 &hellip;&hellip;</span>
 <span>$lineCovData</span> =<span> xdebug_get_code_coverage();
 xdebug_stop_code_coverage();
 &hellip;&hellip;</span><span>
 xdebug_stop_trace();
 &hellip;&hellip;</span><span>
}
</span><span>register_shutdown_function</span><span>(&lsquo;xdebugPhpcoverageBeforeShutdown&rsquo;);
</span><span>&hellip;&hellip;
xdebug_start_trace(&hellip;&hellip;</span><span>);
xdebug_start_code_coverage();<br />//备注:上面省略号表示非关键代码,这里就不展示了</span>

(3)信息存储

我们的函数覆盖率测试有了思路,使用xdebug的function trace获取一次请求中所有函数的调用关系,得到执行过的所有函数,输出到文件中,通过文件解析和reflection获得被执行的函数名和该函数所在文件。将这些信息存入数据库或文件即可。

之前试用Spike的时候,我们发现这些信息以xml格式存入文件,数据冗余度很高,导致几个测试下来,文件已经非常大了。这显然不是我们想看到的。因此在数据存储的时候,我们直接将数据做json格式的序列化,字符串形式存在文件中,大大减少了文件大小。与此同时,我们再通过请求来源的IP和日期作为分隔,分别存储不同的文件。这样,来自每个机器每天的请求数据都能一目了然,向着“精准”的方向又迈进了一步,可以对测试人员的每个请求做精确的监控。下图是我们在业务实践中搜集的部分数据文件截图:

这样,来自任何一个IP的每一次Web请求,它所覆盖的行和函数信息,都会被记录到文件中。对于一般的项目测试中,也就只有几个测试人员在使用,所以不需要考虑一些性能问题。

4. 报告生成

上面讲了生成覆盖率数据的原理,不过我们至此获得的只是一份份的数据文件,如何汇总成一份完整的报告呢?这就需要我们自己来写一段脚本解析刚才生成的数据文件了。我们的做法是借鉴了开源工具spike phpcoverage的模版,并加入自己的代码逻辑,特别是加入了该工具所不具有的函数覆盖率统计数据。我们自己测试的web页面生成的报告如下:

图中可以看到每个文件的行覆盖率,函数覆盖率,还有总的覆盖率统计数据。如果需要更精确的数据,可以点进文件连接,查看到底覆盖的是哪些代码行(蓝色为覆盖,红色为未覆盖):

5. 总结

ビジネステストでWebテストを行う場合、コードカバレッジはテスト品質の重要な指標です。テストの実行後に、コードのどの行が実行され、どの行が実行されなかったのかを正確に確認できるように、この方法を使用したいと考えています。テストケースが実行されなかった原因を分析し、テストケースを改善します。このツールを使用するプロセスも非常に簡単です。インストルメンテーション => テスト => データの収集 => レポートの作成です。また、このソリューションはビジネス コードへの影響を最小限に抑え、コードを 1 行変更するだけで済みます。途中で問題が発生しても、すぐにコードを元の状態に戻すことができます。テストを安心して行うことができ、開発も安心して行えます。

ただし、最後に強調しなければならないのは、すべてのコードをカバーしてもテストが完了したことを意味するわけではないということです。しかし、それがカバーされていない場合、それは不完全でなければなりません。したがって、このソリューションの最大の意義は、テスト中に欠落しているコードを発見し、問題を発見できることです。実際、これは新入社員がプロジェクトのコード構造全体を理解するのにも役立ちます。ブラウザー要求ごとにサーバー上のどのコードが実行されているかを明確に知ることができます。

www.bkjia.com本当http://www.bkjia.com/PHPjc/1068247.html技術記事ウェブサイド PHP コード関数カバレッジ テスト ソリューション、PHP カバレッジ 1. コード カバレッジに関しては、行カバレッジ、関数/メソッド カバレッジ、クラス カバレッジなど、コード カバレッジの測定には多くのレベルがあります...
声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。