// docs / expectations

Expectations

By setting expectations with the Pest expectation API, you may quickly surface bugs and other issues in your code. The API allows you to specify the expected outcome of a test, making any deviation from that behavior easy to detect.

You may start an expectation by passing your value to the expect($value) function. You will reach for expect() every time you want to test a value. However, you will rarely call it on its own; instead, you will pair expect() with an "expectation" method to assert something about the value:

1test('sum', function () {
2 $value = sum(1, 2);
3 
4 expect($value)->toBe(3); // Assert that the value is 3...
5});

In addition, the expect() function allows you to chain multiple expectations together for a given $value. This means you may perform as many checks as you need in a single test by continuing to chain additional expectations:

1expect($value)
2 ->toBeInt()
3 ->toBe(3);

At any time, you may test the opposite of an expectation by prepending the not modifier to the expectation:

1expect($value)
2 ->toBeInt()
3 ->toBe(3)
4 ->not->toBeString() // Not to be string...
5 ->not->toBe(4); // Not to be 4...

With the Pest expectation API, you have access to an extensive collection of individual expectations designed to test various aspects of your code. Below is a comprehensive list of the available expectations.

In addition to the individual expectations, the expectation API also provides several modifiers that allow you to further customize your tests. You may use these modifiers to create more complex expectations and to test multiple values at once. Here are some of the modifiers available in Pest:

toBe()

This expectation ensures that both $value and $expected share the same type and value.

If used with objects, it ensures that both variables refer to the exact same object:

1expect(1)->toBe(1);
2expect('1')->not->toBe(1);
3expect(new StdClass())->not->toBe(new StdClass());

toBeBetween()

This expectation ensures that $value is between two values. It works with int, float, and 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()

This expectation ensures that $value is empty:

1expect('')->toBeEmpty();
2expect([])->toBeEmpty();
3expect(null)->toBeEmpty();

toBeTrue()

This expectation ensures that $value is true:

1expect($isPublished)->toBeTrue();

toBeTruthy()

This expectation ensures that $value is truthy:

1expect(1)->toBeTruthy();
2expect('1')->toBeTruthy();

toBeFalse()

This expectation ensures that $value is false:

1expect($isPublished)->toBeFalse();

toBeFalsy()

This expectation ensures that $value is falsy:

1expect(0)->toBeFalsy();
2expect('')->toBeFalsy();

toBeGreaterThan($expected)

This expectation ensures that $value is greater than $expected:

1expect($count)->toBeGreaterThan(20);

toBeGreaterThanOrEqual($expected)

This expectation ensures that $value is greater than or equal to $expected:

1expect($count)->toBeGreaterThanOrEqual(21);

toBeLessThan($expected)

This expectation ensures that $value is less than $expected:

1expect($count)->toBeLessThan(3);

toBeLessThanOrEqual($expected)

This expectation ensures that $value is less than or equal to $expected:

1expect($count)->toBeLessThanOrEqual(2);

toContain($needles)

This expectation ensures that all the given needles are elements of the $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)

This expectation ensures that all the given needles are elements (in terms of equality) of the $value:

1expect([1, 2, 3])->toContainEqual('1');
2expect([1, 2, 3])->toContainEqual('1', '2');

toContainOnlyInstancesOf($class)

This expectation ensures that $value contains only instances of $class:

1$dates = [new DateTime(), new DateTime()];
2 
3expect($dates)->toContainOnlyInstancesOf(DateTime::class);

toHaveCount(int $count)

This expectation ensures that the $count provided matches the number of elements in an iterable $value:

1expect(['Nuno', 'Luke', 'Alex', 'Dan'])->toHaveCount(4);

toHaveProperty(string $name, $value = null)

This expectation ensures that $value has a property named $name.

In addition, you may verify the actual value of a property by providing a second argument:

1expect($user)->toHaveProperty('name');
2expect($user)->toHaveProperty('name', 'Nuno');
3expect($user)->toHaveProperty('is_active', 'true');

toHaveProperties(iterable $name)

This expectation ensures that $value has property names matching all the names contained in $names:

1expect($user)->toHaveProperties(['name', 'email']);

In addition, you may verify the name and value of multiple properties using an associative array:

1expect($user)->toHaveProperties([
2 'name' => 'Nuno',
3 'email' => 'enunomaduro@gmail.com'
4]);

