PHPUnit9.0 未完成的測(cè)試與跳過(guò)的測(cè)試

2022-03-22 15:20 更新

未完成的測(cè)試

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

public function testSomething(): void
{
}

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

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

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

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

在 PHPUnit 命令行測(cè)試執(zhí)行器的輸出中,未完成的測(cè)試記為 ?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 列舉了用于將測(cè)試標(biāo)記為未完成的 API。

表格 7.1 用于不完整的測(cè)試的 API

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

跳過(guò)測(cè)試

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

<?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 命令行測(cè)試執(zhí)行器的輸出中,被跳過(guò)的測(cè)試記為 ?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 列舉了用于跳過(guò)測(cè)試的 API。

表格 7.2 用于跳過(guò)測(cè)試的 API

 方法 含義 
 ?void markTestSkipped()?  將當(dāng)前測(cè)試標(biāo)記為已跳過(guò)。
 ?void markTestSkipped(string $message)?  將當(dāng)前測(cè)試標(biāo)記為已跳過(guò),并用 ?$message? 作為說(shuō)明信息。

用 @requires 來(lái)跳過(guò)測(cè)試

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

表格 7.3 可能的 @requires 用法

 類型 可能值  示例  其他示例 
PHP  任意PHP版本號(hào)以及可選的運(yùn)算符  @requires PHP 7.1.20  @requires PHP >= 7.2 
PHPUnit  任意PHPUnit版本號(hào)以及可選的運(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ò)展名以及可選的版本號(hào)和可選的運(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? 版本號(hào),只用 ?X.Y? 是不行的。
示例 7.3 用 @requires 跳過(guò)測(cè)試

<?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
    {
        // 測(cè)試需要 mysqli 擴(kuò)展,并且要求 PHP >= 5.3
    }

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


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

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)