Pest testing framework has many fans, mainly because of its elegant, readable "English language" syntax. In this article, I will show you my 3 favorite expect()
syntax examples, comparing the same things in Pest vs PHPUnit.
Notice: Generally, this topic is very opinionated, and the syntax is your personal preference. There is a Reddit post from a year ago where people argue against that Pest syntax. But I personally like it. Let me show you the examples.
1. expect() Object Properties in One Sentence
Let me just show you a real Pest example from open-source project Larastreamers by Christoph Rumpel:
it('can fetch channel details from youtube', function() { // Act $channel = YouTube::channel('UCdtd5QYBx9MUVXHm7qgEpxA'); // Assert expect($channel) ->youTubeCustomUrl->toBe('christophrumpel') ->name->toBe('Christoph Rumpel') ->description->toStartWith('Hi, I\'m Christoph Rumpel') ->onPlatformSince->toIso8601String()->toBe('2010-01-12T19:15:29+00:00') ->country->toBe('AT') ->thumbnailUrl->toBe('https://yt3.ggpht.com/ytc/AAUvwniFZUkXnS4vDKY4lDohrpFsyu1V2AJwt4CFZGy25Q=s800-c-k-c0x00ffffff-no-rj');});
See that expect()
with chained methods?
If you have an object/array and want to check its parts for different values, you can do it in one sentence.
A similar functionality in PHPUnit would look like this:
public function testCanFetchChannelDetailsFromYoutube(){ // Act $channel = YouTube::channel('UCdtd5QYBx9MUVXHm7qgEpxA'); // Assert $this->assertEquals('christophrumpel', $channel->youTubeCustomUrl); $this->assertEquals('Christoph Rumpel', $channel->name); $this->assertStringStartsWith('Hi, I\'m Christoph Rumpel', $channel->description); $this->assertEquals('2010-01-12T19:15:29+00:00', $channel->onPlatformSince->toIso8601String()); $this->assertEquals('AT', $channel->country); $this->assertEquals('https://yt3.ggpht.com/ytc/AAUvwniFZUkXnS4vDKY4lDohrpFsyu1V2AJwt4CFZGy25Q=s800-c-k-c0x00ffffff-no-rj', $channel->thumbnailUrl); }
You can see three repeating parts here:
-
$this->
-
$channel->
- and
assertEquals()
or even longerassertStringStartsWith()
Each assertion is a separate PHP statement.
Pest "chain" syntax is shorter and more elegant. Again, in my opinion.
2. Expect X AND Y
Another Pest example is checking the class and its contents in the same sentence.
test('users table contains pagination', function () { $resp = actingAs($this->admin) ->get(route('users.index')); $users = $resp->original->getData()['users']; expect($users) ->toBeInstanceOf(\Illuminate\Pagination\LengthAwarePaginator::class) ->and($users->perPage()) ->toBe(20);});
The same code with PHPUnit:
public function testUsersTableContainsPagination(){ $resp = $this->actingAs($this->admin) ->get(route('users.index')); $users = $resp->original->getData()['users']; $this->assertInstanceOf(\Illuminate\Pagination\LengthAwarePaginator::class, $users); $this->assertEquals(20, $users->perPage());}
In this case, it's not shorter but still more readable to me, as the assertion of the same variable is grouped in the same sentence instead of having two separate ones.
3. Expect (NOT) toContain()
Oh, and did I mention the syntax of the not
with expect()
?
Pest:
test('correct file can be seen on projects edit page', function () { // ... $resp = actingAs($this->user) ->get(route('projects.edit', $this->project)); expect($resp->content()) ->toContain('project-file.pdf') ->not->toContain('task-file.pdf');});
Two assertions in one sentence. Cool, right? Right?..
PHPUnit version:
public function testCorrectFileCanBeSeenOnProjectsEditPage(){ $resp = $this->actingAs($user) ->get(route('projects.edit', $project)); $resp->assertSeeText('project-file.pdf'); $resp->assertDontSeeText('task-file.pdf');}
It's personal preference, as I mentioned, but Pest syntax reads more "human" to me.
What do you think? Yay or Nay?
In Laravel Daily courses, we try to show code examples of both Pest and PHPUnit. Check them out:
No comments or questions yet...