PHPUnit9.0 編寫PHPUnit測試-測試的依賴關(guān)系

2022-03-25 15:31 更新

示例 2.1 展示了如何用 PHPUnit 編寫測試來對 PHP 數(shù)組操作進(jìn)行測試。此示例介紹了用 PHPUnit 編寫測試的基本慣例與步驟:

  1. 針對類 ?Class ?的測試寫在類 ?ClassTest ?中。
  2. ?ClassTest?(通常)繼承自 ?PHPUnit\Framework\TestCase?。
  3. 測試都是命名為 ?test*? 的公用方法。也可以在方法的文檔注釋塊(docblock)中使用 ?@test? 標(biāo)注將其標(biāo)記為測試方法。
  4. 在測試方法內(nèi),類似于 ?assertSame()這樣的斷言方法用來對實際值與預(yù)期值的匹配做出斷言。

示例 2.1 用 PHPUnit 測試數(shù)組操作

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

final class StackTest extends TestCase
{
    public function testPushAndPop(): void
    {
        $stack = [];
        $this->assertSame(0, count($stack));

        array_push($stack, 'foo');
        $this->assertSame('foo', $stack[count($stack)-1]);
        $this->assertSame(1, count($stack));

        $this->assertSame('foo', array_pop($stack));
        $this->assertSame(0, count($stack));
    }
}

當(dāng)你想把一些東西寫到 ?print ?語句或者調(diào)試表達(dá)式中時,別這么做,改為將其寫成測試。

測試的依賴關(guān)系

單元測試主要是作為一種良好實踐來編寫的,它能幫助開發(fā)人員識別并修復(fù) bug、重構(gòu)代碼,還可以看作被測軟件單元的文檔。要實現(xiàn)這些好處,理想的單元測試應(yīng)當(dāng)覆蓋程序中所有可能的路徑。一個單元測試通常覆蓋一個函數(shù)或方法中的一個特定路徑。但是,測試方法不一定是封裝良好的獨立實體。測試方法之間經(jīng)常有隱含的依賴關(guān)系暗藏在測試的實現(xiàn)方案中。

PHPUnit支持對測試方法之間的顯式依賴關(guān)系進(jìn)行聲明。這種依賴關(guān)系并不是定義在測試方法的執(zhí)行順序中,而是允許生產(chǎn)者(producer)返回一個測試基境(fixture)的實例,并將此實例傳遞給依賴于它的消費者(consumer)們。

  • 生產(chǎn)者(producer),是能生成被測單元并將其作為返回值的測試方法。
  • 消費者(consumer),是依賴于一個或多個生產(chǎn)者及其返回值的測試方法。

示例 2.2 展示了如何用 ?@depends? 標(biāo)注來表示測試方法之間的依賴關(guān)系。
示例 2.2 用 ?@depends? 標(biāo)注來表示依賴關(guān)系

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

final class StackTest extends TestCase
{
    public function testEmpty(): array
    {
        $stack = [];
        $this->assertEmpty($stack);

        return $stack;
    }

    /**
     * @depends testEmpty
     */
    public function testPush(array $stack): array
    {
        array_push($stack, 'foo');
        $this->assertSame('foo', $stack[count($stack)-1]);
        $this->assertNotEmpty($stack);

        return $stack;
    }

    /**
     * @depends testPush
     */
    public function testPop(array $stack): void
    {
        $this->assertSame('foo', array_pop($stack));
        $this->assertEmpty($stack);
    }
}

在上例中,第一個測試?testEmpty()? 創(chuàng)建了一個新數(shù)組,并斷言其為空。隨后,此測試將此基境作為結(jié)果返回。第二個測試 ?testPush()? 依賴于 ?testEmpty()?,并將所依賴的測試之結(jié)果作為參數(shù)傳入。最后,?testPop()? 依賴于 ?testPush()?。

注解:

默認(rèn)情況下,生產(chǎn)者所產(chǎn)生的返回值將原樣傳遞給相應(yīng)的消費者。這意味著,如果生產(chǎn)者返回的是一個對象,那么傳遞給消費者的將是指向此對象的引用。但同樣也可以(a)通過 ?@depends clone? 來傳遞指向深拷貝對象的引用,或(b)通過 ?@depends shallowClone? 來傳遞指向正常淺克隆對象(基于 PHP 關(guān)鍵字 ?clone?)的引用。

為了定位缺陷,我們希望把注意力集中于相關(guān)的失敗測試上。這就是為什么當(dāng)某個測試所依賴的測試失敗時,PHPUnit 會跳過這個測試。利用測試之間的依賴關(guān)系可以改進(jìn)缺陷定位,如示例 2.3 所示。
示例 2.3 利用測試之間的依賴關(guān)系

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

final class DependencyFailureTest extends TestCase
{
    public function testOne(): void
    {
        $this->assertTrue(false);
    }

    /**
     * @depends testOne
     */
    public function testTwo(): void
    {
    }
}
$ phpunit --verbose DependencyFailureTest
PHPUnit latest.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.

測試可以使用多個 ?@depends? 標(biāo)注。PHPUnit 不會更改測試的運行順序,因此你需要自行保證某個測試所依賴的所有測試均出現(xiàn)于這個測試之前。
擁有多個 ?@depends? 標(biāo)注的測試,其第一個參數(shù)是第一個生產(chǎn)者提供的基境,第二個參數(shù)是第二個生產(chǎn)者提供的基境,以此類推。參見示例 2.4
示例 2.4 有多個依賴項的測試

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

final class MultipleDependenciesTest extends TestCase
{
    public function testProducerFirst(): string
    {
        $this->assertTrue(true);

        return 'first';
    }

    public function testProducerSecond(): string
    {
        $this->assertTrue(true);

        return 'second';
    }

    /**
     * @depends testProducerFirst
     * @depends testProducerSecond
     */
    public function testConsumer(string $a, string $b): void
    {
        $this->assertSame('first', $a);
        $this->assertSame('second', $b);
    }
}
$ phpunit --verbose MultipleDependenciesTest
PHPUnit latest.0 by Sebastian Bergmann and contributors.

...

Time: 0 seconds, Memory: 3.25Mb

OK (3 tests, 4 assertions)


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

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號