【问题标题】:Codeception acceptance tests within database transaction on MySQLMySQL 数据库事务中的代码接收验收测试
【发布时间】:2017-11-13 23:04:40
【问题描述】:

使用 Codeception 为我们的 Custom(使用 Symfony 组件和 Doctrine)框架编写验收测试。我们有一组实用方法,由我们的 Phpunit 测试单独使用,用于创建各种实体进行测试。这包括诸如用户和其他相关数据之类的东西。

在我们的 Codeception 测试中,我们希望利用此功能,允许我们播种自定义数据并在之后对其进行清理。在我们的单元测试的上下文中,这是由事务处理的。鉴于 Codeception 通过 HTTP 上的 Phantomjs 向我们的应用程序发出请求,它不能使用事务,因为为测试使用的数据库创建了一个单独的数据库连接(看起来这可以使用 Dbh,但不支持由 MySQL 提供,因为不支持嵌套事务)。这样做的结果是验收测试可以播种数据,但除非数据被持久化,否则该数据不存在于外部请求中。

我能想到的唯一其他解决方案是在测试套件运行之前触发数据库转储。将我们的测试数据保存到数据库中,以便外部请求可以访问它,然后在测试套件完成后恢复转储的数据库。不过,我们有一个相当大的数据库,这将增加运行测试套件的大量开销。

我希望有其他可用的选项,或者我们可以尝试的其他方法。 谢谢。

【问题讨论】:

    标签: php mysql testing codeception


    【解决方案1】:

    总是有其他选择:)。

    在我的情况下,使用转储是不可能的,因为我们还有一个非常大的数据库(1.2 GB 精简到必需品,> 250 GB 实时)。 相反,我有一堆 .sql 文件,它们删除了由特定测试插入的任何记录。

    我有一个类 DbHelper,它有这个函数来运行查询:

    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();
    }
    

    作为一个魅力,运行测试没有更多的开销。

    更新:

    如果您处理用户及其相关数据,通常很容易定位您需要删除的所有记录。用户名和电子邮件很可能是唯一的,您可以使用它们来获取用户的 id(自动递增主键)。该 id 可能在相关表中使用。 比如这样:

    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;
    

    【讨论】:

    • 您如何跟踪需要删除的内容?在开始时从每个表中获取最大主键并删除 where id > stored_key?
    • 我已经更新了答案,以展示如何定位需要删除的记录。
    猜你喜欢
    • 2016-09-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多