phpunit - testing is painfully slow

Solution 1:

You have several problems.

The first is process isolation. Normally, it should not be necessary and you only want to use it to find out which specific test is the one that fatally breaks your tests. As you noted yourself, it's awfully slow, which is something you cannot fix. You might want to disable backing up global vars which saves some milliseconds per test, though.

The second problem, which leads to your first problem, is that your code is not testable because static vars are kept during tests - my most-hated singleton problem. You can solve that problem by providing a "cleanup" or "reset" method in your dependency containers. Those will get called from the setUp() method in your main test case class and reset everything to a clean state.

Speed

Regarding the runtime of tests - I recently wrote a blog entry about finding out which tests were too slow. Generally, tests are too slow if you can't run them after saving the file or each commit on your own box. 10 seconds is barely acceptable for me. The more tests you have, the slower will running them be.

If you really have 35 minutes, then split up your tests into sensible groups so that you can run the necessary ones on your own machine - only the tests that test the code you changed. Pyrus, the next-gen PEAR installer, has the nifty feature to automatically detect and run the tests that need to be run, depending on what files you changed. PHPUnit does not have that, but you can emulate that by hand and phpunit --group .. :)

Always take care of mocking web services and databases, or at least running the database with only necessary data for each single test. Waiting 3 seconds for a web services response in a test that's verifying if you can save the user to database is something you never want.

Solution 2:

One of the things I usually do when I test with MySQL instead of SQLite's :memory: is I add Hash::setRounds(5); inside tests/CreatesApplication.php Trait like this. I experienced this will make the tests especially with MySQL so much faster:

public function createApplication()
{
    $app = require __DIR__ . '/../bootstrap/app.php';

    $app->make(Kernel::class)->bootstrap();

    // TODO: DON'T FORGET TO IMPORT HASH OBJECT ON TOP
    Hash::setRounds(5);

    return $app;
}