toMatchArray($array)

This expectation ensures that the $value array matches the given $array subset:

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)

This expectation ensures that the $value object matches a subset of the properties of a given $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)

This expectation ensures that $value and $expected have the same value:

1expect($title)->toEqual('Hello World');
2expect('1')->toEqual(1);
3expect(new StdClass())->toEqual(new StdClass());

toEqualCanonicalizing($expected)

This expectation ensures that $value and $expected have the same values, no matter what order the elements are given in:

1$usersAsc = ['Dan', 'Fabio', 'Nuno'];
2$usersDesc = ['Nuno', 'Fabio', 'Dan'];
3 
4expect($usersAsc)->toEqualCanonicalizing($usersDesc);
5expect($usersAsc)->not->toEqual($usersDesc);

toEqualWithDelta($expected, float $delta)

This expectation ensures that the absolute difference between $value and $expected is lower than $delta:

1expect($durationInMinutes)->toEqualWithDelta(10, 5); //duration of 10 minutes with 5 minutes tolerance
2 
3expect(14)->toEqualWithDelta(10, 5); // Pass
4expect(14)->toEqualWithDelta(10, 0.1); // Fail

toBeIn()

This expectation ensures that $value is one of the given values:

1expect($newUser->status)->toBeIn(['pending', 'new', 'active']);

toBeInfinite()

This expectation ensures that $value is infinite:

1expect(log(0))->toBeInfinite();

toBeInstanceOf($class)

This expectation ensures that $value is an instance of $class:

1expect($user)->toBeInstanceOf(User::class);

toBeArray()

This expectation ensures that $value is an array:

1expect(['Pest','PHP','Laravel'])->toBeArray();

toBeBool()

This expectation ensures that $value is of type bool:

1expect($isActive)->toBeBool();

toBeCallable()

This expectation ensures that $value is of type callable:

1$myFunction = function () {};
2 
3expect($myFunction)->toBeCallable();

toBeFile()

This expectation ensures that the string $value is an existing file:

1expect('/tmp/some-file.tmp')->toBeFile();

toBeFloat()

This expectation ensures that $value is of type float:

1expect($height)->toBeFloat();

toBeInt()

This expectation ensures that $value is of type integer:

1expect($count)->toBeInt();

toBeIterable()

This expectation ensures that $value is of type iterable:

1expect($array)->toBeIterable();

toBeNumeric()

This expectation ensures that $value is of type numeric:

1expect($age)->toBeNumeric();
2expect(10)->toBeNumeric();
3expect('10')->toBeNumeric();

toBeDigits()

This expectation ensures that $value contains only digits:

1expect($year)->toBeDigits();
2expect(15)->toBeDigits();
3expect('15')->toBeDigits();
4expect(0.123)->not->toBeDigits();
5expect('0.123')->not->toBeDigits();

toBeObject()

This expectation ensures that $value is of type object:

1$object = new stdClass();
2 
3expect($object)->toBeObject();

toBeResource()

This expectation ensures that $value is of type resource:

1$handle = fopen('php://memory', 'r+');
2 
3expect($handle)->toBeResource();

toBeScalar()

This expectation ensures that $value is of type scalar:

1expect('1')->toBeScalar();
2expect(1)->toBeScalar();
3expect(1.0)->toBeScalar();
4expect(true)->toBeScalar();
5expect([1, '1'])->not->toBeScalar();

toBeString()

This expectation ensures that $value is of type string:

1expect($string)->toBeString();

toBeJson()

This expectation ensures that $value is a JSON string:

1expect('{"hello":"world"}')->toBeJson();

toBeNan()

This expectation ensures that $value is not a number (NaN):

1expect(sqrt(-1))->toBeNan();

toBeNull()

This expectation ensures that $value is null:

1expect(null)->toBeNull();

toHaveKey(string $key)

This expectation ensures that $value contains the provided $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)

This expectation ensures that $value contains the provided $keys:

1expect(['id' => 1, 'name' => 'Nuno'])->toHaveKeys(['id', 'name']);
2expect(['message' => ['from' => 'Nuno', 'to' => 'Luke'] ])->toHaveKeys(['message.from', 'message.to']);

toHaveLength(int $number)

This expectation ensures that the provided $number matches the length of a string $value or the number of elements in an iterable $value:

