PHPUnit9.0 未完成的測試與跳過的測試

2022-03-22 15:20 更新

未完成的測試

開始寫新的測試用例類時(shí),可能想從寫下空測試方法開始,比如:

public function testSomething(): void
{
}

以此來跟蹤需要編寫的測試??諟y試的問題是 PHPUnit 框架會(huì)將它們解讀為成功。這種錯(cuò)誤解讀導(dǎo)致錯(cuò)誤報(bào)告變得毫無用處——無法分辨出測試是真的成功了還是根本就未編寫實(shí)現(xiàn)。在未實(shí)現(xiàn)的測試中調(diào)用 ?$this->fail()? 同樣沒啥幫助,因?yàn)闇y試將被解讀為失敗。這和將未實(shí)現(xiàn)的測試解讀為成功是一樣的錯(cuò)誤。
假如把成功的測試視為綠燈、測試失敗視為紅燈,那么還額外需要黃燈來將測試標(biāo)記為未完成或尚未實(shí)現(xiàn)。?PHPUnit\Framework\IncompleteTest? 是一個(gè)標(biāo)記接口,用于將測試方法拋出的異常標(biāo)記為測試未完成或目前尚未實(shí)現(xiàn)而導(dǎo)致的結(jié)果。?PHPUnit\Framework\IncompleteTestError? 是這個(gè)接口的標(biāo)準(zhǔn)實(shí)現(xiàn)。
示例 7.1 展示了一個(gè)測試用例類 ?SampleTest?,它有一個(gè)測試方法 ?testSomething()?。通過在測試方法中調(diào)用便捷方法 ?markTestIncomplete()(會(huì)自動(dòng)拋出一個(gè) ?PHPUnit\Framework\IncompleteTestError? 異常)將這個(gè)測試標(biāo)記為未完成。
示例 7.1 將測試標(biāo)記為不完整

<?php declare(strict_types=1);
use PHPUnit\Framework\TestCase;

final class SampleTest extends TestCase
{
    public function testSomething(): void
    {
        // 可選:如果愿意,在這里隨便測試點(diǎn)什么。
        $this->assertTrue(true, 'This should already work.');

        // 在這里停止,并將此測試標(biāo)記為未完成。
        $this->markTestIncomplete(
          'This test has not been implemented yet.'
        );
    }
}

在 PHPUnit 命令行測試執(zhí)行器的輸出中,未完成的測試記為 ?I?,如下例所示:

$ phpunit --verbose SampleTest
PHPUnit latest.0 by Sebastian Bergmann and contributors.

I

Time: 0 seconds, Memory: 3.95Mb

There was 1 incomplete test:

1) SampleTest::testSomething
This test has not been implemented yet.

/home/sb/SampleTest.php:12
OK, but incomplete or skipped tests!
Tests: 1, Assertions: 1, Incomplete: 1.

表格 7.1 列舉了用于將測試標(biāo)記為未完成的 API。

表格 7.1 用于不完整的測試的 API

 方法  含義
void markTestIncomplete()?  將當(dāng)前測試標(biāo)記為未完成。
void markTestIncomplete(string $message)?  將當(dāng)前測試標(biāo)記為未完成。并用 ?$message? 作為說明信息。

跳過測試

并非所有測試都能在任何環(huán)境中運(yùn)行。比如說,考慮這樣一種情況:一個(gè)數(shù)據(jù)庫抽象層,針對其所支持的各種數(shù)據(jù)庫系統(tǒng)有多個(gè)不同的驅(qū)動(dòng)程序。針對 MySQL 驅(qū)動(dòng)程序的測試只在 MySQL 服務(wù)器可用才能運(yùn)行。
示例 7.2 展示了一個(gè)測試用例類 ?DatabaseTest?,它有一個(gè)測試方法 ?testConnection()?。在測試用例類的 ?setUp()? 模板方法中,檢查了 MySQLi 擴(kuò)展是否可用,并且在擴(kuò)展不可用時(shí)用 ?markTestSkipped()? 方法來跳過此測試。
示例 7.2 跳過測試

<?php declare(strict_types=1);
use PHPUnit\Framework\TestCase;

final class DatabaseTest extends TestCase
{
    protected function setUp(): void
    {
        if (!extension_loaded('mysqli')) {
            $this->markTestSkipped(
              'The MySQLi extension is not available.'
            );
        }
    }

    public function testConnection(): void
    {
        // ...
    }
}

在 PHPUnit 命令行測試執(zhí)行器的輸出中,被跳過的測試記為 ?S?,如下例所示:

$ phpunit --verbose DatabaseTest
PHPUnit latest.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()?  將當(dāng)前測試標(biāo)記為已跳過。
 ?void markTestSkipped(string $message)?  將當(dāng)前測試標(biāo)記為已跳過,并用 ?$message? 作為說明信息。

用 @requires 來跳過測試

除了上述方法,還可以用 ?@requires? 標(biāo)注來表達(dá)測試用例的一些常見前提條件。

表格 7.3 可能的 @requires 用法

 類型 可能值  示例  其他示例 
PHP  任意PHP版本號以及可選的運(yùn)算符  @requires PHP 7.1.20  @requires PHP >= 7.2 
PHPUnit  任意PHPUnit版本號以及可選的運(yùn)算符  @requires PHPUnit 7.3.1  @requires PHPUnit < 8 
OS   與 PHP_OS 匹配的正則表達(dá)式  @requires OS Linux @requires OS WIN32|WINNT
OSFAMILY   任意 OS family  @requires OSFAMILY Solaris @requires OSFAMILY Windows
function   任意 function_exists 的有效參數(shù)  @requires function imap_open @requires function ReflectionMethod::setAccessible
extension   任意擴(kuò)展名以及可選的版本號和可選的運(yùn)算符  @requires extension mysqli @requires extension redis >= 2.2.0 

PHP、PHPUnit 和擴(kuò)展的版本約束支持以下運(yùn)算符:?<?、?<=?、?>?、?>=?、?=?、?==?、?!=?、?<>?。

版本是用 PHP 的 version_compare 函數(shù)進(jìn)行比較的。除了其他事情之外,這意味著 ?=? 和 ?==? 運(yùn)算符只能用于完整的 ?X.Y.Z? 版本號,只用 ?X.Y? 是不行的。
示例 7.3 用 @requires 跳過測試

<?php declare(strict_types=1);
use PHPUnit\Framework\TestCase;

/**
 * @requires extension mysqli
 */
final class DatabaseTest extends TestCase
{
    /**
     * @requires PHP >= 5.3
     */
    public function testConnection(): void
    {
        // 測試需要 mysqli 擴(kuò)展,并且要求 PHP >= 5.3
    }

    // ... 其他需要 mysqli 擴(kuò)展的測試
}


以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號