6
votes

I am trying to run some acceptance tests in my Laravel application. While functional tests trigger testing environment, acceptance tests do not. Is it a bug or a feature of acceptance tests? The main problem why this is bothering me is the fact, that it is not using(+populating+cleanup) testing database, it only connects to dev database (which is used, when no other ENV is specified e.g. testing, production) and this often fails those tests when I run them multiple times.

This is my configuration:

codeception.yml

paths:
    tests: app/tests
    log: app/tests/_log
    data: app/tests/_data
    helpers: app/tests/_helpers
settings:
    bootstrap: _bootstrap.php
    suite_class: \PHPUnit_Framework_TestSuite
    colors: true
    memory_limit: 1024M
    log: true
modules:
    config:
        Db:
            dsn: 'mysql:host=localhost;dbname=testdb'
            user: 'root'
            password: 'root'
            dump: 'app/tests/_data/dump.sql'
            populate: true
            cleanup: true

acceptance.suite.yml

class_name: WebGuy
modules:
    enabled:
        - PhpBrowser
        - WebHelper
        - Db
    config:
        PhpBrowser:
            url: 'http://localhost/'

functional.suite.yml

class_name: TestGuy
modules:
    enabled: [Filesystem, TestHelper, Laravel4, Db]

Thanks for your help!

2
I am having this same issue. My Codeception acceptance tests do NOT run under the 'testing' environment. I have tried to include Laravel4 in the acceptance.suite.yml - and that does not change anything. - Laurence
From what I can tell - Codeception runs 'two' cycles of each test. One of them is run as the 'test' environment, but the second is NOT run in the 'test' environment. I can confirm this - because if you force BOTH tests to run in 'test' environment, then your routes dont work correctly (as they are normally disabled for tests). - Laurence
@Fabrizio - what extra information do you need for this? I've already provided an answer? - Laurence
@TheShiftExchange I can't make it work, I understand why Codeception and Laravel behave like that, but still the 2 answers below doesn't explain very well how to create a codeception environment for run the acceptance tests. Thanks a Lots! - Fabrizio Fenoglio
I can't tell for codeception, but I hit the same wall. I solved passing a x-unit-testing header which triggers the testing environment (only if the request comes from localhost). - tacone

2 Answers

7
votes

"Acceptance" tests are not run in the testing environment. The reason is when Laravel is in the testing environment, it disables filters by default. So therefore the testing environment is only for unit and functional tests.

Acceptance tests should be run in another environment (like dev or a specific one to Codeception).

Because Codeception 2.x now uses Guzzle to get a page response, it is possible to detect when you are on your host machine and Codeception is doing a specific request. That way you can have a "testing" environment and also a "codeception" environment specifically for your acceptance tests.

If you are using Homestead, I do this in my start.php file to detect if Codeception is running, and specifically put it into a 'codeception' environment, otherwise I let it run my environment detection normally

if ((gethostname() === 'homestead') && (isset($_SERVER['REMOTE_ADDR'])) && ($_SERVER['REMOTE_ADDR'] === '127.0.0.1'))
{
    $env = $app->detectEnvironment(['codeception' => ['homestead']]);
}
else
{
    $env = $app->detectEnvironment(['dev' => ['homestead']]);
}

Then in my 'codeception' environment, I setup a SQLite file database, and run acceptance tests against that (which is faster than mySQL testing).

5
votes

First, you must understand that Codeception acceptance tests do not run inside the Laravel testing environment. Rather, it uses Guzzle to make external HTTP requests. Assuming your acceptance tests run against localhost, you are running in your standard development environment. It is just like using your browser.

That said, here is how I use Codeception Acceptance tests to run against a Laravel testing environment. I run Vagrant with a LAMP stack on Ubuntu.

  1. Edit your /etc/hosts file. Add test.localhost to the 127.0.0.1 line. Do not remove the other hosts there. If you use WAMP/MAMP/or other, it might be a similar setup.

    /etc/hosts

    127.0.0.1 localhost test.localhost

  2. Setup your environment handling with Laravel. Below is code in the bootstrap/start.php file in your larval root dir. pay attention to the 'testing' line.

    bootstrap/start.php

    $env = $app->detectEnvironment(array(
        'local' => array('your-machine-name'),
        'testing' => array('test.localhost')
    ));
    
  3. Make sure your codeception acceptance test is configured to hit the right domain/url. The code below is from my own acceptance tests for an API. Notice the url: sections have test.localhost. That is the url that Codeception will hit for the tests.

    app/tests/acceptance.suite.yml

    class_name: ApiGuy
    modules:
        enabled: [PhpBrowser, REST, ApiHelper, Db, FileSystem]
        config:
            PhpBrowser:
                url: http://test.localhost/
            REST:
                url: http://test.localhost/api/v1/
    

Putting it all together

  1. We edited the /etc/hosts file so that Codeception can find test.localhost. Editing your web server config to handle test.localhost is outside the scope of this answer.
  2. We edited Laravel's bootstrap/start.php so that it knows that any requests coming into test.localhost should run in the testing environment.
  3. We edited Codeception's acceptance.suite.yml file to tell it to run all tests against http://test.localhost

Now, assuming the above is done correctly, you should be able to run codeception run acceptance and see the output of your tests.