Courses

Testing in Laravel 12 For Beginners

AAA: Arrange, Act, Assert

Summary of this lesson:
- Understanding Arrange-Act-Assert testing pattern
- Using AAA pattern in Laravel tests
- Implementing each phase of the pattern
- Best practices for test structure and organization

In this lesson, we will not write code but look at a typical "plan" behind every test method.

One of the most common ways to write tests is to divide any function into three phases, and they all start with an "A" letter. It's a "AAA". You can call it a 3-step framework:

  • Arrange
  • Act
  • Assert

In most cases, you should stick to this plan for every function in your test.


Step 1. Arrange.

You can call it a "preparation" step.

Add any data you need, any configuration. Build the scenario.

test('homepage contains non empty table', function () {
Product::create([
'name' => 'Product 1',
'price' => 123,
]);
 
get('/products')
->assertStatus(200)
->assertDontSee(__('No products found'));
});

Step 2. Act.

This step is usually about calling some URL, API endpoint, or function. So, simulate the actual action of the user, like you would be behind the browser doing the same thing.

test('homepage contains non empty table', function () {
Product::create([
'name' => 'Product 1',
'price' => 123,
]);
 
get('/products')
->assertStatus(200)
->assertDontSee(__('No products found'));
});

Step 3. Assert.

This is where you check what happened after your main action.

There can be multiple assertions. For example, we can assert the status, assert that you (don't) see some text, or that you see the product's name.

test('homepage contains non empty table', function () {
Product::create([
'name' => 'Product 1',
'price' => 123,
]);
 
get('/products')
->assertStatus(200)
->assertDontSee(__('No products found'));
});

PHPUnit example

As usual, at the end of the lesson, the same topic but with the PHPUnit code.

Arrange

public function test_homepage_contains_non_empty_table(): void
{
Product::create([
'name' => 'Product 1',
'price' => 123,
]);
 
$response = $this->get('/products');
 
$response->assertStatus(200);
$response->assertDontSee(__('No products found'));
}

Act

public function test_homepage_contains_non_empty_table(): void
{
Product::create([
'name' => 'Product 1',
'price' => 123,
]);
 
$response = $this->get('/products');
 
$response->assertStatus(200);
$response->assertDontSee(__('No products found'));
}

Assert

public function test_homepage_contains_non_empty_table(): void
{
Product::create([
'name' => 'Product 1',
'price' => 123,
]);
 
$response = $this->get('/products');
 
$response->assertStatus(200);
$response->assertDontSee(__('No products found'));
$response->assertSee('Product 1');
}

AAA: In Summary

Typically, the Arrange step contains multiple operations. Or, sometimes, no preparation needed at all.

Then, the Act step is usually a single call for the action.

Finally, the Assert step usually contains multiple assertions.

That said, you shouldn't over-push with multiple assertions because you may bump into testing different scenarios. So, sometimes, multiple assertions mean that it should become a separate test method.

avatar

Could you kindly also indicate in the image which stage you are referring to?

avatar

Sorry, could you explain what do you mean by this?

avatar

Vance is probabbly referring to the PEST code where same code is used under Arrange, Act and Assert without any parts being bolded or otherwise marked. Though I doubt this will confuse many, you might just want to put 1 example with comments:

	test('homepage contains non empty table', function () {
			// Arrange
			Product::create([
					'name'  => 'Product 1',
					'price' => 123,
			]);

			// Act
			get('/products') 

			// Assert
					->assertStatus(200)
					->assertDontSee(__('No products found'));
	});
avatar

From this pag, nobody can unserstand what is Arrange, Act, Assert.

avatar
You can use Markdown
avatar
You can use Markdown