1expect('Pest')->toHaveLength(4);
2expect(['Nuno', 'Maduro'])->toHaveLength(2);

toBeDirectory()

This expectation ensures that the string $value is a directory:

1expect('/tmp')->toBeDirectory();

toBeReadableDirectory()

This expectation ensures that the string $value is a directory and that it is readable:

1expect('/tmp')->toBeReadableDirectory();

toBeReadableFile()

This expectation ensures that the string $value is a file and that it is readable:

1expect('/tmp/some-file.tmp')->toBeReadableFile();

toBeWritableDirectory()

This expectation ensures that the string $value is a directory and that it is writable:

1expect('/tmp')->toBeWritableDirectory();

toBeWritableFile()

This expectation ensures that the string $value is a file and that it is writable:

1expect('/tmp/some-file.tmp')->toBeWritableFile();

toStartWith(string $expected)

This expectation ensures that $value starts with the provided string:

1expect('Hello World')->toStartWith('Hello');

toThrow()

This expectation ensures that a closure throws a specific exception class, exception message, or both:

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)

This expectation ensures that $value matches a regular expression:

1expect('Hello World')->toMatch('/^hello wo.*$/i');

toEndWith(string $expected)

This expectation ensures that $value ends with the provided string:

1expect('Hello World')->toEndWith('World');

toMatchConstraint(Constraint $constraint)

This expectation ensures that $value matches a specified PHPUnit constraint:

1use PHPUnit\Framework\Constraint\IsTrue;
2 
3expect(true)->toMatchConstraint(new IsTrue());

toBeUppercase(string $expected)

This expectation ensures that $value is uppercase:

1expect('PESTPHP')->toBeUppercase();

toBeLowercase(string $expected)

This expectation ensures that $value is lowercase:

1expect('pestphp')->toBeLowercase();

toBeAlpha(string $expected)

This expectation ensures that $value only contains alpha characters:

1expect('pestphp')->toBeAlpha();

toBeAlphaNumeric(string $expected)

This expectation ensures that $value only contains alphanumeric characters:

1expect('pestPHP123')->toBeAlphaNumeric();

toBeSnakeCase()

This expectation ensures that $value only contains string in snake_case format:

1expect('snake_case')->toBeSnakeCase();

toBeKebabCase()

This expectation ensures that $value only contains string in kebab-case format:

1expect('kebab-case')->toBeKebabCase();

toBeCamelCase()

This expectation ensures that $value only contains string in camelCase format:

1expect('camelCase')->toBeCamelCase();

toBeStudlyCase()

This expectation ensures that $value only contains string in StudlyCase format:

1expect('StudlyCase')->toBeStudlyCase();

toHaveSnakeCaseKeys()

This expectation ensures that $value only contains an array with keys in snake_case format:

1expect(['snake_case' => 'abc123'])->toHaveSnakeCaseKeys();

toHaveKebabCaseKeys()

This expectation ensures that $value only contains an array with keys in kebab-case format:

1expect(['kebab-case' => 'abc123'])->toHaveKebabCaseKeys();

toHaveCamelCaseKeys()

This expectation ensures that $value only contains an array with keys in camelCase format:

1expect(['camelCase' => 'abc123'])->toHaveCamelCaseKeys();

toHaveStudlyCaseKeys()

This expectation ensures that $value only contains an array with keys in StudlyCase format:

1expect(['StudlyCase' => 'abc123'])->toHaveStudlyCaseKeys();

toHaveSameSize()

This expectation ensures that the size of $value and the provided iterable are the same:

1expect(['foo', 'bar'])->toHaveSameSize(['baz', 'bazz']);

toBeEmail()

This expectation ensures that $value is a valid email address:

1expect('user@example.com')->toBeEmail();

toBeUrl()

This expectation ensures that $value is a URL:

1expect('https://pestphp.com/')->toBeUrl();

toBeUuid()

This expectation ensures that $value is a UUID:

1expect('ca0a8228-cdf6-41db-b34b-c2f31485796c')->toBeUuid();

toBeUlid()

This expectation ensures that $value is a ULID:

1expect('01ARZ3NDEKTSV4RRFFQ69G5FAV')->toBeUlid();

toBeBase64()

This expectation ensures that $value is a valid base64-encoded string:

1expect('Zm9vYmFy')->toBeBase64();

toBeDomain()

This expectation ensures that $value is a valid domain name:

