jozefhornik/php-mysql-engine

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

dev-master 2024-07-10 09:35 UTC

This package is not auto-updated.

Last update: 2024-10-03 08:55:56 UTC


README

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

PHP MySQL 引擎基于 Slack 的 Hack SQL Fake,由 Scott Sandler 创建。

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

动机

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

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

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

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

支持的 SQL 语法

此库支持各种查询语法,包括

  • 支持每个查询类型适当的 FROMWHEREGROUP BYHAVINGORDER BYLIMIT 子句
  • 支持所有连接类型的 JOIN 查询
  • 多查询,如子查询、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类型)。在某些情况下,与MySQL默认字符串类型不同,php-mysql-engine可能比实际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

以及Phasmal的检查

vendor/bin/psalm

谢谢!