Setup testing database for acceptance tests in Codeception (Laravel)

心已入冬 提交于 2019-12-21 06:06:33

问题


I'm using Codeception framework to perform acceptance tests in Laravel 5 application. I wanted to use a separate database for testing to keep real database from changing through testing. I configued the .yml files based on Codeception documentation. But the real database gets affected anyway. This is my configuration files:

/codeception.yml

actor: Tester
 paths:
   tests: tests
    log: tests/_output
    data: tests/_data
   support: tests/_support
   envs: tests/_envs
 settings:
   bootstrap: _bootstrap.php
   colors: true
    memory_limit: 1024M
  extensions:
  enabled:
    - Codeception\Extension\RunFailed
  modules:
  config:
     Db:
        dsn: 'mysql:host=localhost;dbname=realDB'
        user: 'root'
        password: 'secret'
        dump: 'tests/_data/dump.sql'

/tests/acceptance.suite.yml

class_name: AcceptanceTester
modules:
  enabled:
    - WebDriver:
        url: 'http://localhost:8000/'
        browser: firefox
    - Laravel5:
        part: ORM
        cleanup: false # can't wrap into transaction
     Db:
      populate: true
      cleanup: true
    - \Helper\Acceptance

The realDB is the real database and it changes after performing acceptance test. I tried different cases for cleanup in acceptance.suite.yml: 1) cleanup: false in Laravel module and cleanup: true in Db module 2) cleanup: true in Laravel module and cleanup: true in Db module. Codeception documentation says that for acceptance test, we need to "disable cleanup and use Db module to cleanup database betweem tests". But the realDB changes anyway.

I've tried different testing frameworks for PHP such as PHPUnit in Laravel, PHP Selenium driver, Facebook web driver and in all cases the real database get affected when performing acceptance tests. How can I correctly configure Codeception to prevent database changes?

Any help would be appreciated.

[UPDATE1]

As @TheFallen suggested that I use different database for testing, I change the configuration files like this:

/codeception.yml

actor: Tester
 paths:
   tests: tests
    log: tests/_output
    data: tests/_data
   support: tests/_support
   envs: tests/_envs
 settings:
   bootstrap: _bootstrap.php
   colors: true
    memory_limit: 1024M
  extensions:
  enabled:
    - Codeception\Extension\RunFailed
  modules:
  config:
     Db:
        dsn: 'mysql:host=localhost;dbname=testDB'
        user: 'root'
        password: 'secret'
        dump: 'tests/_data/dump.sql'

/tests/acceptance.suite.yml

class_name: AcceptanceTester
modules:
  enabled:
    - WebDriver:
        url: 'http://localhost:8000/'
        browser: firefox
    - Laravel5:
        part: ORM
        environment_file: .env.testing
        cleanup: true
     Db:
      populate: true
      cleanup: true
    - \Helper\Acceptance 

/.env.testing

APPLICATION_URL=http://localhost:8000
APP_DEBUG=true
APP_ENV = testing
MYSQL_MAIN_HOST=localhost
MYSQL_MAIN_DATABASE=realDB
MYSQL_MAIN_USER=root
MYSQL_MAIN_PASSWORD=secret 
CACHE_DRIVER=array 
DB_CONNECTION=test_mysql
TEST_MYSQL_MAIN_DATABASE=testDB

/config/database.php

return [

    'fetch' => PDO::FETCH_CLASS,

    'default' => env('DB_CONNECTION', 'mysql'),

    'connections' => [

        'test_mysql' => [
            'driver'    => 'mysql',
            'host'      => env('MYSQL_MAIN_HOST', 'localhost'),
            'database'  => env('TEST_MYSQL_MAIN_DATABASE', 'testDB'),
            'username' => env('MYSQL_MAIN_USER', 'root'),
            'password' => env('MYSQL_MAIN_PASSWORD', ''),
            'charset'   => 'utf8',
            'collation' => 'utf8_unicode_ci',
            'prefix'    => '',
            'strict'    => false,
        ],
...

The .env.testing is located in the root of Laravel application. But real database (realDB) still gets affected and only dump file get imported in testing database (testDB). It looks like application doesn't use .env.testing. How can I fix this?

Please note that, an AJAX request is sent to call a function changing data in database in my acceptance test. I want to rollback database transactions done by AJAX requests.

[UPDATE2]

According to Codeception documentation, Acceptance tests will be executed in development environment using real web server, so settings from .env.testing can’t be passed to them. :(

After all that I've done to solve this problem, I conclude that it is impossible to keep real database from changing after performing acceptance tests triggering AJAX requests to perform database transactions unless I change the default database to testing one in .env file!

If anyone has a better solution, please share it!


回答1:


Since your Laravel app can run under multiple domains, create one dedicated for your acceptance tests and configure the server to set the environment variable APP_ENV=acceptance (or whatever you call it) for this particular domain. When APP_ENV is set Laravel will automatically load the right environment file for you, in this case .env.acceptance.

I've also seen folks using cookies (set early in the acceptance tests) to configure Laravel to switch databases based on those cookies. It seems a little dirty and potentially insecure, plus you end up adding code to your application core so...




回答2:


If you set cleanup: true in your Laravel5 module settings all database queries will be run in transaction, which will be rolled back at the end of test. So this is one way to prevent changes in your real DB.

Also make sure you have your latest DB dump in tests/_data/dump.sql. You settings for the Db module should be cleanup: true to clean the database after each test, keeping your real data intact, and not sure why you need to reconnect to the database after each test with reconnect: true but you probably don't need it.



来源:https://stackoverflow.com/questions/38411641/setup-testing-database-for-acceptance-tests-in-codeception-laravel

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!