Some years ago I reasoned about upgrading unit tests from ancient PHPUnit 4 to then-recent PHPUnit 9.
Back then Horde’s unit test suite would use a Horde_Test class inheriting from the actual phpunit test cases. Even then I was fairly certain that this approach was not very practical in the long run.
Why extending PHPUnit might be wrong – ralf-lang.de
Turns out this is right. With many new or refactored components I started to use plain PHPUnit 9 and only resorted to Horde_Test when I strictly needed it. This simplified things a lot. The Horde organisation houses a dozen or so apps, almost 200 library repositories and some auxillary stuff. Having Horde_Test in the inheritance hierarchy makes any upgrades awkward. Need to be more strict about signatures for a new PHP release? Fix it all at once. Want to adopt a newer phpunit framework? Do it wholesale. Hook into some internal PHPUnit mechanism? They told us not to and they use their freedom to break internal classes very liberally. Tough luck.
So instead I am mostly abandoning the Horde_Test_Case base class and everything that comes with it.
- PHPUnit hooks right into the composer autoloader. No more AllTests.php, autoload.php or bootstrap.php
- I use the PHPUnit version I see fit. If I rarely update a component and it’s supposed to run on old PHP 7.4 through PHP 8.4, then I am fine when the tests work with PHPUnit 10.
- If I develop something bleeding edge which does not need to work on PHP 8.2 and older, I simply start out at PHPUnit 12.
- If I want to abstract out a test helper which is useful beyond the limits of an individual repo, I try to avoid building new bases classes. Instead I build it as a utility
Many libraries which get a wholesale upgrade no longer depend on Horde/Test. This is good because Horde/Test pulls in too many implicit dependencies anyway.
This comes at a price though. Our custom test runner relied on a specific structure of horde tests. The internal quality check pipeline in the horde-components tool also relied on a specific phpunit version and library layout. These are now broken and I won’t try that approach again.
So the new layout looks fairly standard.
- Tests are in the /test/ subdirectory
- Unit tests which are intended to run on most platforms are in /test/unit. Tests which require external resources, expensive calculations or rarely used PHP extensions get their own lowercase test suite directory
/test/ldap/
/test/pam/
/test/kolab/
/test/integration/ - The horde-components tool autodetects these test suites and sets up the appropriate PSR-4 autoload-dev rules in the composer.json file
- Just call “phpunit” to run the test suites.