CodeBlanks Logo Icon CodeBlanks

Test layout (AAA)

PHP course · Advanced · Lesson 77/92

Learn the Arrange-Act-Assert test layout.

The AAA pattern

AAA is a pattern for writing tests in three parts: Arrange (prepare), Act (run), Assert (check). First you set up the needed objects (Arrange), then you call the method under test (Act), finally you check the result (Assert). This layout makes the test readable; a new reader sees the intent at once. Some teams use the names Given/When/Then; they mean the same thing.

Given/When/Then

Given/When/Then is a behaviour-driven wording of AAA. Given describes the starting state: Given an empty cart. When tells the action: When bread is added. Then states the expected result: Then the cart has 1 item. Because it reads like a sentence, it helps when working with business analysts. In code it still maps to Arrange/Act/Assert.

Exercise Write a test in AAA layout

The borrow method of Library lends a book and returns true. Make LibraryTest extend TestCase. Write testBorrow in AAA layout: in Arrange create a new Library with the "Heidi" book, in Act call borrow, in Assert check the result is true with assertEquals and the remaining count is 0 with assertCount.

Show example solution
Write class LibraryTest extends TestCase. In testBorrow add // Arrange, $library = new Library(["Heidi"]); // Act, $result = $library->borrow("Heidi"); // Assert, $this->assertEquals(true, $result); $this->assertCount(0, $library->books);
Example solution:
<?php
// Here we define TestCase ourselves
class TestCase {
    protected function assertEquals($expected, $actual): void {
        if ($expected !== $actual) {
            throw new Exception("Expected $expected, got $actual");
        }
    }
    protected function assertCount($expected, $actual): void {
        if (count($actual) !== $expected) {
            throw new Exception("Expected count $expected, got " . count($actual));
        }
    }
}

class Library {
    public array $books = [];
    public function __construct(array $books = []) { $this->books = $books; }
    public function borrow(string $title): bool {
        $idx = array_search($title, $this->books);
        if ($idx === false) return false;
        array_splice($this->books, $idx, 1);
        return true;
    }
}

class LibraryTest extends TestCase {
    public function testBorrow(): void {
        // Arrange
        $library = new Library(["Heidi"]);
        // Act
        $result = $library->borrow("Heidi");
        // Assert
        $this->assertEquals(true, $result);
        $this->assertCount(0, $library->books);
    }
}

// Run the test
$test = new LibraryTest();
$test->testBorrow();
echo "testBorrow: PASSED\n";

Test yourself

  1. Which is the Act part?

    • $cart = new ShoppingCart();
    • $this->assertEquals(1, $cart->count());
    • use PHPUnit\Framework\TestCase;
    • $result = $cart->add("Bread");
    Show answer

    $result = $cart->add("Bread"); — Correct. Act calls the method under test; add is called here.

  2. Match the AAA parts

    Arrange
    Setup
    Act
    Run
    Assert
    Check
    Given
    Setup (BDD)
  3. Complete the Act line

    <?php
    public function testAddReturnsItem(): void {
        // Arrange
        $cart = new ShoppingCart();
        // Act
        $result = ____->add("Bread");
        // Assert
        $this->assertEquals("Bread", $result);
    }
    
    Show answer
    <?php
    public function testAddReturnsItem(): void {
        // Arrange
        $cart = new ShoppingCart();
        // Act
        $result = $cart->add("Bread");
        // Assert
        $this->assertEquals("Bread", $result);
    }
    

All lessons in Advanced