bencarter78@hotmail.com's avatar

Running PHPUnit with Homestead is really slow

Hi there

I'm using Homestead as my dev environment and am just starting out with PHPUnit. I find that my test are running really slow, I have 18 tests so far (with 68 assertions) and it's taking 35 seconds.

I know you can't say how long a test is going to take necessarily due to all differing factors (and I'm sure I could write much better tests) but even still that seems pretty slow or is just really slow with VMs?

Can anyone give me any advice?

Thanks!

0 likes
18 replies
bobbybouwmann's avatar

@krizz Thanks for mentioning me :D It's recommended to use an sqlite database and even better in memory. Your tests will run lightning fast! My tests now run 10 times faster then without ;)

MarkRedeman's avatar

@bencarter78 I have the same issue. Running tests from my local machine takes 2.7 seconds while running the tests while being sshd to homestead takes 16 seconds. Both times the same database is used (a mysql database stored in homestead).

In order to run the tests from your local machine while using the database that's available on homestead you should change the DB_HOST value to point to your homestead's ipadress. (In my case my .env includes DB_HOST=192.168.10.10)

2 likes
ohffs's avatar

Just out of interest, can you run 'strace phpunit' (you might have to run 'apt-get install strace' first). That will print a list of all the system calls that happen - it might flag up what's causing the slowdown if you see it pause a little on certain ones.

bugsysha's avatar

Just interested, When does this happen? When you ssh in to the virtual machine or not?

bencarter78@hotmail.com's avatar

@bobbybouwmann @krizz thanks for your suggestion, I was using an sqlite db but tried an in memory one and it had no impact on my tests.

@ohffs I ran that command but there was no significant pause, all seemed to flow fine

@MarkRedeman I tried your change to DB_HOST and it had no change

@bugsysha it's when i ssh into homestead and run the tests

I have this test

class ReportsControllerTest extends TestCase
{
    use DatabaseTransactions;

    function setUp()
    {
        parent::setUp();
        Artisan::call('migrate');
        Artisan::call('db:seed');
    }

  /**
     * @test
     * @group current
     */
    function it_can_run_a_report()
    {
        $report = factory(App\Reports\Report::class)->create();

        $this->seeInDatabase('reports', ['title' => $report->title]);
    }

    public function tearDown()
    {
        Artisan::call('migrate:reset');
        parent::tearDown();
    }

So with those changes I made and scale back my tests to run just this one it takes about 10 seconds. Will it be so slow because I am migrating and seeding my db?

However if I run just this one test

    public function testItWorks()
    {
        $this->assertEquals(true, true);
    }

It still takes 6 seconds!

ohffs's avatar

@bencarter78 amusingly, I just ran my unit tests inside a vagrant box and they took 2 seconds, then ran them on my real machine and it took 55 seconds! I love computers.... ;-)

MarkRedeman's avatar

@bencarter78 I think you misunderstand what I was trying to say, what happens when you run the tests outside of your vm?

In my case I have the following results:

cd ~/Projects/MyApp

vendor/bin/phpunit # takes 2.6 seconds
homestead ssh
cd MyApp
vendor/bin/phpunit # takes 16 seconds
bencarter78@hotmail.com's avatar

@MarkRedeman Ah right, I'm using Homestead because L5.1 won't run locally with my php version, I wanted to get away from using my local machine but i'll try upgrading and give it a go

bencarter78@hotmail.com's avatar

@MarkRedeman So I upgraded my php version locally and the tests seem hugely faster, now taking 5 seconds instead of 35! Thanks man!

One thing I've seen running them locally is that when seeding the database on setUp I get the following error

PDOException: SQLSTATE[HY000]: General error: 1 too many SQL variables

If I don't seed everything (i.e. users and a few others) it is fine. Is there a limit to the number of queries sqlite will process?

MarkRedeman's avatar

I haven't seen that error message before. I always use the database that has been configured on my virtual machine. Perhaps you can seed the database on your vm and then run the tests on your local machine after you've finished seeding.

Personally I tend to run my unit tests using my local machine. Since these tests don't require any infrastructure these tests should easily pass when running them on a machine that only has php installed (so no database etc). Since you probably are already using composer to create a new Laravel application you'll have php installed so that shouldn't be a problem.

When using integration tests I either configure my application to use the database (and any other services required by the app) on my homestead machine (by setting DB_HOST for example) or if that's to much trouble I just run the tests on the vm (but only after all my unit tests have passed).


@ohffs @bugsysha I will try to do some analysis this weekend on why homestead seems to be so slow. I expect that my homestead is slow because my laptop has too little ram.

ohffs's avatar

@MarkRedeman if it's any use, my VM is running CentOS 6.7 with 512mb RAM & PHP 5.3.3 and runs my unit tests in ~2s, My work machine (which is also running the VM on the same partition) is running Ubuntu 14.04 with 8Gb RAM and PHP 5.5.9 and takes 50+s to run, and my Mac at home running PHP 5.3.29 runs them in ~1s. Definitely something wrong with the Ubuntu setup - when I strace it I see a ludicrous amount of blocking happening :

rt_sigprocmask(SIG_BLOCK, ~[RTMIN RT_1], [], 8) = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0

Which doesn't appear in the other two environments. I might dig into it if I'm bored over the weekend ;-)

bobbybouwmann's avatar

I have a project where I have over 1200 tests. The tests of this project takes around 16 second to complete, on Homestead ;) Pretty fast huh!

There is only a little different between my vm and my host machine. My mac runs it in 14 seconds, not much difference!

epreston's avatar

Found that some environments have xdebug enabled from the command line which balloons out the unit test time 10x. If you want it enabled in the webserver but not at the command line where unit tests are run, follow these steps.

  • Copy your php.ini to php-cli.ini in the same directory
  • Edit php-cli to exclude the xdebug configurations

If you are using brew, or a configuration that loads ext module configurations from a conf.d directory. Comment out the settings in the module file ext-xdebug.... then move them to the bottom of the normal php.ini. Web server will use the the normal xdebug settings, the command line will not run with xdebug because the settings do not exist in php-cli.ini

This also improves the performance of some other tools like artisan and composer in your development environment.

Szendi_Attila's avatar

@bobbybouwmann I have nearly 500 tests, and it runs approx. 5 minutes. Could you tell me how did you achieve 16 secs for 1200 tests? I am using sqlite in memory. Most of the tests run DatabaseMigrations.

bobbybouwmann's avatar

@Szendi_Attila Well running migrations are slow! Even when you use sqlite, it still needs to write the data to a while and IO is slow!

My test suite at that time had mostly unit tests, they don't use a database in most cases and are faster because of that!

Right now the test suite has got a bit bigger!

Time: 1.96 minutes, Memory: 382.25MB

OK (5244 tests, 32627 assertions)

However, 90% of them are unit tests only and are fast because of that ;)

1 like

Please or to participate in this conversation.