问题
Writing acceptance tests using Codeception for our Custom (with Symfony components and Doctrine) framework. We have a set of utility methods, used separately by our Phpunit tests, for creating various entities to test against. This includes things such as users, and other related data.
In the case of our Codeception tests we want to make use of this functionality, allowing us to seed custom data and clean it up afterwards. In the context of our Unit tests this is handled by a transaction. Given that Codeception makes requests to our application through Phantomjs over HTTP it can't make use of transactions as a separate database connection is created to the one used by the tests (It looks like this would be possible using Dbh but this isn't supported by MySQL as there's no support for nested transactions). The result of this is that the acceptance test can seed data, but this data doesn't exist within the external request unless the data is persisted.
The only other solution I can think is to trigger a database dump before the test suite runs. Persist our testing data to the database so it's accessible to the external requests, and then restore the dumped database when the test suite has completed. We have a pretty big database though and this is going to add substantial overhead to running the test suite.
I'm hoping there's other options available, or something else we can try. Thanks.
回答1:
There are always other options :).
In my case, using a dump was out of the question because we also have a very large database (1.2 GB when stripped down to the essentials, >250GB on live). Instead, I have a bunch of .sql files that remove any records that were inserted by a specific test.
I have a class DbHelper that has this function to run queries:
public function executeOnDatabase($path_to_sql_file)
{
$sql = file_get_contents($path_to_sql_file);
$dbh = $this->getModule('Db')->dbh;
$this->debugSection('Query', $sql);
$sth = $dbh->prepare($sql);
return $sth->execute();
}
Works as a charm, and no more overhead running the tests.
Update:
If you deal with users and their related data, it is usually pretty easy to target all records you need to remove. Most likely the username and email are unique, and you can use those to get the id (auto increment primary key) of the user. That id is likely used in the related tables. For example like this:
SET @user_id = (SELECT `id` FROM `users` WHERE `username` = 'rgsfdg');
SET @email = 'fdsgds@hgdhf.nl';
DELETE FROM `mail_queue` WHERE `send_to` = @email;
DELETE FROM `user_settings` WHERE `user_id` = @user_id;
DELETE FROM `users` WHERE `id` = @user_id;
来源:https://stackoverflow.com/questions/44499975/codeception-acceptance-tests-within-database-transaction-on-mysql