A tweet of Simon Schubert made me aware of an awesome talk entitled Testing Legacy Code: Safe Refactoring by Katy Ereira. She presented this last year at PHP UK 2020 with tons of valuable information about how to write tests for refactoring legacy code.

Since refactoring legacy code is part of my daily job, some of these insights are quite useful and I would like to keep a note for myself in a few blog posts.

The used examples are all taken from the talk. I made few adjustments to make them runnable instead focusing on the bear minimum. They are also available int the testing-legacy-code repository.

Function with echo output

Given is a function which echos or prints an output.

<?php

declare(strict_types=1);

namespace RefactoringLegacyCode;

class EchoOutput
{
    public function yodel(?string $tune = null): void
    {
        if ($tune) {
            echo $tune;
        } else {
            echo 'Odl lay ee';
        }
    }
}

Test

The test is utilizing output buffering control to capture the echo output and make assertions on it.

<?php

declare(strict_types=1);

namespace RefactoringLegacyCodeTest;

use PHPUnit\Framework\TestCase;
use RefactoringLegacyCode\EchoOutput;

use function ob_get_clean;
use function ob_start;

class EchoOutputTest extends TestCase
{
    /**
     * @covers \RefactoringLegacyCode\EchoOutput::yodel
     */
    public function test_yodel_with_null_argument(): void
    {
        ob_start();

        (new EchoOutput())->yodel();

        $output = ob_get_clean();

        self::assertSame(
            'Odl lay ee',
            $output
        );
    }

    /**
     * @covers \RefactoringLegacyCode\EchoOutput::yodel
     */
    public function test_yodel_with_string_argument(): void
    {
        ob_start();

        (new EchoOutput())->yodel('Oh, lorolo lolalalalalalalalolalalolalalola lo la lo');

        $output = ob_get_clean();

        self::assertSame(
            'Oh, lorolo lolalalalalalalalolalalolalalola lo la lo',
            $output
        );
    }
}