1expect('example.com')->toBeDomain();

toBeHexadecimal()

This expectation ensures that $value is a valid hexadecimal string:

1expect('deadbeef')->toBeHexadecimal();

toBeHostname()

This expectation ensures that $value is a valid hostname:

1expect('example.com')->toBeHostname();

toBeIpAddress()

This expectation ensures that $value is a valid IP address:

1expect('192.168.1.1')->toBeIpAddress();

toBeMacAddress()

This expectation ensures that $value is a valid MAC address:

1expect('00:1a:2b:3c:4d:5e')->toBeMacAddress();

and($value)

The and() modifier allows you to pass a new $value, enabling you to chain multiple expectations in a single test:

1expect($id)->toBe(14)
2 ->and($name)->toBe('Nuno');

dd()

The dd() modifier allows you to dump the current expectation $value and stop code execution. This can be helpful for debugging, allowing you to inspect the current state of the $value at a particular point in your test:

1expect(14)->dd(); // 14
2expect([1, 2])->sequence(
3 fn ($number) => $number->toBe(1),
4 fn ($number) => $number->dd(), // 2
5);

ddWhen($condition)

The ddWhen() modifier allows you to dump the current expectation $value and stop code execution when the given $condition is truthy:

1expect([1, 2])->each(
2 fn ($number) => $number->ddWhen(fn (int $number) => $number === 2) // 2
3);

ddUnless($condition)

The ddUnless() modifier allows you to dump the current expectation $value and stop code execution when the given $condition is falsy:

1expect([1, 2])->each(
2 fn ($number) => $number->ddUnless(fn (int $number) => $number === 1) // 2
3);

each()

The each() modifier allows you to create an expectation on each item of the given iterable. It works by iterating over the iterable and applying the expectation to each item:

1expect([1, 2, 3])->each->toBeInt();
2expect([1, 2, 3])->each->not->toBeString();
3expect([1, 2, 3])->each(fn ($number) => $number->toBeLessThan(4));
4expect([1, 2, 3])->each(fn ($number, $key) => $number->toEqual($key + 1));

json()

The json() modifier decodes the current expectation $value from JSON to an array:

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()

The match() modifier executes the closure associated with the first array key that matches the value of the first argument given to the method:

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 ]);

To check whether the expected value is equal to the value associated with the matching key, you may pass the expected value directly as the array value instead of using a closure:

1expect($user->default_language)
2 ->match($user->country, [
3 'PT' => 'Português',
4 'US' => 'English',
5 'TR' => 'Türkçe',
6 ]);

not

The not modifier allows you to invert the subsequent expectation:

1expect(10)->not->toBeGreaterThan(100);
2expect(true)->not->toBeFalse();

ray()

The ray() modifier allows you to debug the current $value with myray.app:

1expect(14)->ray(); // 14
2expect([1, 2])->sequence(
3 fn ($number) => $number->toBe(1),
4 fn ($number) => $number->ray(), // 2
5);

sequence()

The sequence() modifier allows you to specify a sequential set of expectations for a single iterable:

1expect([1, 2, 3])->sequence(
2 fn ($number) => $number->toBe(1),
3 fn ($number) => $number->toBe(2),
4 fn ($number) => $number->toBe(3),
5);

The sequence() modifier can also be used with associative iterables. Each closure in the sequence will receive two arguments: the first argument being the expectation for the value and the second argument being the expectation for the key:

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);

The sequence() modifier may also be used to check whether each value in the iterable matches a set of expected values. In this case, you may pass the expected values directly to the sequence() method instead of using closures:

1expect(['foo', 'bar', 'baz'])->sequence('foo', 'bar', 'baz');

when()

The when() modifier runs the provided callback when the first argument passed to the method evaluates to true:

1expect($user)
2 ->when($user->is_verified === true, fn ($user) => $user->daily_limit->toBeGreaterThan(10))
3 ->email->not->toBeEmpty();

unless()

The unless() modifier runs the provided callback when the first argument passed to the method evaluates to false:

1expect($user)
2 ->unless($user->is_verified === true, fn ($user) => $user->daily_limit->toBe(10))
3 ->email->not->toBeEmpty();

Now that you know how to write expectations, the next section covers hooks: helpful functions such as beforeEach() and afterEach() that you may use to set up preconditions and cleanup actions for your tests: Hooks →