sebastianbergmann / phpunit

The PHP Unit Testing framework.
https://phpunit.de/
BSD 3-Clause "New" or "Revised" License
19.69k stars 2.2k forks source link

`TestCase` should not extend `Assert` #5433

Open BafS opened 1 year ago

BafS commented 1 year ago

TestCase is currently 2276 lines long and contains 129 functions, we can argue that this class concentrates too much responsibilities and is a god class. Unfortunately this class extends Assert which is 2293 lines long and contains 175 functions.

My question is: could we remove the Assert inheritance from TestCase? What is the advantage of extending Assert? Writing self:: instead of Assert:: doesn't seem to be a good reason.

Proposal

Because there is a trait, it would be easy to have our own Assert by using use AssertTrait and add methods.

class MyAssert {
    use PhpUnitAssert;

   // custom methods...
}

In a future version we could imagine to remove the trait from TestCase. By doing so, devs would be free to either use AssertTrait to keep the "legacy" syntax or to use composition (Assert::).

class MyTest extends TestCase {
    use PhpUnitAssert;

    // We can use "self::assertXxx()"
}

or

class MyTest extends TestCase {
    // We can use "Assert::assertXxx()"
}
sebastianbergmann commented 1 year ago

In the long run: yes.

thbley commented 1 year ago

Maybe offer to write Test classes without "extends TestCase".

Example:

<?php declare(strict_types=1);

use PHPUnit\Framework\Assert;
use PHPUnit\Framework\TestCaseInterface;

final class GreeterTest
{
    private static $dbh;

    private TestCaseInterface $testCase;

    public function __construct(TestCaseInterface $testCase) // setUp()
    {
        $this->testCase = $testCase;
    }

    public function __destruct(): void // tearDown()
    {
    }

    public static function setUpBeforeClass(): void
    {
        self::$dbh = new PDO('sqlite::memory:');
    }

    public static function tearDownAfterClass(): void
    {
        self::$dbh = null;
    }

    public function testGreetsWithName(): void
    {
        $greeter = new Greeter;

        $greeting = $greeter->greet('Alice');

        $this->testCase->expectException(Exception::class);

        $this->testCase->assertSame('Hello, Alice!', $greeting); // alternative 1
        Assert::assertSame('Hello, Alice!', $greeting); // alternative 2
    }
}