testing php applications

Testing Output

Return Values Are Easier To Test

A function that returns rendered text is easier to inspect than one that echoes in several places. At application boundaries, capture output deliberately and assert meaningful fragments or the complete stable string.

Avoid Fragile Markup Tests

If the contract is a message, assert the message. If exact HTML is important, assert exact HTML or use a DOM-aware check. Do not make every whitespace change break unrelated tests.

PHP example
<?php

declare(strict_types=1);

use PHPUnit\Framework\TestCase;

function receiptLine(string $name, int $pricePence): string
{
    return sprintf('%s: £%.2f', $name, $pricePence / 100);
}

final class ReceiptLineTest extends TestCase
{
    public function testFormatsPenceAsPounds(): void
    {
        $this->assertSame('Desk lamp: £39.99', receiptLine('Desk lamp', 3_999));
    }
}

When output itself is the contract, PHPUnit can capture it:

PHP example
<?php

use PHPUnit\Framework\TestCase;

final class ImportCommandTest extends TestCase
{
    public function testCommandPrintsCompletionMessage(): void
    {
        $this->expectOutputString("Import complete\n");

        echo "Import complete\n";
    }
}

Common Mistakes

  • Echoing deep inside business logic.
  • Asserting huge HTML pages when one fragment is the contract.
  • Ignoring escaping in rendered output.
  • Using snapshots without reviewing changes carefully.

What To Practise

  • Return testable strings from renderers.
  • Capture boundary output when needed.
  • Assert stable meaningful output.

Practice

Practice: Render A Receipt Line

Create and check a receipt-line formatter.

Requirements

  • Return rather than echo inside the formatter.
  • Format pence as pounds with two decimals.
  • Include product name.
  • Show a value ending in a trailing zero.
Show solution

Returning a string keeps formatting logic easy to test.

PHP example
<?php

declare(strict_types=1);

function receiptLine(string $name, int $pricePence): string
{
    return sprintf('%s: £%.2f', $name, $pricePence / 100);
}

echo receiptLine('Notebook', 250) . PHP_EOL;
echo receiptLine('Desk lamp', 3999) . PHP_EOL;

// Prints:
// Notebook: £2.50
// Desk lamp: £39.99

A PHPUnit test would use assertSame() against these stable strings.