理解数据库测试

在测试的世界里,数据库往往在文献中被忽视。大多数应用程序通常假设使用内存数据存储,就像我们到目前为止在 BookSwap 应用程序中所做的那样。然而,理解验证数据库时遇到的困难和我们可以采用的技术是很重要的。

数据库通常被视为系统中的外部系统或黑箱。它们提供专门的行为,并且通常是复杂的系统,且大多数情况下不会失败。图 5.6 展示了典型的数据格式转换:

在一个典型的应用程序中,数据格式会经历多次变化。用户请求通常以 JSON 格式进入我们的系统。API 层将这些请求转换为内部应用模型,并将其进一步传递到服务层。最终,服务层使用 SQL 或数据库所需的格式将数据持久化到数据库中。通常,NoSQL 数据库将以 JSON 格式保存数据并持久化。

我们应该编写测试,覆盖我们数据库系统的以下方面:

  • 启动和可用性:应用程序应等待数据库变为可用,并应以高效的方式进行等待。

  • 持久化和查询:一旦数据存储在数据库中,它应该被正确存储和获取。这是由业务逻辑完成的,并应验证其正确实现。

  • 性能测试:这种非功能性测试对数据库非常重要,因为数据库通常支持应用程序中的所有请求。典型的验证包括使用大文件或结果计数进行负载测试,使用多个远程用户运行测试,以及任何与数据库有效负载中列/字段值相关的边界情况。

这些系统的关键方面应该通过测试进行覆盖,特别是在数据格式发生变化和进行转换的地方。这些格式转换可能是导致 bug 和系统故障的原因。例如,某个字段可能在数据库层面是必填且不可为空,但在更上层的系统中却缺失了该字段。

作为数据库的 Mock

可能会有人认为使用 Mock 来包装复杂的外部行为是合适的,但社区普遍不推荐这样做,认为这是一种工程反模式。端到端和集成测试应该验证并针对在生产中使用的数据库运行,以避免功能和性能上的差异。

有用的库

幸运的是,Go 生态系统提供了一些很棒的库,使我们能够轻松地将数据库集成到我们的应用程序中。以下是一些在将数据库集成到 Go 应用程序时非常有用的 Go 库:

  • go-testfixturesGitHub链接 ):一个开源库,简化了功能性数据库测试的编写。它使用 Ruby on Rails 风格的固定数据文件(fixtures files)来设置数据样本。

  • golang-migrateGitHub链接 ):一个开源库,简化了数据库启动位置的设置,无需我们自己编写数据格式和文件。它支持多种 SQL 和 NoSQL 数据库。

  • go-txdbGitHub链接 ):一个开源库,在事务中运行数据库查询。测试完成后,事务会回滚,数据不会持久化。这允许我们在真实数据库上隔离运行测试。

  • gormGitHub链接 ):一个流行的开源库,提供对象关系映射(ORM)。这个开发者友好的库使得将数据库类型转换为有用的自定义结构体变得更加容易。

  • bunGitHub链接 ):这是 go-pgGitHub链接 )项目的重写版本。这个项目为多种 SQL 数据库提供 ORM 功能。

关于是否使用 SQLNoSQL 数据库的文献非常丰富,并涉及广泛的推荐。我们不会在这里开始这个讨论,但 SQL 数据库仍然是最受欢迎的数据库解决方案。在接下来的讨论中,我们将重点介绍如何实现和测试 SQL 数据库。我们还将看到本节中提到的一些库在实际应用中的使用。