15

I am trying to develop a Laravel composer package and run unit tests from within it. After spending the last couple of days reading various outdated and contradictory guides and blogposts, I am completely confused as to how to go about this.

Here's what I know so far:

  • I shouldn't run tests from the main Laravel installation. Tests should all be contained within the package. I'll admit this has a certain logic to it.
  • There's something called Orchestra Testbench. If you're developing a Laravel package then apparently you should use this.
  • There's also something called Laravel Dusk, which is included in Laravel 5.4.

I can get Orchestra Test Bench working with some basic tests from the examples given, but I don't really understand what's going on and the documentation explains almost nothing. When it comes to testing my application's routes, I can't get anything to work.

I don't understand if Orchestra and Dusk can play together, or if I have to choose between them. If so, which one should I use? And if it's Laravel Dusk I should be using, then how do I run it from within my package directory?

hakre
  • 193,403
  • 52
  • 435
  • 836
Inigo
  • 8,110
  • 18
  • 62
  • 110
  • Can you tell us what your package does? If it's a composer plugin I doubt you will need Dusk as it's aimed at doing functional testing of your application through the UI layer. It doesn't sound like that's what you are looking for. I don't know Testbench but it looks more like what youmight need, but quite frankly I would start with plain phpunit and some of the test-traits that laravel provides. – dbrumann Jul 02 '17 at 14:08
  • It's a content management system which also uses Angular JS 4. I'm using Angular's testing suite for all the UI stuff. The Dusk code for writing route tests looks nice and straightforward and would like to use it to test API routes.. I also need to able to test database queries and the like so I really need to working with an instance of Laravel. – Inigo Jul 02 '17 at 15:13
  • So you want to use Laravel for Dusk? And you are testing completely different application? This can be done with changing Dusk's visit URL. – hasandz Jul 02 '17 at 18:51
  • @hasandz No, I am testing a package which I am in the process of developinng, which resides in its own sub directory of the main app/Laravel installation. I want to run my tests from this directory so that all my package components are bundled together and I don't need to pollute the main app- which I believe is recommended protocol. – Inigo Jul 02 '17 at 19:27
  • Lets check phpunit and Dusk. Just run `php vendor/bin/phpunit` and it runs both unit tests and Dusk tests. If you want to run only the Dusk test you can use `php artisan dusk`. Do you get errors with these commands? – hasandz Jul 02 '17 at 20:17
  • Perhaps I'm not being clear enough. I am trying to develop my package in isolation. The default directory for Dusk tests is `\tests\Browser`. But I want to keep my tests in the `tests` directory of my package, ie. `\packages\pascall\icms\tests`. Similar to as is described in this blog post: https://laracasts.com/discuss/channels/guides/guide-how-to-run-integration-tests-from-a-package Is this possible? – Inigo Jul 02 '17 at 20:50
  • In other tutorials written about Orchestra Testbench and similar tools for package development, **the tests don't use the main Laravel Installation, but rather a completely separate instance of Laravel required in your package's composer.json**- which then resides in your package's vendor folder. – Inigo Jul 02 '17 at 20:58
  • There is nothing wrong for `\tests\Browser`, phpunit will grab Dusk tests from this folder. First go to your package folder like `cd /path/to/packages/pascall/icms`, then run `../../../vendor/bin/phpunit` or simply run `phpunit` if you installed globally. Also you may want to edit your package's __phpunit.xml__ and __phpunit.dusk.xml__ if you need to change any options. – hasandz Jul 02 '17 at 21:15

3 Answers3

5

I agree with:

I shouldn't run tests from the main Laravel installation. Tests should all be contained within the package

To avoid installing Laravel in your application and bootstraping it by hand to test your package, you can use Orchestral Testbench.

The docs of Orchestral are pretty good today, but I will give anyway a short example how to use it, if you want to make unit tests on some Eloquent models.

First, make sure that your package has a ServiceProvider class which points to your migration files as described in the docs.

Then, require the orchestral/testbench package into your package and create a file in tests/TestCase.php.

The file TestCase should do the following:

  • Extend Orchestra TestCase
  • Point to your Service-Provider with getPackageProviders
  • Setup a SQLite database in memory with getEnvironmentSetUp
  • Run migrate to create you tables in setUp()

Here is an example:

<?php

namespace MyVendorName\MyPackageName\Tests;

use MyVendorName\MyPackageName\MyServiceProvider;

class TestCase extends \Orchestra\Testbench\TestCase
{
    public function setUp(): void
    {
        parent::setUp();

        $this->artisan('migrate', ['--database' => 'testbench'])->run();
    }

    /**
     * add the package provider
     *
     * @param $app
     * @return array
     */
    protected function getPackageProviders($app)
    {
        return [MyServiceProvider::class];
    }


    /**
     * Define environment setup.
     *
     * @param  \Illuminate\Foundation\Application  $app
     * @return void
     */
    protected function getEnvironmentSetUp($app)
    {
        // Setup default database to use sqlite :memory:
        $app['config']->set('database.default', 'testbench');
        $app['config']->set('database.connections.testbench', [
            'driver'   => 'sqlite',
            'database' => ':memory:',
            'prefix'   => '',
        ]);
    }
}

And to answer your second question: Laravel Dusk works well with Orchestral Testbench. Similar as above where you needed to mock up a database to test your Eloquent package models, you have to mock up routes & views with Orchestral to make the Browser tests with Laravel Dusk.

For more details, check out my blog post.

Adam
  • 25,960
  • 22
  • 158
  • 247
4

Here is what I do when developing a package:

1) Create a folder named src/tests.

2) Inside this folder I follow the "normal" structure:

  • A Unit folder for unit tests.
  • A Feature folder.
  • A Browser folder for running tests with Laravel Dusk (for the end-to-end tests).

Note: Dusk allows you to test your application as a real user would do clicking links, filling forms, etc. It is really cool to test an application user interface (even if it uses JavaScript). So, if your package does not include any interface you may not need Dusk.

3) All the tests use the base testing suite of Laravel, so you need a full Laravel installation with Dusk included (Dusk only needed if you are using browser tests).

  • So for the Unit and Feature tests I extended \Tests\TestCase.

  • Browser tests extend \Tests\DuskTestCase.

4) Now run your tests using the path to your tests:

phpunit /path/to/packages/pascall/icms

or, for Dusk:

php artisan dusk /path/to/packages/pascall/icms

(or you can cd /path/to/packages/pascall/icms and then run phpunit.

I have never used Orchestra because my team finds this option more straightforward and easier so I can't help you with that.

Drawbacks:

  • Dusk test failures will appear in the Default Laravel Dusk screenshot folder (for us this is fine so we have not spent time investingating this).
GorkaU
  • 343
  • 3
  • 13
0

I did all of the things that others said but my problem didn't been solved unless I change <testsuites> in phpunit.xml of Laravel's root :

<testsuites>
    <testsuite name="Unit">
        <directory suffix="Test.php">packages\YourVendorName\YourPackageName</directory>
    </testsuite>
</testsuites>
akbar
  • 625
  • 6
  • 12