在“如何提高 PHP 代碼的質量?”的前一部分中:我們設定了一些自動化工具來自動檢查我們的代碼,這很有幫助,但關于我們的代碼如何滿足業務需求并沒有給我們留下任何印象,我們現在需要創建特定代碼域的測驗,
1 單元測驗
最常見的測驗軟體的方法可能是撰寫單元測驗,它們的目的是測驗代碼的特定單元,基于這樣的假設:一切都按預期運行,為了能夠撰寫適當的單元測驗,我們的代碼應該遵循一些基本的設計規則,我們應該特別關注 SOLID 原則,
- 通過實作單一責任原則(我們的代碼應該只關注功能的單個部分),我們將確保在測驗期間,我們只會同時關注專案的一小部分
- 通過使用 Liskov 替換原則和依賴倒置原則,我們的代碼不會關心我們是否注入模擬依賴關系,只要它們實作了適當的介面
在單元測驗中,我們確實希望用模擬物件替換所有依賴的服務,因此我們一次只測驗一個類,但模擬是什么?它們是實作與其他物件相同的介面的物件,但它們的行為是受控的,例如,假設我們在創建一個價格比較服務,我們利用另一個服務來獲取當前的匯率,在測驗我們的比較器時,我們可以使用一個模擬物件來為特定的貨幣回傳特定的匯率,因此我們的測驗既不依賴也不呼叫真正的服務,
2 應該使用哪個框架?
有幾個好的框架可以達到這個目的,最常見的可能是 PHPUnit,在我的作業中,我發現使用行為方法來撰寫測驗會帶來更好的結果,并使我更急切地撰寫測驗,對于我們的專案,我們選擇 phpspec,
安裝程序相當簡單 - 只需使用:
$ php composer.phar require --dev phpspec/phpspec
然后,如果你在本文的第一部分中配置了 PHing,那么你可以在 build.xml 中添加構建目標:
<target name="phpspec"> <exec executable="bin/phpspec" passthru="true" checkreturn="true"> <arg line="run --format=pretty"/> </exec></target>...<target name="run" depends="phpcs,phpcpd,phan,phpspec"/>
然后,你必須為你想要測驗的每個服務類創建一個測驗類,讓 PHPSpec 非常容易使用的是模型創建,你只需使用嚴格的輸入,就可以將模擬物件宣告為測驗函式的引數,PHPSpec 會自動為你創建模擬,讓我們看一下代碼示例:
// spec/Domain/PriceComparatorSpec.php<?phpnamespace spec\Domain;use Domain\Price;use Domain\PriceConverter;use PhpSpec\ObjectBehavior;class PriceComparatorSpec extends ObjectBehavior{ public function let(PriceConverter $converter) { $this->beConstructedWith($converter); } public function it_should_return_equal() { $price1 = new Price(100, 'EUR'); $price2 = new Price(100, 'EUR'); $this->compare($price1, $price2)->shouldReturn(0); } public function it_should_convert_first(PriceConverter $converter) { $price1 = new Price(100, 'EUR'); $price2 = new Price(100, 'PLN'); $priceConverted = new Price(25, 'EUR'); $converter->convert($price2, 'EUR')->willReturn($priceConverted); $this->compare($price1, $price2)->shouldReturn(1); }}
這里有三個函式:
- let( ) - 它允許使用依賴來初始化服務
- 兩個 it_* 函式實作測驗,其中一種方法是使用模擬 $priceConverter 的方法實作 priceConverter 介面,該介面被注入到測驗物件的創建中,
你可以看到創建模擬非常容易,你所需要做的就是將它定義為測驗函式的引數,并通過指定在執行代碼時應該運行哪些函式來配置 mock,如果需要,你還可以設定回傳值,
所有測驗的方法都是從 $this 背景關系中運行的,你可以使用與模擬相同的語法來輕松地檢查它們的結果,
3 如何設定測驗?
Phpspec 有一個很好的檔案,但是我將嘗試向你展示一些在日常實踐中有用的基本用例,
構建測驗物件
一般來說,設定測驗物件的最簡單方法是呼叫 $this->beConstructedWith(…) 方法,該方法將所有應該傳遞給物件建構式的 params 作為引數,
如果你的物件應該使用工廠方法來創建,那么你可以使用 this?>beConstructedThrough(this?>beConstructedThrough(methodName,$argumentsArray)方法,
在模擬中匹配運行時引數
你會發現 phpspec 使用一種非常類似于人類的語法來配置模擬,例如,如果你想要檢查在運行時是否有一個模擬方法 someMethod 與引數“desired value”被呼叫,你可以在測驗中定義它,如下面的例子:
$mockObject->someMethod("desired value")->shouldBeCalled();
如果你想要測驗代碼的行為,當一些 mock 的函式回傳“some value”時,你可以通過呼叫來輕松地設定它:
$mockObject->someFunction("some input")->willReturn("some value");
有時我們并不真正關心傳遞給 mock 的確切引數,然后可以寫這段代碼:
use Prophecy\Argument\Token\AnyValueToken;...$mockObject->someFunction(new AnyValueToken())->willReturn(true);
有時你會關心一些引數,最好是寫一個檢查函式,它會告訴你是否正確地呼叫了一些方法,例如:
use Prophecy\Argument\Token\CallbackToken;...$checker = function (Message $message) use ($to, $text) { return $message->to === $to && $message->text === $text;};$msgSender->send(new CallbackToken($messageChecker))->shouldBeCalled()
匹配運行時例外
,在某些情況下,例外是代碼介面的一部分,你希望它們在特定的場景被拋出,你可以通過撰寫以下代碼來完成這項作業:
$this->shouldThrow(\DomainException::class)->during('execute', [$command, $responder]);
傳給 during() 的第一個引數是將要呼叫的方法的名稱,第二個引數是將傳遞給我們的方法的引數陣列,
5 在哪里可以找到更多的例子?
在本文中,我們只介紹了一些基本的用例,請參考 phpspec 的檔案,以找到更多的示例,這些示例將使你的測驗代碼變得漂亮!
代碼覆寫率
PHPSpec 附帶了擴展子系統,它允許例如創建代碼覆寫率報告,如果您想要檢查在測驗中執行了多少代碼,它們是很有幫助的,
你可以通過以下來安裝這個擴展:
$ php composer.phar require --dev leanphp/phpspec-code-coverage
然后通過創建 phpspec 來啟用它,yml 檔案內容:
1 extensions: LeanPHP\PhpSpec\CodeCoverage\CodeCoverageExtension: ~
默認情況下,這個擴展會使用 PHP 的 Xdebug 擴展生成代碼覆寫率資訊,但是 PHP 的本機除錯器 - phpdbg 會更快速一些:
$ phpdbg -qrr phpspec run
現在,你可以在 build 中更改 phpspec 的構建目標,xml:
<target name="phpspec"> <exec executable="phpdbg" passthru="true" checkreturn="true"> <arg line="-qrr bin/phpspec run --format=pretty"/> </exec></target>...<target name="run" depends="phpcs,phpcpd,phan,phpspec"/>
報告在覆寫率 / 目錄中生成,作為漂亮的 HTML 頁面,可以瀏覽以檢查測驗覆寫率,
推薦閱讀:
教你如何提高 PHP 代碼的質量
如何提高 PHP 代碼的質量?第三:端到端 / 集成測驗
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/100300.html
標籤:PHP
上一篇:教你如何提高 PHP 代碼的質量
