<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                > 沒有經過測試的代碼不是完成的代碼。 對于敏捷開發來說,測試也是重要的一環。對于ThinkPHP和其上開發的應用我們需要進行單元測試。 PHPUnit 是一個面向程序員的PHP測試框架。它是一個xUnit架構的單元測試框架的實例。 # 運行條件 PHPUnit 4.6 需要 PHP 5.3.3,強烈推薦使用最新版本的 PHP。 PHPUnit 需要使用 [dom](http://php.net/manual/en/dom.setup.php) 和 [json](http://php.net/manual/en/json.installation.php) 擴展,它們通常是默認啟用的。 PHPUnit 還需要 [pcre](http://php.net/manual/en/pcre.installation.php)、[reflection](http://php.net/manual/en/reflection.installation.php)、[spl](http://php.net/manual/en/spl.installation.php) 擴展。自 5.3.0 開始 PHP 核心需要這些擴展,通常無法禁用。 代碼覆蓋率分析報告功能需要 [Xdebug](http://xdebug.org/) (2.1.3以上)與 [tokenizer](http://php.net/manual/en/tokenizer.installation.php) 擴展。生成 XML 格式的報告需要有 xmlwriter 擴展。 # PHP檔案包(PHAR) 要獲取 PHPUnit,最簡單的方法是下載 PHPUnit 的 PHP 檔案包 (PHAR),它將 PHPUnit 所需要的所有必要組件(以及某些可選組件)捆綁在單個文件中: 要使用 PHP檔案包(PHAR)需要有 [phar](http://php.net/manual/en/phar.installation.php) 擴展。 要使用 PHAR 的 --self-update 功能需要有 [openssl](http://php.net/manual/en/openssl.installation.php) 擴展。 如果啟用了 Suhosin 擴展,需要在 php.ini 中允許執行 PHAR: `suhosin.executor.include.whitelist = phar` 注意 要從 <https://phar.phpunit.de/> 下載,需要[支持 TLS/SNI](http://en.wikipedia.org/wiki/Server_Name_Indication)的客戶端,例如 wget 1.14(或更高版本)。 如果要全局安裝 PHAR: ~~~ $ wget https://phar.phpunit.de/phpunit.phar $ chmod +x phpunit.phar $ sudo mv phpunit.phar /usr/local/bin/phpunit $ phpunit --version PHPUnit x.y.z by Sebastian Bergmann and contributors. ~~~ 也可以直接使用下載的 PHAR 文件: ~~~ $ wget https://phar.phpunit.de/phpunit.phar $ php phpunit.phar --version PHPUnit x.y.z by Sebastian Bergmann and contributors. ~~~ ## Windows 整體上說,在 Windows 下安裝 PHAR 和手工[在 Windows 下安裝 Composer](https://getcomposer.org/doc/00-intro.md#installation-windows) 是一樣的過程: 1. 為 PHP 的二進制可執行文件建立一個目錄,例如 C:\bin 2. 將 **;C:\bin** 附加到 PATH 環境變量中([相關幫助](http://stackoverflow.com/questions/6318156/adding-python-path-on-windows-7)) 3. 下載 <https://phar.phpunit.de/phpunit.phar> 并將文件保存到 *C:\bin\phpunit.phar* 4. 打開命令行(例如,按 **Windows+R** ? 輸入 cmd ? **ENTER**) 5. 建立外包覆批處理腳本(最后得到 C:\bin\phpunit.cmd): ~~~ C:\Users\username> cd C:\bin C:\bin> echo @php "%~dp0phpunit.phar" %* > phpunit.cmd C:\bin> exit ~~~ 6. 新開一個命令行窗口,確認一下可以在任意路徑下執行 PHPUnit: ~~~ C:\Users\username> phpunit --version PHPUnit x.y.z by Sebastian Bergmann and contributors. ~~~ 對于 Cygwin 或 MingW32 (例如 TortoiseGit) shell 環境,可以跳過第五步。 取而代之的是,把文件保存為 phpunit (沒有 .phar 擴展名),然后用 `chmod 775 phpunit` 將其設為可執行。 # Composer 如果用 [Composer](https://getcomposer.org/) 來管理項目的依賴關系,只要在項目的 composer.json 文件中簡單地加上對 phpunit/phpunit 的依賴關系即可。下面是一個最小化的 composer.json 文件的例子,只定義了一個對 PHPUnit 4.6 的開發時(development-time)依賴: ~~~ { "require-dev": { "phpunit/phpunit": "4.6.*" } } ~~~ 要通過 Composer 完成系統級的安裝,可以運行: `composer global require "phpunit/phpunit=4.6.*"` 請確保 path 變量中包含有 `~/.composer/vendor/bin/`。 ## 可選的組件包 有以下可選組件包可用: - PHP_Invoker 一個工具類,可以用帶有超時限制的方式調用可調用內容。當需要在嚴格模式下保證測試的超時限制時,這個組件包是必須的。 PHPUnit 的 PHAR 分發中已經包含了此組件包。若要通過 Composer 安裝此組件包,添加如下 "require-dev" 依賴項:`"phpunit/php-invoker": "*"` - DbUnit 移植到 PHP/PHPUnit 上的 DbUnit 用于提供對數據庫交互測試的支持。 PHPUnit 的 PHAR 分發中已經包含了此組件包。若要通過 Composer 安裝此組件包,添加如下 "require-dev" 依賴項: `"phpunit/dbunit": ">=1.2"` - PHPUnit_Selenium 將 Selenium RC 集成于 PHPUnit。 PHPUnit 的 PHAR 分發中已經包含了此組件包。若要通過 Composer 安裝此組件包,添加如下 "require-dev" 依賴項: `"phpunit/phpunit-selenium": ">=1.2"` # 開始寫測試 PHPUnit 編寫測試的基本慣例與步驟: 1. 針對類 Class 的測試寫在類 ClassTest中。 2. ClassTest(通常)繼承自 PHPUnit_Framework_TestCase。 3. 測試都是命名為 test* 的公用方法。 也可以在方法的文檔注釋塊(docblock)中使用 @test 標注將其標記為測試方法。 4. 在測試方法內,類似于 assertEquals()(參見 [附錄 A](https://phpunit.de/manual/current/zh_cn/phpunit-book.html#appendixes.assertions))這樣的斷言方法用來對實際值與預期值的匹配做出斷言。 ## 例子 ~~~ <?php class StackTest extends PHPUnit_Framework_TestCase{ public function testPushAndPop(){ $stack = array(); $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)); } } ?> ~~~ > 當你想把一些東西寫到 print 語句或者調試表達式中時,別這么做,將其寫成一個測試來代替。--Martin Fowler ## 注意點: ### 測試的依賴關系 理想的測試應當覆蓋程序的所有可能路徑。故此,我們可能為某一種場景做測試,這個場景里某些程序的調用有依賴順序,如點擊了A 成功響應事件B,然后B中又調用了C方法。 測試的時候肯定有A失敗的情況,而A失敗了不會走B和C的過程。 在測試里,我們往往單獨一個方法測試一個功能。A的處理,B的事件,C的事件。 并且默認是按照A B C的順序往下測試,但是如果對應現實場景,我們寫了ABC,但是BC 其實是依賴于A的成功結果才會執行的。 因此,我們可以通過 B 和 C 上寫 `@depends`依賴的方式,當A 失敗了 B和C 直接 也報失敗。 這樣的處理 符合自然也更高效。 ~~~ <?php class DependencyFailureTest extends PHPUnit_Framework_TestCase{ public function testOne(){ $this->assertTrue(FALSE); } /** * @depends testOne */ public function testTwo(){ } } ?> ~~~ 測試結果: ~~~ phpunit --verbose DependencyFailureTest PHPUnit 4.6.0 by Sebastian Bergmann and contributors. FS Time: 0 seconds, Memory: 5.00Mb There was 1 failure: 1) DependencyFailureTest::testOne Failed asserting that false is true. /home/sb/DependencyFailureTest.php:6 There was 1 skipped test: 1) DependencyFailureTest::testTwo This test depends on "DependencyFailureTest::testOne" to pass. FAILURES! Tests: 1, Assertions: 1, Failures: 1, Skipped: 1. ~~~ 為了快速定位缺陷,我們希望把注意力集中于相關的失敗測試上。這就是為什么當某個測試所依賴的測試失敗時,PHPUnit 會跳過這個測試。通過利用測試之間的依賴關系,缺陷定位得到了改進。 ### 命令行測試執行器 PHPUnit 命令行測試執行器可通過 phpunit 命令調用。下面的代碼展示了如何用 PHPUnit 命令行測試執行器來運行測試: ~~~ phpunit ArrayTest PHPUnit 4.6.0 by Sebastian Bergmann and contributors. .. Time: 0 seconds OK (2 tests, 2 assertions) ~~~ 上面這個調用例子中,PHPUnit 命令行測試執行器將在當前工作目錄中尋找 ArrayTest.php 源文件并加載之。而在此源文件中應當能找到 ArrayTest 測試用例類,此類中的測試將被執行。 對于每個測試的運行,PHPUnit 命令行工具輸出一個字符來指示進展: . 當測試成功時輸出。 F 當測試方法運行過程中一個斷言失敗時輸出。 E 當測試方法運行過程中產生一個錯誤時輸出。 R 當測試被標記為有風險時輸出(參見[第 6 章](https://phpunit.de/manual/current/zh_cn/phpunit-book.html#risky-tests))。 S 當測試被跳過時輸出(參見[第 7 章](https://phpunit.de/manual/current/zh_cn/phpunit-book.html#incomplete-and-skipped-tests))。 I 當測試被標記為不完整或未實現時輸出(參見[第 7 章](https://phpunit.de/manual/current/zh_cn/phpunit-book.html#incomplete-and-skipped-tests))。 PHPUnit 區分 敗(failure)與錯誤(error)。失敗指的是被違背了的 PHPUnit 斷言,例如一個失敗的 assertEquals() 調用。錯誤指的是意料之外的異常(exception)或 PHP 錯誤。這種差異已被證明在某些時候是非常有用的,因為錯誤往往比失敗更容易修復。如果得到了一個非常長的問題列表,那么最好先對付錯誤,當錯誤全部修復了之后再試一次瞧瞧還有沒有失敗。 #### 命令行選項 讓我們來瞧瞧以下代碼中命令行測試運行器的各種選項 ~~~ phpunit --help PHPUnit 4.6.0 by Sebastian Bergmann and contributors. Usage: phpunit [options] UnitTest [UnitTest.php] phpunit [options] <directory> Code Coverage Options: --coverage-clover <file> Generate code coverage report in Clover XML format. --coverage-crap4j <file> Generate code coverage report in Crap4J XML format. --coverage-html <dir> Generate code coverage report in HTML format. --coverage-php <file> Export PHP_CodeCoverage object to file. --coverage-text=<file> Generate code coverage report in text format. Default: Standard output. --coverage-xml <dir> Generate code coverage report in PHPUnit XML format. Logging Options: --log-junit <file> Log test execution in JUnit XML format to file. --log-tap <file> Log test execution in TAP format to file. --log-json <file> Log test execution in JSON format. --testdox-html <file> Write agile documentation in HTML format to file. --testdox-text <file> Write agile documentation in Text format to file. Test Selection Options: --filter <pattern> Filter which tests to run. --testsuite <pattern> Filter which testsuite to run. --group ... Only runs tests from the specified group(s). --exclude-group ... Exclude tests from the specified group(s). --list-groups List available test groups. --test-suffix ... Only search for test in files with specified suffix(es). Default: Test.php,.phpt Test Execution Options: --report-useless-tests Be strict about tests that do not test anything. --strict-coverage Be strict about unintentionally covered code. --strict-global-state Be strict about changes to global state --disallow-test-output Be strict about output during tests. --enforce-time-limit Enforce time limit based on test size. --disallow-todo-tests Disallow @todo-annotated tests. --process-isolation Run each test in a separate PHP process. --no-globals-backup Do not backup and restore $GLOBALS for each test. --static-backup Backup and restore static attributes for each test. --colors Use colors in output. --columns <n> Number of columns to use for progress output. --columns max Use maximum number of columns for progress output. --stderr Write to STDERR instead of STDOUT. --stop-on-error Stop execution upon first error. --stop-on-failure Stop execution upon first error or failure. --stop-on-risky Stop execution upon first risky test. --stop-on-skipped Stop execution upon first skipped test. --stop-on-incomplete Stop execution upon first incomplete test. -v|--verbose Output more verbose information. --debug Display debugging information during test execution. --loader <loader> TestSuiteLoader implementation to use. --repeat <times> Runs the test(s) repeatedly. --tap Report test execution progress in TAP format. --testdox Report test execution progress in TestDox format. --printer <printer> TestListener implementation to use. Configuration Options: --bootstrap <file> A "bootstrap" PHP file that is run before the tests. -c|--configuration <file> Read configuration from XML file. --no-configuration Ignore default configuration file (phpunit.xml). --include-path <path(s)> Prepend PHP's include_path with given path(s). -d key[=value] Sets a php.ini value. Miscellaneous Options: -h|--help Prints this usage information. --version Prints the version and exits. ~~~ phpunit UnitTest 運行由 UnitTest 類提供的測試。這個類應當在 UnitTest.php 源文件中聲明。 UnitTest 這個類必須滿足以下二個條件之一:要么它繼承自 PHPUnit_Framework_TestCase;要么它提供 public static suite() 方法,這個方法返回一個 PHPUnit_Framework_Test 對象,比如,一個 PHPUnit_Framework_TestSuite 類的實例。 phpunit UnitTest UnitTest.php 運行由 UnitTest 類提供的測試。這個類應當在指定的源文件中聲明。 --coverage-clover 為運行的測試生成帶有代碼覆蓋率信息的 XML 格式的日志文件。更多細節請參見第 14 章。 請注意,此功能僅當安裝了 tokenizer 和 Xdebug 這兩個 PHP 擴展后才可用。 --coverage-crap4j 生成 Crap4j 格式的代碼覆蓋率報告。更多細節請參見第 11 章。 請注意,此功能僅當安裝了 tokenizer 和 Xdebug 這兩個 PHP 擴展后才可用。 --coverage-html 生成 HTML 格式的代碼覆蓋率報告。更多細節請參見 第 11 章。 請注意,此功能僅當安裝了 tokenizer 和 Xdebug 這兩個 PHP 擴展后才可用。 --coverage-php 生成一個序列化后的 PHP_CodeCoverage 對象,此對象含有代碼覆蓋率信息。 請注意,此功能僅當安裝了 tokenizer 和 Xdebug 這兩個 PHP 擴展后才可用。 --coverage-text 為運行的測試以人們可讀的格式生成帶有代碼覆蓋率信息的日志文件或命令行輸出。更多細節請參見 第 14 章。 請注意,此功能僅當安裝了 tokenizer 和 Xdebug 這兩個 PHP 擴展后才可用。 --log-junit 為運行的測試生成 JUnit XML 格式的日志文件。更多細節請參見 第 14 章。 --log-tap 為運行的測試生成 Test Anything Protocol (TAP) 格式的日志文件。更多細節請參見第 14 章。 --log-json 生成 JSON 格式的日志文件。更多細節請參見第 14 章。 --testdox-html 和 --testdox-text 為運行的測試以 HTML 或純文本格式生成敏捷文檔。更多細節請參見 第 12 章。 --filter 只運行名稱與給定模式匹配的測試。如果模式未閉合包裹于分隔符,PHPUnit 將用 / 分隔符對其進行閉合包裹。 測試名稱將以以下格式之一進行匹配: TestNamespace\TestCaseClass::testMethod -testsuite 只運行名稱與給定模式匹配的測試套件。 --group 只運行來自指定分組(可以多個)的測試。可以用 @group 標注為測試標記其所屬的分組。 @author 標注是 @group 的一個別名,允許按作者來篩選測試。 --exclude-group 排除來自指定分組(可以多個)的測試。可以用 @group 標注為測試標記其所屬的分組。 --list-groups 列出所有有效的測試分組。 --test-suffix 只查找文件名以指定后綴(可以多個)結尾的測試文件。 --report-useless-tests 更嚴格對待事實上不測試任何內容的測試。詳情參見 第 6 章。 --strict-coverage 更嚴格對待意外的代碼覆蓋。詳情參見 第 6 章。 --strict-global-state 更嚴格對待全局狀態篡改。詳情參見 第 6 章。 --disallow-test-output 更嚴格對待測試執行期間產生的輸出。詳情參見第 6 章。 --disallow-todo-tests 不執行文檔注釋塊中含有 @todo 標注的測試。 --enforce-time-limit 根據測試規模對其加上執行時長限制。詳情參見第 6 章。 --strict 以嚴格模式運行測試(效果的功能等同于同時使用 --report-useless-tests、--strict-coverage、--disallow-test-output 和 --enforce-time-limit)。詳情參見第 6 章。 --process-isolation 每個測試都在獨立的PHP進程中運行。 --no-globals-backup 不要備份并還原 $GLOBALS。更多細節請參見“全局狀態”一節。 --static-backup 備份并還原用戶定義的類中的靜態屬性。更多細節請參見“全局狀態”一節。 --colors 使用彩色輸出。Windows下,用 ANSICON 或 ConEmu。 --stderr 選擇輸出到 STDERR 而非 STDOUT. --stop-on-error 首次錯誤出現后停止執行。 --stop-on-failure 首次錯誤或失敗出現后停止執行。 --stop-on-risky 首次碰到有風險的測試時停止執行。 --stop-on-skipped 首次碰到跳過的測試時停止執行。 --stop-on-incomplete 首次碰到不完整的測試時停止執行。 --verbose 輸出更詳盡的信息,例如不完整或者跳過的測試的名稱。 --debug 輸出調試信息,例如當一個測試開始執行時輸出其名稱。 --loader 指定要使用的 PHPUnit_Runner_TestSuiteLoader 實現。 標準的測試套件加載器將在當前工作目錄和 PHP 的 include_path 配置指令中指定的每個目錄內查找源文件。諸如 Project_Package_Class 這樣的類名對應的源文件名為 Project/Package/Class.php。 --repeat 將測試重復運行指定次數。 --tap 使用 Test Anything Protocol (TAP) 報告測試進度。更多細節請參見 第 14 章。 --testdox 將測試進度以敏捷文檔方式報告。更多細節請參見 第 12 章。 --printer 指定要使用的結果輸出器(printer)。輸出器類必須擴展 PHPUnit_Util_Printer 并且實現 PHPUnit_Framework_TestListener 接口。 --bootstrap 在測試前先運行一個 "bootstrap" PHP 文件。 --configuration, -c 從 XML 文件中讀取配置信息。更多細節請參見附錄 C。 如果 phpunit.xml 或 phpunit.xml.dist (按此順序)存在于當前工作目錄并且未使用 --configuration,將自動從此文件中讀取配置。 --no-configuration 忽略當前工作目錄下的 phpunit.xml 與 phpunit.xml.dist。 --include-path 向 PHP 的 include_path 開頭添加指定路徑(可以多個)。 -d 設置指定的 PHP 配置選項的值。 **注意** 請注意,選項不能放在參數之后。 ### 基境 在編寫測試時,最費時的部分之一是編寫代碼來將整個場景設置成某個已知的狀態,并在測試結束后將其復原到初始狀態。這個已知的狀態稱為測試的 基境(fixture)。 #### 可用方法 `setUp()` 和 `tearDown()` 模板方法(同時,每個測試方法都是在一個全新的測試類實例上運行的)。 另外,`setUpBeforeClass()` 與 `tearDownAfterClass()` 模板方法將分別在測試用例類的第一個測試運行之前和測試用例類的最后一個測試運行之后調用。 ### 全局變量 [使用單件(singleton)的代碼很難測試](http://googletesting.blogspot.com/2008/05/tott-using-dependancy-injection-to.html)。使用全局變量的代碼也一樣。通常情況下,欲測代碼和全局變量之間會強烈耦合,并且其創建無法控制。另外一個問題是,一個測試對全局變量的改變可能會破壞另外一個測試。 默認情況下,PHPUnit 用一種更改全局變量與超全局變量($GLOBALS、$_ENV、$_POST、$_GET、$_COOKIE、$_SERVER、$_FILES、$_REQUEST)不會影響到其他測試的方式來運行所有測試。同時,還可以選擇將這種隔離擴展到類的靜態屬性。 默認情況下 測試方法間全局變量是失效的。 ~~~ <?php class StackTest extends PHPUnit_Framework_TestCase{ public function testOne{ $_SESSION['a'] = 'b'; } public function testTwo(){ var_dump(isset($_SESSION['a'])); //結果是false } } ?> ~~~ 解決的方法是,在繼承PHPUnit_Framework_TestCase 的測試類里 設置屬性 `protected $backupGlobals = FALSE;` ### 測試順序控制 #### 文件系統順序 >當 PHPUnit 命令行測試執行器指向一個目錄時,它會在目錄下查找 *Test.php 文件。 最簡單的大概就是把所有測試用例源文件放在一個測試目錄中。通過對測試目錄進行遞歸遍歷,PHPUnit 能自動發現并運行測試。 現在來看看 sebastianbergmann/money 這個庫的測試套件。在這個項目的目錄結構中,可以看到 tests 目錄下的測試用例類鏡像了 src 目錄下被測系統(SUT, System Under Test)的包(package)與類(class)的結構: ~~~ src tests `-- Currency.php `-- CurrencyTest.php `-- IntlFormatter.php `-- IntlFormatterTest.php `-- Money.php `-- MoneyTest.php `-- autoload.php ~~~ 要運行這個庫的全部測試,只要將 PHPUnit 命令行測試執行器指向測試目錄即可: ~~~ phpunit --bootstrap src/autoload.php tests PHPUnit 4.6.0 by Sebastian Bergmann. ................................. Time: 636 ms, Memory: 3.50Mb OK (33 tests, 52 assertions) ~~~ #### XML文件配置 PHPUnit的 XML 配置文件([附錄 C](https://phpunit.de/manual/current/zh_cn/phpunit-book.html#appendixes.configuration))也可以用于編排測試套件。例 5.1展示了一個最小化的 phpunit.xml 例子,它將在遞歸遍歷 tests 時添加所有在 *Test.php 文件中找到的 *Test 類。 例 5.1: 用 XML 配置來編排測試套件 ~~~ <phpunit bootstrap="src/autoload.php"> <testsuites> <testsuite name="money"> <directory>tests</directory> </testsuite> </testsuites> </phpunit> ~~~ 如果 phpunit.xml 或 phpunit.xml.dist (按此順序)存在于當前工作目錄并且未使用 --configuration,將自動從此文件中讀取配置。 可以明確指定測試的執行順序: 例 5.2: 用 XML 配置來編排測試套件 ~~~ <phpunit bootstrap="src/autoload.php"> <testsuites> <testsuite name="money"> <file>tests/IntlFormatterTest.php</file> <file>tests/MoneyTest.php</file> <file>tests/CurrencyTest.php</file> </testsuite> </testsuites> </phpunit> ~~~ ### 跳過測試 并非所有測試都能在任何環境中運行。比如說,考慮這樣一種情況:一個數據庫抽象層,針對其所支持的各種數據庫系統有多個不同的驅動程序。針對 MySQL 驅動程序的測試當然只在 MySQL 服務器可用才能運行。 例 7.2 展示了一個測試用例類 DatabaseTest,它有一個測試方法 testConnection()。在測試用例類的 setUp()模板方法中,檢查了 MySQLi 擴展是否可用,并且在擴展不可用時用 markTestSkipped() 方法來跳過此測試。 例 7.2: 跳過某個測試 ~~~ <?php class DatabaseTest extends PHPUnit_Framework_TestCase { protected function setUp() { if (!extension_loaded('mysqli')) { $this->markTestSkipped( 'The MySQLi 擴展不可用。' ); } } public function testConnection() { // ... } } ?> ~~~ 在 PHPUnit 命令行測試執行器的輸出中,被跳過的測試記為 S,如下例所示: ~~~ phpunit --verbose DatabaseTest PHPUnit 4.6.0 by Sebastian Bergmann and contributors. S Time: 0 seconds, Memory: 3.95Mb There was 1 skipped test: 1) DatabaseTest::testConnection The MySQLi extension is not available. /home/sb/DatabaseTest.php:9 OK, but incomplete or skipped tests! Tests: 1, Assertions: 0, Skipped: 1. ~~~ 表 7.2列舉了用于跳過測試的 API。 表 7.2. 用于跳過測試的 API |方法| 含義| |-|-| |void markTestSkipped()|將當前測試標記為已跳過。| |void markTestSkipped(string $message)|將當前測試標記為已跳過,并用 $message 作為說明信息。| 用 @requires 來跳過測試 除了上述方法,還可以用 @requires 標注來表達測試用例的一些常見前提條件。 表 7.3. 可能的 @requires 用法 |類型 |可能的值 |范例 |其他范例| |-----|-----|------|------| |PHP |任何 PHP 版本標識符 |@requires PHP 5.3.3 |@requires PHP 5.4-dev| |PHPUnit |任何 PHPUnit 版本標識符 |@requires PHPUnit 3.6.3 |@requires PHPUnit 4.6| |OS |用來對 PHP_OS 進行匹配的正則表達式 |@requires OS Linux |@requires OS WIN32 WINNT| |function |任何對 function_exists 而言有效的參數 |@requires function imap_open |@requires function ReflectionMethod::setAccessible| |extension |任何擴展的名稱 |@requires extension| mysqli @requires extension curl| 例 7.3: 用 @requires 來跳過測試 ~~~ <?php /** * @requires extension mysqli */ class DatabaseTest extends PHPUnit_Framework_TestCase { /** * @requires PHP 5.3 */ public function testConnection() { // 測試要求有 mysqli 擴展,并且 PHP >= 5.3 } // ... 所有其他要求有 mysqli 擴展的測試 } ?> ~~~ 如果使用了某種在特定版本的 PHP 下無法編譯的語法,請在此章節內查找 XML 配置信息中關于版本依賴的信息:[“測試套件”一節](https://phpunit.de/manual/current/zh_cn/phpunit-book.html#appendixes.configuration.testsuites) # 個人思考 ## 測試 先有測試后開發,測試能提高質量 自動化 可以快速定義錯誤 測試原則: 1. 最大覆蓋測試 2. 測試有依賴可以快速定位 3. 一致性,不要為了命名這件事浪費時間 ## PHPUnit ### 測試得出代碼寫的技巧 1. 數據庫操作級的函數和方法 寫在前面 2. 易被別處調用的基礎方法寫上面 3. 每個函數或方法最好有返回值,特殊情況例外 ## 一個ThinkPHP單元測試的例子: 大家可以看隨書項目的示列項目 [yang_book](https://coding.net/u/jaylabs/p/yang_book/git) 里phpunit里tests目錄下的測試,就寫了個函數測試。 因為發現tp耦合性太高,文件加載自動沒法弄,除非手寫死所有框架要加載的文件要死人的。 所以就只自己寫了加載框架和函數及慣例配置文件。函數庫里一些和類相關及文件加載相關的函數也沒測試。 因為涉及類的命名空間,正常來說都能加載、實例化成功。就沒測試。 ![document/2015-08-23/55d9c1b5746ea](http://box.kancloud.cn/document_2015-08-23_55d9c1b5746ea.png) 先命令行切換到單元測試目錄。然后 phpunit 指定目錄即可。 ![document/2015-08-23/55d9c1e94f64b](http://box.kancloud.cn/document_2015-08-23_55d9c1e94f64b.png) 也可以手動指定一個測試方法。 PS:老大說Thinkphp4會有單元測試的。 其實很多tp用戶也關心測試這個問題,寫了一些框架來解決單元測試問題: - [一個為ThinkPHP打造的簡單易用的UnitTest](http://www.thinkphp.cn/extend/670.html) - [ThinkPHP3.2單元測試實踐](http://www.thinkphp.cn/topic/31450.html) - [LTPTest2.0.0 -- TP 下的單元測試框架擴展](http://www.thinkphp.cn/extend/599.html)
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看