vimeo/php-mysql-engine

用PHP编写的MySQL引擎,用于加速测试

0.7.5 2024-07-08 14:10 UTC

This package is auto-updated.

Last update: 2024-09-11 19:26:24 UTC


README

PHP MySQL Engine 是一个PHP库,允许您通过内存中MySQL 5.6的模拟来测试数据库驱动应用程序。该项目扩展了 PDO 类,并允许您调用常见的PDO MySQL方法。它支持广泛的查询,以及一些PDO特定的功能,如事务和不同的获取模式。

PHP MySQL Engine 基于Slack的由 Scott Sandler 创建的 Hack SQL Fake

您可以在这里阅读有关此工具的文章 这里

动机

目前有两种方法来测试读取和写入数据库的代码

  • 模拟SQL查询执行
    模拟需要显式列出预期的查询及其返回结果。这会导致大量的手动设置预期的工作,并且测试脆弱且必须更新代码或查询的良性更改。这也意味着数据访问层没有进行单元测试。

  • 使用实际的数据库
    使用单独的数据库实例进行测试可能是有意义的——这是我们在Vimeo过去所做的事情。但是,MySQL之类的数据库是为了填充大量持久数据而设计的,而单元测试则写入少量非常短暂的数据。这意味着必须格外小心,确保测试数据库在测试之间被截断,这会引发性能问题。

PHP MySQL Engine 采用不同的方法 - 它解析并执行针对存储在PHP数组中的内存中“数据库”的 SELECTINSERTUPDATEDELETE 查询。只要用于测试的数据量很小,这就可以解决上述问题。

支持的SQL语法

此库支持广泛的查询语法,包括

  • FROMWHEREGROUP BYHAVINGORDER BYLIMIT子句,根据每种查询类型相应地支持
  • 所有类型的连接查询
  • 多查询,如子查询、UNIONUNION ALLINTERSECTEXCEPT
  • 复杂的表达式,如CASEBETWEEN和行比较符(1, 2, 3) < (4, 5, 6)
  • 所有基本运算符均按运算符优先级实现
  • 列别名,跨数据库查询
  • INSERT ... ON DUPLICATE KEY UPDATE
  • 各种SQL函数,如COUNT()NULLIF()COALESCE()CONCAT_WS()
  • 临时变量,如@previous_name := user.name
  • 验证解析器:查询解析器将在大多数无效的SQL查询上抛出异常,帮助保护您的生产环境免受意外的SQL语法错误的影响

不支持的MySQL功能

此引擎不支持MySQL存储对象,这排除了对存储过程、触发器和视图的测试。

告示

Psalm不同,这个包并不是面向广大用户设计的。为了使项目真正受益于这个库,该项目应该已经拥有大量需要数据库连接才能完成的测试,并且项目的维护者必须理解在使用测试套件中的非官方MySQL实现时相关的权衡。

已知问题

不模拟预处理语句的结果类型

默认情况下,引擎将所有数据格式化为字符串。如果调用$pdo->setAttribute(\PDO::ATTR_EMULATE_PREPARES, false),则引擎将相反地推断列类型(例如,SUM(some_int_column)将被赋予int类型)。在某些情况下,php-mysql-engine可能在推断正确的列类型方面比实际的MySQL做得更好,MySQL默认将列类型设置为字符串。如果您对结果进行严格的类型检查,您可能会看到一些小的差异。

安装

composer require --dev vimeo/php-mysql-engine

使用方法

PHP MySQL Engine通过提供PDO的一个子类来工作。

您可以像使用PDO一样实例化子类,并通过依赖注入或类似的方法将该实例提供给您的应用程序代码。

// use a class specific to your current PHP version (APIs changed in major versions)
$pdo = new \Vimeo\MysqlEngine\Php8\FakePdo($dsn, $user, $password);
// currently supported attributes
$pdo->setAttribute(\PDO::ATTR_CASE, \PDO::CASE_LOWER);
$pdo->setAttribute(\PDO::ATTR_EMULATE_PREPARES, false);

其余的代码可以按正常方式操作,使用数据库的方式与生产环境中相同。

为什么它不支持X?

这个库的目标是支持用户在MySQL中使用的所有内容,而不是MySQL提供的所有可能的功能。我们欢迎提交拉取请求来添加对新语法、SQL函数、数据类型、错误修复和其他特性的支持。

为什么这个项目没有问题跟踪器?

维护开源项目是一项艰巨的工作,我不想给自己或我的同事增加更多的工作。请自行承担使用此项目的风险。

如果您想使用问题跟踪器分叉此项目,请随时操作!

贡献

如果您想创建一个PR,请确保它通过了单元测试

vendor/bin/phpunit

以及Psalm的检查

vendor/bin/psalm

谢谢!