PHP单元测试利器 PHPUNIT深入用法(三)_php技巧
在本系列文章的前两篇中PHP单元测试利器:PHPUNIT初探和PHP单元测试利器:PHPUNIT深入用法(二)中,分别介绍了phpunit的基本用法和phpunit中的一些重要用法。
在本文中,笔者将为大家介绍phpunit中的两个高级概念和用法,尽管它不一定在你的日常单元测试中都用到,但理解和学会它们的用法对学习phpunit还是十分重要的。
Phpunit中的Annotations
如果有其他编程语言经验的开发者,应该对Annotations(注解)不陌生,其实在phpunit中,一个简单的如下面的一段注释也可以认为是Annotations:
<? php class MyTestClass extends PHPUnit_Framework_TestCase { /* * * Testing the answer to “do you love unit tests?” */ public function testDoYouLoveUnitTests() { $love = true ; $this -> assertTrue( $love ); } } ?>
可以看到,其实一段以/** **/为标记的文字,就可以认为是一种Annotations,但Annotations其实不单单是简单的注释,它是与一个程序元素相关联信息或者元数据的标注,它不影响程序的运行,但相关的软件工具或框架能够将其转换成特殊的元数据标记,以方便开发者以更少的代码去提高效率(比如通过。如果你熟悉Java,则会发现在Java SE 5中及象Spring等框架中,都大量使用了Annotations。
然而,由于php并不象Java那样是编译性语言,因此本身缺乏去解析Annotations的机制,但幸好phpunit去提供了这样的功能,我们以下面的代码为例:
<? php class MyMathClass { /* * * Add two given values together and return sum */ public function addValues( $a , $b ) { return $a + $b ; } } ?>
上面的只是一个简单的加法的例子,为此,我们使用Annotations去编写一个单元测试,在上两篇文章中,我们采用的是手工编写单元测试的方法,而本文中,将介绍使用phpunit命令行的方法,自动生成单元测试的框架,方法如下:
首先把上面的类保存为MyMathClass.php,然后在命令行下运行如下命令:
phpunit –skeleton-test MyMathClass
这时phpunit会自动生成如下的框架单元测试代码:
<? php require_once ' /path/to/MyMathClass.php ' ; /* * * Test class for MyMathClass. * Generated by PHPUnit on 2011-02-07 at 12:22:07. */ class MyMathClassTest extends PHPUnit_Framework_TestCase { /* * * @var MyMathClass */ protected $object ; /* * * Sets up the fixture, for example, opens a network connection. * This method is called before a test is executed. */ protected function setUp() { $this -> object = new MyMathClass; } /* * * Tears down the fixture, for example, closes a network connection. * This method is called after a test is executed. */ protected function tearDown() { } /* * * @todo Implement testAddValues(). */ public function testAddValues() { // Remove the following lines when you implement this test. $this -> markTestIncomplete( ' This test has not been implemented yet. ' ); } } ?>
可以看到,phpunit为我们生成的单元测试代码自动引入了原来的MyMathClass.php,同时也生成了setUp和tearDown方法,但唯一的核心单元测试代码是留给了我们编写。如果想在这个基础上更快速的生成我们想要的单元测试代码,要如何实现呢?没错,就是使用annotations!我们可以在原来的MyMathClass.php中加入如下的annotations。
<? php class MyMathClass { /* * * Add two given values together and return sum * @assert (1,2) == 3 */ public function addValues( $a , $b ) { return $a + $b ; } } ?>
然后再象上述一样在命令行运行:
phpunit –skeleton-test MyMathClass
这个时候会为我们生成如下的单元测试代码:
<? php /* * * Generated from @assert (1,2) == 3. */ public function testAddValues() { $this -> assertEquals( 3 , $this -> object -> addValues( 1 , 2 ) ); } ?>
看到了么?我们在原有的类中加入了注解@assert(1,2)==3,则phpunit自动为我们生成了正确的单元测试代码。当然,可以参考phpunit手册,学习到更多的关于@assert注解使用的规则。
下面再举一个例子来讲解annotations。假设我们的程序中的一个方法,只是仅需要数据的输入,并且不依赖XML或者数据库提供数据源,则为了测试这个方法,我们可能想到的一个方法是在程序中设置一个测试数据集去测试,但这里介绍一个比较简单的方法,就是使用注解@dataProvider,修改MyMathClass.php如下:
<? php /* * * Data provider for test methods below */ public static function provider() { return array ( array ( 1 , 2 , 3 ) , array ( 4 , 2 , 6 ) , array ( 1 , 5 , 7 ) ); } /* * * Testing addValues returns sum of two values * @dataProvider provider */ public function testAddValues( $a , $b , $sum ) { $this -> assertEquals( $sum , $this -> object -> addValues( $a , $b ) ); } ?>
可以看到,这里使用了注解@dataProvider,指明了测试用例的数据提供者是由provider方法返回的一个数组。所以在单元测试时,数组中的第0个元素则会赋值给$a,第1个元素则会赋值给b,第3个元素则会赋值给sum,可以看到,上面的第3个数组提供的数据是不能通过单元测试的,因为1+5不等于7。
此外,这里还简单介绍两个常用的annotations,比如@expectedException注解可以测试代码中是否正确抛出了异常,比如:
<? phprequire_once ' PHPUnit/Framework.php ' ; class ExceptionTest extends PHPUnit_Framework_TestCase{ /* * * @expectedException InvalidArgumentException */ public function testException() { } } ?>
这里就用注解的方法表示testException中必须抛出的异常类型为InvalidArgumentException。
另外一个是@cover注解。它的作用是标识phpunit只为类中的哪些方法或作用域生成测试代码,比如:
/* * * @covers SampleClass::publicMethod * @covers SampleClass::<!public> * @covers HelperClass<extended> */ public function testMethod() { $result = SampleClass :: method(); }
则phpunit只为SampleClass类中的publicMethod方法、SampleClass类中的所有非public声明的方法和HelperClass类或者它的其中一个父类产生单元测试代码。
Phpunit中的Mocking
在介绍Mocking前,先来看下为什么要使用Mocking。举一个数据库查询的例子,比如在某个应用中,如果要测试一个数据库的应用,但假如这个数据库的测试要耗费很多资源以及编写很复杂的单元测试的代码的话,可以尝试使用Mocking技术。举例说明如下:
<? php class Database { public function reallyLongTime() { $results = array ( array ( 1 , ' test ' , ' foo value ' ) ); sleep ( 100 ); return $results ; } } ?>
在上面这个例子中,我们模拟了一个数据库的操作,认为它需要运行很长时间。接下来我们编写其单元测试代码如下:
<? php require_once ' /path/to/Database.php ' ; class DatabaseTest extends PHPUnit_Framework_TestCase { private $db = null ; public function setUp() { $this -> db = new Database(); } public function tearDown() { unset ( $this -> db); } /* * * Test that the "really long query" always returns values */ public function testReallyLongReturn() { $mock = $this -> getMock( ' Database ' ); $result = array ( array ( 1 , ' foo ' , ' bar test ' ) ); $mock -> expects( $this -> any()) -> method( ' reallyLongTime ' ) -> will( $this -> returnValue( $result )); $return = $mock -> reallyLongTime(); $this -> assertGreaterThan( 0 , count ( $return )); } } ?>
注意看这段代码中有趣的地方,这里,使用了phpunit中的getMock对象方法,这里实际上是模拟生成一个Database类的“伪实例”了,这里生成了$mock这个mock对象实例,以方便接着的单元测试中用到。接下来的这三行代码
$mock -> expects( $this -> any()) -> method( ' reallyLongTime ' ) -> will( $this -> returnValue( $result ));
它们的含义为:无论方法reallyLongtime执行了多长时间,始终最后会直接返回$result这个数组的结果。这样,你就可以通过mocking技术很轻易地去实现在单元测试中,绕过某些复杂的逻辑部分,而节省大量的宝贵时间提高测试效率。
下面的这个例子,讲解的是Mocking技术中的更高级用法Mockbuilder。依然以上面的例子说明:
<? php public function testReallyLongRunBuilder() { $stub = $this -> getMockBuilder( ' Database ' ) -> setMethods( array ( ' reallyLongTime ' )) -> disableAutoload() -> disableOriginalConstructor() -> getMock(); $result = array ( array ( 1 , ' foo ' , ' bar test ' )); $stub -> expects( $this -> any()) -> method( ' reallyLongTime ' ) -> will( $this -> returnValue( $result )); $this -> assertGreaterThan( 0 , count ( $return )); } ?>
通过使用Mockbuilder,我们可以不用通过构造函数的方法去初始化一个mock对象。这段代码跟上一段代码的功能其实是一样的,只不过留意一下新的两个方法: disableAutoload和disableOriginalConstructor,其功能分别是禁止使用php的内置的autoload初始构造方法和禁止调用该类原有的构造函数。最后再看一个例子:
<? php /* * * Testing enforcing the type to "array" like the "enforceTypes" * method does via type hinting */ public function ttestReallyLongRunBuilderConstraint() { $stub = $this -> getMock( ' Database ' , array ( ' reallyLongTime ' )); $stub -> expects( $this -> any()) -> method( ' reallyLongTime ' ) -> with( $this -> isType( ' array ' )); $arr = array ( ' test ' ); $this -> assertTrue( $stub -> reallyLongTime ( $arr )); } ?>
在这里,我们使用了with方法,其中这个方法中指定了要传入的参数类型为array数组类型,最后这个断言是通过了,因为返回的的确是数组类型。
以上就是PHP单元测试利器 PHPUNIT深入用法(三)_php技巧的内容,更多相关内容请关注PHP中文网(www.php.cn)!

ホットAIツール

Undresser.AI Undress
リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover
写真から衣服を削除するオンライン AI ツール。

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

Video Face Swap
完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

人気の記事

ホットツール

メモ帳++7.3.1
使いやすく無料のコードエディター

SublimeText3 中国語版
中国語版、とても使いやすい

ゼンドスタジオ 13.0.1
強力な PHP 統合開発環境

ドリームウィーバー CS6
ビジュアル Web 開発ツール

SublimeText3 Mac版
神レベルのコード編集ソフト(SublimeText3)

ホットトピック









PHP 8.4 では、いくつかの新機能、セキュリティの改善、パフォーマンスの改善が行われ、かなりの量の機能の非推奨と削除が行われています。 このガイドでは、Ubuntu、Debian、またはその派生版に PHP 8.4 をインストールする方法、または PHP 8.4 にアップグレードする方法について説明します。

あなたが経験豊富な PHP 開発者であれば、すでにそこにいて、すでにそれを行っていると感じているかもしれません。あなたは、運用を達成するために、かなりの数のアプリケーションを開発し、数百万行のコードをデバッグし、大量のスクリプトを微調整してきました。

Visual Studio Code (VS Code とも呼ばれる) は、すべての主要なオペレーティング システムで利用できる無料のソース コード エディター (統合開発環境 (IDE)) です。 多くのプログラミング言語の拡張機能の大規模なコレクションを備えた VS Code は、

JWTは、JSONに基づくオープン標準であり、主にアイデンティティ認証と情報交換のために、当事者間で情報を安全に送信するために使用されます。 1。JWTは、ヘッダー、ペイロード、署名の3つの部分で構成されています。 2。JWTの実用的な原則には、JWTの生成、JWTの検証、ペイロードの解析という3つのステップが含まれます。 3. PHPでの認証にJWTを使用する場合、JWTを生成および検証でき、ユーザーの役割と許可情報を高度な使用に含めることができます。 4.一般的なエラーには、署名検証障害、トークンの有効期限、およびペイロードが大きくなります。デバッグスキルには、デバッグツールの使用とロギングが含まれます。 5.パフォーマンスの最適化とベストプラクティスには、適切な署名アルゴリズムの使用、有効期間を合理的に設定することが含まれます。

このチュートリアルでは、PHPを使用してXMLドキュメントを効率的に処理する方法を示しています。 XML(拡張可能なマークアップ言語)は、人間の読みやすさとマシン解析の両方に合わせて設計された多用途のテキストベースのマークアップ言語です。一般的にデータストレージに使用されます

文字列は、文字、数字、シンボルを含む一連の文字です。このチュートリアルでは、さまざまな方法を使用してPHPの特定の文字列内の母音の数を計算する方法を学びます。英語の母音は、a、e、i、o、u、そしてそれらは大文字または小文字である可能性があります。 母音とは何ですか? 母音は、特定の発音を表すアルファベットのある文字です。大文字と小文字など、英語には5つの母音があります。 a、e、i、o、u 例1 入力:string = "tutorialspoint" 出力:6 説明する 文字列「TutorialSpoint」の母音は、u、o、i、a、o、iです。合計で6元があります

静的結合(静的::) PHPで後期静的結合(LSB)を実装し、クラスを定義するのではなく、静的コンテキストで呼び出しクラスを参照できるようにします。 1)解析プロセスは実行時に実行されます。2)継承関係のコールクラスを検索します。3)パフォーマンスオーバーヘッドをもたらす可能性があります。

PHPの魔法の方法は何ですか? PHPの魔法の方法には次のものが含まれます。1。\ _ \ _コンストラクト、オブジェクトの初期化に使用されます。 2。\ _ \ _リソースのクリーンアップに使用される破壊。 3。\ _ \ _呼び出し、存在しないメソッド呼び出しを処理します。 4。\ _ \ _ get、dynamic属性アクセスを実装します。 5。\ _ \ _セット、動的属性設定を実装します。これらの方法は、特定の状況で自動的に呼び出され、コードの柔軟性と効率を向上させます。
