Codeception acceptance tests within database transaction on MySQL

人盡茶涼 提交于 2019-12-02 10:30:10

问题


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

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