預期
藉由使用 Pest 預期 API 來設定測試的預期,你可以輕鬆找出程式碼中的錯誤和其他問題。這是因為此 API 允許你指定測試的預期結果,使其可以輕易地偵測出與預期行為的任何差異。
你可以將值傳遞給 expect($value)
函式來開始預期。你每次想要測試一個值時,就會使用 expect()
函式。你很少會單獨呼叫 expect()
。你會使用 expect()
與「預期」方法來判斷值是否正確。
1test('sum', function () {2 $value = sum(1, 2);3 4 expect($value)->toBe(3); // Assert that the value is 3...5});
如示範所示,Pest 中的 expect 函式允許你為一個給定的 $value
串聯多個預期。這表示你可以在一個測試中執行必要的檢查次数,只需要持續串聯其他預期即可。
1expect($value)2 ->toBeInt()3 ->toBe(3);
你可以隨時在預期之前加上 not
修飾詞來測試相反的預期。
1expect($value)2 ->toBeInt()3 ->toBe(3)4 ->not->toBeString() // Not to be string...5 ->not->toBe(4); // Not to be 4...
藉由使用 Pest 預期 API,你可以存取許多用於測試不同程式碼區塊的個別預期。以下提供可用預期的完整清單。
-
toBe()
-
toBeArray()
-
toBeBetween()
-
toBeEmpty()
-
toBeTrue()
-
toBeTruthy()
-
toBeFalse()
-
toBeFalsy()
-
toBeGreaterThan()
-
toBeGreaterThanOrEqual()
-
toBeLessThan()
-
toBeLessThanOrEqual()
-
toContain()
-
toContainEqual()
-
toContainOnlyInstancesOf()
-
toHaveCount()
-
toHaveProperty()
-
toHaveProperties()
-
toMatchArray()
-
toMatchObject()
-
toEqual()
-
toEqualCanonicalizing()
-
toEqualWithDelta()
-
toBeIn()
-
toBeInfinite()
-
toBeInstanceOf()
-
toBeBool()
-
toBeCallable()
-
toBeFile()
-
toBeFloat()
-
toBeInt()
-
toBeIterable()
-
toBeNumeric()
-
toBeDigits()
-
toBeObject()
-
toBeResource()
-
toBeScalar()
-
toBeString()
-
toBeJson()
-
toBeNan()
-
toBeNull()
-
toHaveKey()
-
toHaveKeys()
-
toHaveLength()
-
toBeReadableDirectory()
-
toBeReadableFile()
-
toBeWritableDirectory()
-
toBeWritableFile()
-
toStartWith()
-
toThrow()
-
toEndWith()
-
toMatch()
-
toMatchConstraint()
-
toBeUppercase()
-
toBeLowercase()
-
toBeAlpha()
-
toBeAlphaNumeric()
-
toBeSnakeCase()
-
toBeKebabCase()
-
toBeCamelCase()
-
toBeStudlyCase()
-
toHaveSnakeCaseKeys()
-
toHaveKebabCaseKeys()
-
toHaveCamelCaseKeys()
-
toHaveStudlyCaseKeys()
-
toHaveSameSize()
-
toBeUrl()
-
toBeUuid()
除了 Pest 中提供的個別預期之外,預期 API 還提供幾個修改器,讓你可以進一步自訂你的測試。這些修改器可用于創建更複雜的預期並一次測試多個值。以下是 Pest 中可用的修改器的一些範例:
toBe()
這個預期確保 $value
和 $expected
共享相同的類型和值。
如果用於物件,它確保兩個變數參照完全相同的物件。
1expect(1)->toBe(1);2expect('1')->not->toBe(1);3expect(new StdClass())->not->toBe(new StdClass());
toBeBetween()
這個預期確保 $value
介於兩個值之間。它適用於 int
、float
和 DateTime
。
1expect(2)->toBeBetween(1, 3);2expect(1.5)->toBeBetween(1, 2);3 4$expectationDate = new DateTime('2023-09-22');5$oldestDate = new DateTime('2023-09-21');6$latestDate = new DateTime('2023-09-23');7 8expect($expectationDate)->toBeBetween($oldestDate, $latestDate);
toBeEmpty()
這個預期確保 $value
為空。
1expect('')->toBeEmpty();2expect([])->toBeEmpty();3expect(null)->toBeEmpty();
toBeTrue()
這個預期確保 $value
為真。
1expect($isPublished)->toBeTrue();
toBeTruthy()
這個預期確保 $value
為真值。
1expect(1)->toBeTruthy();2expect('1')->toBeTruthy();
toBeFalse()
這個預期確保 $value
為假。
1expect($isPublished)->toBeFalse();
toBeFalsy()
這個預期確保 $value
為假值。
1expect(0)->toBeFalsy();2expect('')->toBeFalsy();
toBeGreaterThan($expected)
這個預期確保 $value
大於 $expected
。
1expect($count)->toBeGreaterThan(20);
toBeGreaterThanOrEqual($expected)
這個預期確保 $value
大於或等於 $expected
。
1expect($count)->toBeGreaterThanOrEqual(21);
toBeLessThan($expected)
這個預期確保 $value
小於 $expected
。
1expect($count)->toBeLessThan(3);
toBeLessThanOrEqual($expected)
這個預期確保 $value
小於或等於 $expected
。
1expect($count)->toBeLessThanOrEqual(2);
toContain($needles)
這個預期確保所有指定的 needles 都是 $value
中的元素。
1expect('Hello World')->toContain('Hello');2expect('Pest: an elegant PHP Testing Framework')->toContain('Pest', 'PHP', 'Framework');3expect([1, 2, 3, 4])->toContain(2, 4);
toContainEqual($needles)
這個預期確保所有指定的 needles 是 $value
中的元素(在相等意義上)。
1expect([1, 2, 3])->toContainEqual('1');2expect([1, 2, 3])->toContainEqual('1', '2');
toContainOnlyInstancesOf($class)
這個預期確保 $value
僅包含 $class
的實例。
1$dates = [new DateTime(), new DateTime()];2 3expect($dates)->toContainOnlyInstancesOf(DateTime::class);
toHaveCount(int $count)
此期望可確保所提供的 $count
與可迭代 $value
中的元素數量相符。
1expect(['Nuno', 'Luke', 'Alex', 'Dan'])->toHaveCount(4);
toHaveProperty(string $name, $value = null)
此期望可確保 $value
具有名為 $name
的屬性。
此外,您可以透過提供第二個參數來驗證屬性的實際值。
1expect($user)->toHaveProperty('name');2expect($user)->toHaveProperty('name', 'Nuno');3expect($user)->toHaveProperty('is_active', 'true');
toHaveProperties(iterable $name)
此期望可確保 $value
具有與 $names
中所有名稱相符的屬性名稱。
1expect($user)->toHaveProperties(['name', 'email']);
此外,您可以使用關聯陣列驗證多個屬性的名稱和值。
1expect($user)->toHaveProperties([2 'name' => 'Nuno',3 'email' => 'enunomaduro@gmail.com'4]);
toMatchArray($array)
此期望可確保 $value
陣列與指定的 $array
子集相符。
1$user = [ 2 'id' => 1, 3 'name' => 'Nuno', 4 'email' => 'enunomaduro@gmail.com', 5 'is_active' => true, 6]; 7 8expect($user)->toMatchArray([ 9 'email' => 'enunomaduro@gmail.com',10 'name' => 'Nuno'11]);
toMatchObject($object)
此期望可確保 $value
物件符合已提供 $object
部份屬性的子集。
1$user = new stdClass();2$user->id = 1;3$user->email = 'enunomaduro@gmail.com';4$user->name = 'Nuno';5 6expect($user)->toMatchObject([7 'email' => 'enunomaduro@gmail.com',8 'name' => 'Nuno'9]);
toEqual($expected)
此期望可確保 $value
和 $expected
具有相同的數值。
1expect($title)->toEqual('Hello World');2expect('1')->toEqual(1);3expect(new StdClass())->toEqual(new StdClass());
toEqualCanonicalizing($expected)
此期望可確保 $value
和 $expected
具有相同的數值,不論提供元素的順序為何。
1$usersAsc = ['Dan', 'Fabio', 'Nuno'];2$usersDesc = ['Nuno', 'Fabio', 'Dan'];3 4expect($usersAsc)->toEqualCanonicalizing($usersDesc);5expect($usersAsc)->not->toEqual($usersDesc);
toEqualWithDelta($expected, float $delta)
此期望可確保 $value
和 $expected
的絕對差低於 $delta
。
1expect($durationInMinutes)->toEqualWithDelta(10, 5); //duration of 10 minutes with 5 minutes tolerance2 3expect(14)->toEqualWithDelta(10, 5); // Pass4expect(14)->toEqualWithDelta(10, 0.1); // Fail
toBeIn()
此期望可確保 $value
是其中一個給定值。
1expect($newUser->status)->toBeIn(['pending', 'new', 'active']);
toBeInfinite()
此期望可確保 $value
無限大。
1expect(log(0))->toBeInfinite();
toBeInstanceOf($class)
此期望可確保 $value
是 $class
的實例。
1expect($user)->toBeInstanceOf(User::class);
toBeArray()
此期望可確保 $value
是個陣列。
1expect(['Pest','PHP','Laravel'])->toBeArray();
toBeBool()
此期望可確保 $value
的類型為布林。
1expect($isActive)->toBeBool();
toBeCallable()
此期望可確保 $value
的類型可呼叫。
1$myFunction = function () {};2 3expect($myFunction)->toBeCallable();
toBeFile()
此期望可確保字串 $value
為現有的檔案。
1expect('/tmp/some-file.tmp')->toBeFile();
toBeFloat()
此期望可確保 $value
的類型為浮點數。
1expect($height)->toBeFloat();
toBeInt()
此期望可確保 $value
的類型為整數。
1expect($count)->toBeInt();
toBeIterable()
此期望可確保 $value
的類型可迭代。
1expect($array)->toBeIterable();
toBeNumeric()
此期望可確保 $value
的類型為數值。
1expect($age)->toBeNumeric();2expect(10)->toBeNumeric();3expect('10')->toBeNumeric();
toBeDigits()
此預期值確保 $value
僅包含數字。
1expect($year)->toBeDigits();2expect(15)->toBeDigits();3expect('15')->toBeDigits();
toBeObject()
此預期值確保 $value
的型別為物件。
1$object = new stdClass();2 3expect($object)->toBeObject();
toBeResource()
此預期值確保 $value
的型別為資源。
1$handle = fopen('php://memory', 'r+');2 3expect($handle)->toBeResource();
toBeScalar()
此預期值確保 $value
的型別為純量。
1expect('1')->toBeScalar();2expect(1)->toBeScalar();3expect(1.0)->toBeScalar();4expect(true)->toBeScalar();5expect([1, '1'])->not->toBeScalar();
toBeString()
此預期值確保 $value
的型別為字串。
1expect($string)->toBeString();
toBeJson()
此預期值確保 $value
是 JSON 字串。
1expect('{"hello":"world"}')->toBeJson();
toBeNan()
此預期值確保 $value
不是數字 (NaN)。
1expect(sqrt(-1))->toBeNan();
toBeNull()
此預期值確保 $value
是 null。
1expect(null)->toBeNull();
toHaveKey(string $key)
此預期值確保 $value
包含提供的 $key
。
1expect(['name' => 'Nuno', 'surname' => 'Maduro'])->toHaveKey('name');2expect(['name' => 'Nuno', 'surname' => 'Maduro'])->toHaveKey('name', 'Nuno');3expect(['user' => ['name' => 'Nuno', 'surname' => 'Maduro']])->toHaveKey('user.name');4expect(['user' => ['name' => 'Nuno', 'surname' => 'Maduro']])->toHaveKey('user.name', 'Nuno');
toHaveKeys(array $keys)
此預期值確保 $value
包含提供的 $keys
。
1expect(['id' => 1, 'name' => 'Nuno'])->toHaveKeys(['id', 'name']);2expect(['message' => ['from' => 'Nuno', 'to' => 'Luke'] ])->toHaveKeys(['message.from', 'message.to']);
toHaveLength(int $number)
此預期值確保提供的 $number
與字串 $value
的長度或可迭代 $value
中的元素數目相符。
1expect('Pest')->toHaveLength(4);2expect(['Nuno', 'Maduro'])->toHaveLength(2);
toBeDirectory()
此預期值確保字串 $value
是目錄。
1expect('/tmp')->toBeDirectory();
toBeReadableDirectory()
此預期值確保字串 $value
是目錄且可讀取。
1expect('/tmp')->toBeReadableDirectory();
toBeReadableFile()
此預期值確保字串 $value
是檔案且可讀取。
1expect('/tmp/some-file.tmp')->toBeReadableFile();
toBeWritableDirectory()
此預期值確保字串 $value
是目錄且可寫入。
1expect('/tmp')->toBeWritableDirectory();
toBeWritableFile()
此預期值確保字串 $value
是檔案且可寫入。
1expect('/tmp/some-file.tmp')->toBeWritableFile();
toStartWith(string $expected)
此預期值確保 $value
以提供的字串開頭。
1expect('Hello World')->toStartWith('Hello');
toThrow()
此預期值確保封閉會擲出特定的例外類別、例外訊息,或兩者皆是。
1expect(fn() => throw new Exception('Something happened.'))->toThrow(Exception::class);2expect(fn() => throw new Exception('Something happened.'))->toThrow('Something happened.');3expect(fn() => throw new Exception('Something happened.'))->toThrow(Exception::class, 'Something happened.');4expect(fn() => throw new Exception('Something happened.'))->toThrow(new Exception('Something happened.'));
toMatch(string $expression)
此預期值確保 $value
與正規表示式相符。
1expect('Hello World')->toMatch('/^hello wo.*$/i');
toEndWith(字串 $預期值)
此預期值確保 $值
以提供的字串結尾。
1expect('Hello World')->toEndWith('World');
toMatchConstraint(約束 $約束)
此預期值確保 $值
相符特定的 PHPUnit 約束。
1use PHPUnit\Framework\Constraint\IsTrue;2 3expect(true)->toMatchConstraint(new IsTrue());
toBeUppercase(字串 $預期值)
此預期值確保 $值
為大寫。
1expect('PESTPHP')->toBeUppercase();
toBeLowercase(字串 $預期值)
此預期值確保 $值
為小寫。
1expect('pestphp')->toBeLowercase();
toBeAlpha(字串 $預期值)
此預期值確保 $值
僅包含英文字母字元。
1expect('pestphp')->toBeAlpha();
toBeAlphaNumeric(字串 $預期值)
此預期值確保 $值
僅包含英數字元。
1expect('pestPHP123')->toBeAlphaNumeric();
toBeSnakeCase()
此預期值確保 $值
僅包含蛇形大小寫格式的字串。
1expect('snake_case')->toBeSnakeCase();
toBeKebabCase()
此預期值確保 $值
僅包含連字號大小寫格式的字串。
1expect('kebab-case')->toBeKebabCase();
toBeCamelCase()
此預期值確保 $值
僅包含駝峰大小寫格式的字串。
1expect('camelCase')->toBeCamelCase();
toBeStudlyCase()
此預期值確保 $值
僅包含帕斯卡大小寫格式的字串。
1expect('StudlyCase')->toBeStudlyCase();
toHaveSnakeCaseKeys()
此預期值確保 $值
僅包含鍵值為蛇形大小寫格式的陣列。
1expect(['snake_case' => 'abc123'])->toHaveSnakeCaseKeys();
toHaveKebabCaseKeys()
此預期值確保 $值
僅包含鍵值為連字號大小寫格式的陣列。
1expect(['kebab-case' => 'abc123'])->toHaveKebabCaseKeys();
toHaveCamelCaseKeys()
此預期值確保 $值
僅包含鍵值為駝峰大小寫格式的陣列。
1expect(['camelCase' => 'abc123'])->toHaveCamelCaseKeys();
toHaveStudlyCaseKeys()
此預期值確保 $值
僅包含鍵值為帕斯卡大小寫格式的陣列。
1expect(['StudlyCase' => 'abc123'])->toHaveStudlyCaseKeys();
toHaveSameSize()
此預期值確保 $值
與提供的可疊代物件的大小相同。
1expect(['foo', 'bar'])->toHaveSameSize(['baz', 'bazz']);
toBeUrl()
此預期值確保 $值
為 URL。
1expect('https://pest.dev.org.tw/')->toBeUrl();
toBeUuid()
此預期值確保 $值
為 UUID。
1expect('ca0a8228-cdf6-41db-b34b-c2f31485796c')->toBeUuid();
and($值)
and()
修飾子允許您傳遞新的 $值
,讓您在單一測試中串連多個預期值。
1expect($id)->toBe(14)2 ->and($name)->toBe('Nuno');
dd()
dd()
修飾子
使用 dd()
修改器允許你轉儲目前預期的 $value
,並中止程式碼執行。這在除錯時會很有用,可以讓你檢測在測試中某個特定時間點上,$value
的目前狀態。
1expect(14)->dd(); // 142expect([1, 2])->sequence(3 fn ($number) => $number->toBe(1),4 fn ($number) => $number->dd(), // 25);
ddWhen($condition)
使用 ddWhen()
修改器允許你在指定 $condition
為真時,轉儲目前預期的 $value
並中止程式碼執行。
1expect([1, 2])->each(2 fn ($number) => $number->ddWhen(fn (int $number) => $number === 2) // 23);
ddUnless($condition)
使用 ddUnless()
修改器允許你在指定 $condition
為假時,轉儲目前預期的 $value
並中止程式碼執行。
1expect([1, 2])->each(2 fn ($number) => $number->ddUnless(fn (int $number) => $number === 1) // 23);
each()
each()
修改器允許你針對可迭代物件的每一個項目建立預期。它的運作方式是迭代可迭代物件上的每個項目,並對每一個項目套用預期。
1expect([1, 2, 3])->each->toBeInt();2expect([1, 2, 3])->each->not->toBeString();3expect([1, 2, 3])->each(fn ($number) => $number->toBeLessThan(4));
json()
json()
修改器將目前預期的 $value
從 JSON 編碼為陣列。
1expect('{"name":"Nuno","credit":1000.00}')2 ->json()3 ->toHaveCount(2)4 ->name->toBe('Nuno')5 ->credit->toBeFloat();6 7expect('not-a-json')->json(); //Fails
match()
match()
修改器會執行與第一個陣列鍵相關聯的封閉,其值與提供給該方法的第一個引數中值相符。
1expect($user->miles)2 ->match($user->status, [3 'new' => fn ($userMiles) => $userMiles->ToBe(0),4 'gold' => fn ($userMiles) => $userMiles->toBeGreaterThan(500),5 'platinum' => fn ($userMiles) => $userMiles->toBeGreaterThan(1000),6 ]);
若要檢查預期值是否等於與配對鍵相關聯的值,你可以直接將預期值傳遞為陣列值,而不使用封閉。
1expect($user->default_language)2 ->match($user->country, [3 'PT' => 'Português',4 'US' => 'English',5 'TR' => 'Türkçe',6 ]);
not
not
修改器允許反轉後續預期。
1expect(10)->not->toBeGreaterThan(100);2expect(true)->not->toBeFalse();
ray()
ray()
修改器允許你透過 myray.app 除錯目前的 $value
。
1expect(14)->ray(); // 142expect([1, 2])->sequence(3 fn ($number) => $number->toBe(1),4 fn ($number) => $number->ray(), // 25);
sequence()
sequence()
修改器允許你為單一可迭代物件指定順序預期的組合。
1expect([1, 2, 3])->sequence(2 fn ($number) => $number->toBe(1),3 fn ($number) => $number->toBe(2),4 fn ($number) => $number->toBe(3),5);
sequence()
修改器也可使用於關聯式可迭代物件。每一個封閉在順序中會收到兩個引數:第一個引數是值預期,第二個引數是鍵預期。
1expect(['hello' => 'world', 'foo' => 'bar', 'john' => 'doe'])->sequence(2 fn ($value, $key) => $value->toEqual('world'),3 fn ($value, $key) => $key->toEqual('foo'),4 fn ($value, $key) => $value->toBeString(),5);
sequence()
修改器也可使用於檢查可迭代物件中的各個值是否配對一組預期值。在這種情況下,你可以直接將預期值傳遞給 sequence() 方法,而不使用封閉。
1expect(['foo', 'bar', 'baz'])->sequence('foo', 'bar', 'baz');
when()
when()
修改器在傳遞給該方法的第一個引數評量為真時執行所提供的呼叫回程式。
1expect($user)2 ->when($user->is_verified === true, fn ($user) => $user->daily_limit->toBeGreaterThan(10))3 ->email->not->toBeEmpty();
unless()
unless()
修改器在傳遞給該方法的第一個引數評量為假時執行所提供的呼叫回程式。
1expect($user)2 ->unless($user->is_verified === true, fn ($user) => $user->daily_limit->toBe(10))3 ->email->not->toBeEmpty();
在學習如何撰寫預期後,文件中的下一節,"Hooks",涵蓋了有用的函式,例如"beforeEach" 與 "afterEach",可協助設定測試的前置條件和清除動作: Hooks →