包含数据库的单元测试应用程序太慢了。

3
我经常进行单元测试(主要是PHP/Mysql),但用于创建数据库的SQL脚本运行速度太慢,因此我浪费了很多时间。我无法总是模拟数据库(旧代码,处理过于复杂),那么我该怎么办呢?直接复制Mysql文件中的数据吗?以其他方式加载我的数据库?
加载大量数据很快,只有CREATE TABLES的速度较慢。

1
你没有进行单元测试。单元测试意味着你在隔离的环境中测试应用逻辑,不涉及任何外部系统,比如文件系统、网络服务或数据库。你所做的是集成测试。 - Steven
没错。实际上我两种都做,而且纯单元测试运行非常快。 - Cédric Girard
6个回答

2

阅读另一个问题给我答案:将我的测试数据库移动到内存中。在Debian / Ubuntu(我的情况下),我只需将我的测试DB目录移动到/ dev / shm,创建一个链接来将旧目录链接到新目录,重新启动mysql服务器,tada!

一个需要运行140秒的套件现在只需要10秒钟就能运行。如此显而易见!该项目在测试期间经常使用数据库。 另一个项目使用磁盘上的数据库运行18/20秒,并不会因为使用内存中的数据库而更快,但它有比另一个项目更多的单元测试,并且需要创建的集成测试表更少。


1

您可以使用MySQL的MEMORY引擎。

它比innoDB快得多,虽然不支持所有功能(例如外键),但对于测试非常有用。

假设您有一个脚本来从头开始设置您的数据库(例如在初始化测试时运行),您只需将InnoDB的引擎定义替换为MEMORY即可。

您甚至可以将引擎设置为测试套件的参数,以便每次保存/提交时都可以运行快速的MEMORY版本,在发布之前使用更长但更稳健的InnoDB版本。

与此处的其他建议相比:

  • 它是跨平台的(与通过复制将DB移动到内存仅适用于Linux不同)
  • 比使用类似Docker / VMWare的虚拟服务器更容易和更快

1

您可以使用初始化(测试)数据库。这样,您只需要:

  1. 开始一个事务,
  2. 将特定于您的测试的数据插入到数据库中,
  3. 运行您的测试
  4. 回滚事务。

这样做时,您需要维护一个数据库迁移脚本,以便在模式更改时更新测试数据库,但是您可能已经在使用当前方法进行此操作了,并且在推出软件的新版本时无论如何都需要执行此操作。

像这样做仍然会相当慢,但比为每个测试运行所有DDL脚本要快得多。如果可能,请编写单元测试,而不是集成测试,但是考虑到系统的状态(遗留),您已经说过这很困难。


真遗憾:我仍然没有为所有项目使用支持事务的真正数据库引擎,但对于新项目来说这是个好主意。 - Cédric Girard
MySQL 不支持事务吗? - Steven
MyISAM 引擎不支持,InnoDB 支持,我们仍然有一些应用程序在使用 InnoDB。 - Cédric Girard

0

我曾经遇到过类似的情况。我创建了一个仅用于测试的玩具数据库。 这个数据库只有很少的记录。


2
不是记录的问题,而是DDL指令的问题。我可以在很短的时间内加载数千条记录(几乎是)但是40个CREATE TABLES需要太长时间。 - Cédric Girard
如果您对数据库进行转储,包括结构(即创建表等),那么重置应该不会花费太多时间。实际上,我曾经为一个项目做过这样的事情,只需要几秒钟的时间。花费很长时间的是将数据库填充超过100K条记录。DDL非常快速。 - Luixv
创建一个表格需要10秒钟,进行50个测试需要不到2秒钟。我使用不到100k的记录,但希望尽快运行测试套件。 - Cédric Girard

0

我会:

  1. 按照自己想要的方式创建测试数据库
  2. 对数据库执行 mysqldump,并使用 --add-drop-table 和 --no-autocommit 选项,以便只有一个大型事务
  3. 在需要重置数据库时导入转储文件

1
这就是我所做的,对于超过几个表格来说非常缓慢。 - Cédric Girard

0
另一个选择是在VMWare实例中设置数据库...需要时只需重置即可。

如何快速重置我的VM实例?快照回滚是否快速完成? - Cédric Girard
是的 - 在最坏的情况下,它可能需要几分钟,就像复制一个大文件一样。 - Randy
@Randy,OP在这里谈论运行单元测试,并且至少以秒为单位工作。 - hijarian
是的,但与通过脚本重新加载数据库到初始状态相比,这将更快。 - Randy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接