问题
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