我總感受 PHP 的開發者們並無對 PHP 的質量有所追求,多是由於 PHP 的機制問題吧,讓大部分的開發者總覺得瀏覽器訪問就沒有問題,因此不少時候,作 PHP 開發的,就沒有單元測試的這些概念了。能不能有點追求?php
我我的也是 PHP,但同時我也比較討厭那些完事就算了的開發者,做爲一個開發者,或者說是一個產品的經手人,就應該用心地去作好每一個細節,一次比一次要更好。html
可是作單元測試,質量檢查,是須要必定的時間和人力投入的,但我敢保證地說,你花時間投入的,絕對不會是沒用的,必定對你,對項目來講,是一個質的提高,只要你肯投入時間用心去作。mysql
屁話說太多了,那接下來簡單講講 phpunit 吧,官網。sql
由於咱們習慣用 composer
,因此咱們也使用 composer
安裝吧。數據庫
$ composer require phpunit/phpunit -vvv
安裝完 phpunit,bin 執行腳本會建立在 vendor/bin
目錄下,命名爲 phpunit
, 執行 php vendor/bin/phpunit
執行測試腳本json
配置 bin 目錄:bootstrap
{ "config": { "bin": "bin" } }
配置 bin 目錄產生的目錄,執行 php bin/phpunit
腳本開始測試。數組
phpunit
能夠配置在當前執行路徑添加一個配置文件 phpunit.xml.dist
或者 phpunit.xml
,內容以下:瀏覽器
<phpunit colors="true" bootstrap="./vendor/autoload.php" > <testsuites> <testsuite> <directory>dir1</directory> </testsuite> <testsuite> <directory>dir2</directory> </testsuite> </testsuites> </phpunit>
能夠經過配置目錄和初始化信息,讓腳本自動執行對應的測試用例。composer
使用 PHPUnit 建立咱們的測試用例:
<?php class DemoTest extends PHPUnit_Framework_TestCase { public function testPushAndPop() { $stack = []; $this->assertEquals(0, count($stack)); array_push($stack, 'foo'); $this->assertEquals('foo', $stack[count($stack)-1]); $this->assertEquals(1, count($stack)); $this->assertEquals('foo', array_pop($stack)); $this->assertEquals(0, count($stack)); } }
類名須要以 *Test 結尾,繼承 PHPUnit_Framework_TestCase
。須要測試的方法須要一 test 開頭,代表是一個測試方法。
通常經常使用測試無非就是 "斷言",說白了,就是看看產生的結果是否是符合預期,若是是,那就證實,已經測試經過,不然,失敗,說明邏輯處理,存在必定的差別,致使不符合預期。
更多的測試使用方法請看官網用例: PHPUnit
當咱們的測試對象繼承了 PHPUnit 後,初始化方法就須要使用它自己提供的 setUp 方法,表明類初始化,能夠在初始化方法中初始化一些資源,或者加載。
除了以上基礎的測試以外,關鍵一點應該在動態的數據,須要去測試嗎,若是須要,那應該怎麼去測試? 生產環境,也須要這樣測試? 這個曾經困惑這個人問題,已經解開。
解答:
composer 中,有 --no-dev 選項,用來部署生產環境,避免測試環境的數據或者代碼跑在了生產環境下。而且生產環境上數據庫操做是沒有很高權限的操做,要是有的話,你得回去面壁思考一下了。
dbunit 每次測試都重置數據,其實在生產環境下,就重置不了了,第一個是composer --no-dev 已經沒有執行權利了,要是有,數據庫已經不容許清空操做了。
要是生產環境不須要這些東西,那麼應該怎麼測試。其實須要有一個模擬生產環境的測試環境,去模擬生產環境測試,當全部測試都OK沒有問題,那麼就能夠發佈到生產環境上,要是嚴格一些,生產環境也是須要一輪測試。
$ composer require phpunit/dbunit -vvv
更多測試可看: 數據庫測試
<?php class DBTest extends PHPUnit_Extensions_Database_TestCase { /** * @return PHPUnit_Extensions_Database_DB_IDatabaseConnection */ public function getConnection() { $pdo = new PDO('mysql::dbname=test;host=127.0.0.1', 'user', 'pass'); return $this->createDefaultDBConnection($pdo, ':memory:'); } /** * @return PHPUnit_Extensions_Database_DataSet_IDataSet */ public function getDataSet() { return $this->createFlatXMLDataSet(dirname(__FILE__).'/_files/guestbook-seed.xml'); } }
getConnection
方法是獲取數據庫鏈接,繼承數據庫測試後,必須實現的一個方法,而且須要返回 PHPUnit_Extensions_Database_DB_IDatabaseConnection
對象,能夠仿照上述寫法便可。
getDataSet
方法是數據集,在建立數據庫測試的時候,自動填充,測試,和刪除。他執行的流程是,每一個測試用例,都會填充一次,以保證不會被其餘測試用例影響。噹噹前測試用例測試完成後,會 truncate
掉填充的數據。
數據集支持挺多種方法,能夠自定義數組,yml,xml,能夠根據本身的使用習慣,自定義填充數據。數據集可看: 點我
執行腳本 php vendor/bin/phpunit
而後去對應查看本身的數據表,是否多了一些填充的數據呢?
在不少狀況下,咱們的業務可謂是各類各樣吧,假若 phpunit 提供的數據庫測試還不能知足或者不夠方便的時候,就須要擴展本身的數據庫測試,來達到本身想要的效果。
幸虧,phpunit 提供了靈活的擴展操做(確定啦,別人確定不會像你這麼傻,寫死吧。哈哈),咱們能夠很容易地去實現本身的數據庫測試類。
<?php abstract class MyApp_Tests_DatabaseTestCase extends PHPUnit_Extensions_Database_TestCase { // 只實例化 pdo 一次,供測試的清理和裝載基境使用 static private $pdo = null; // 對於每一個測試,只實例化 PHPUnit_Extensions_Database_DB_IDatabaseConnection 一次 private $conn = null; final public function getConnection() { if ($this->conn === null) { if (self::$pdo == null) { self::$pdo = new PDO('mysql::dbname=test;host=127.0.0.1', 'user', 'pass'); } $this->conn = $this->createDefaultDBConnection(self::$pdo, ':memory:'); } return $this->conn; } }
至今爲止,完成了最基礎和入門的單元測試和數據庫測試,最終數據庫無非就是查看數據增刪改查是否和預期同樣。因此,配置完數據庫測試後,就能夠走回第一步,編寫你的測試用例,斷言測試了。
恭喜你,你已經構建完本身的單元測試環境了。接下來須要作的是,提升易用性,測試覆蓋率。我只能幫你到這裏了,接下來的路,本身走吧。