彩票走势图

最新数据库测试方法,让我们先睹为快

原创|行业资讯|编辑:龚雪|2015-10-14 13:29:35.000|阅读 375 次

概述:在这里向大家分享一些测试数据库时的一些方法,并指出这些方法各自的优点和缺点。最后还介绍了一个新的测试方法,大家可以一起探讨和学习。

# 慧都年终大促·界面/图表报表/文档/IDE等千款热门软控件火热促销中 >>

当我们提到数据库测试时,有一件事是公认的:这不是一件容易的事。在最近一期的JAX杂志中,代表JAX发言的测试大师Colin Vipurs总结了测试数据库常用方法的优点和缺点。

在我从事软件开发的这些年,曾在许多不同的数据库上执行过各种级别和类型的测试实例,其中包括RDBMS和NoSQL。它们有一个共同点——很难。因此,我在这里向大家分享一些测试数据库时的一些方法,并指出这些方法各自的优点和缺点。

模拟(Mocking)

示例1

这种方法我过去常用,但现在我不建议大家继续使用。在我的《测试也需要热爱》(《Tests Need Love Too》)一书中,详细讨论了为什么决不能模拟任何第三方接口。没看过这本书也没有关系,我会在这里再次强调一遍。

一般情况下,你会用你认为的方式去模拟第三方接口的代码,但其实你并不知道它真正的代码是什么。这一点很重要,它很可能会导致错误的出现。除非你有更高级别的测试覆盖你的代码,但结果出来之前你没法确定这样的级别。此外,模拟原始JDBC真的很难。例如,测试示例1中的那小段代码。

在这个测试中,不仅需要大量的预期设置,还需要验证所有的请求都有正确的响应,jMock “states”被广泛使用。由于JDBC工作方式的限制,这个步骤违反了模拟测试的规则——不能越过当前的级别进行测试模拟。所以,即使你的测试结果表明所有工作都可以正常进行,但是当按照这样的代码进行生产时还是会出现错误。

直接在数据库测试

示例2

这听起来好像很疯狂,但这是最好的方法来验证数据库之间代码的交互是否按照预期运行的。同样,你还要确保你使用了正确的API。这种技术可以做到模式测试永远不可能完成的效果,例如,使你的SQL语法正确并达到你预期的效果。

内存数据库:使用e.g.H2内存版本,这是设置数据库测试的一个最简单快捷的方式。如果你愿意为你的代码引入Spring,那么测试设置也会变得一样简单。

这段代码创建了一个H2数据库实例,并加载了在schema.sql和test-data.sql的测试数据中定义的模式。返回对象工具为javax.sql。使得源数据可以直接进入到需要它的类别中去。

这个方法的好处之一是快。你可以为你的每个测试需求建立一个新的数据库,为你得到的数据准确性提供坚实的保障。这些都可以在JVM中完成,因此你的开发平台上不需要额外的基础设施。

这种方法同样存在着一些缺点。除非你在测试中使用完全相同的内存数据库,否则会不可避免的遇到兼容性问题。因为源数据的不同,很容易错过正确的驱动操作的配置选项。最近我看到这样的设置,在H2上配置使用了一个精确到毫秒的DATATIME column。在MySQL生产实例上使用同样的模式定义,不仅需要DATATIME(3),还需要参数useFractinalSeconds=true。这个从H2迁移到MySQL实例上的问题直到测试后才被发现。

实时数据库

我强烈推荐测试尽可能在生产环境中进行。但是因为各种各样的原因使它很难实现,比如在每台开发平台上安装商业数据库非常昂贵。有一个经典的方法可以绕过这个问题,就是可以给每个人提供单独的开发数据库。这就会导致一系列的问题,不仅仅是性能(因为总是被安装在便宜老旧的硬件上)和测试重复性的问题。当两个或两个以上的人共享数据库,然后同时运行测试时,可能会有不一样的结果和不可预料的改变。随着人数的增加,这样的情况会更加严重。你会浪费很多时间重新运行测试,并试图找出更加稳定的构建。

当你使用一个免费的MySQL数据库或免费的NoSQL选项,在开发平台中仍然会出现一些问题。例如,需要同时运行多个版本,或者需要通知他们需要构建怎样的基础设施和怎样的接口。在这之前,我们还需要在培训新员工上花费更多的时间。

值得庆幸的是近几年出现了一些工具来帮助我们缓解这个问题,最显著的有Vagrant和Docker。例如,Docker中的内置MySQL版本可以轻松的发出一下命令:

$ docker run -p 3306:3306 -e MYSQL_ROOT_PASSWORD=bob mysql

这将使用提供的根密码,启动一个最新的MySQL独立版本映射到本地3306端口。我使用的四年前的苹果笔记本,在最初的映像下载之后,只需要12秒的时间。如果你需要运行Redis 2.8,就在Docker上这样写:

$ docker run -p 6389:6389 redis:2.8

或者在不同的本地端口运行最新的Redis版本:

$ docker run -p 6390:6389 redis:latest

这将很容易的插入到你的构建系统中,使整个过程自动化。这就意味着开发者只需在本地机器上安装Docker (或Vagrant)即可,并且可以将需要的基础设施打包到脚本文件中。

测试方法

当你的数据库建立并运行起来后,这时你将面临新的问题:我该怎么测试?根据实际情况的不同,测试方法也要相应改变。一个新建项目的初期阶段我们会关心关系模式在怎样迅速的变化。而一个既定的项目我们会更关注怎样读取现有的数据。 大多数情况使用Redis可以进行高速缓存,所以读取现有数据会更容易些。(不是所有情况都可以,比如当Redis是主数据存储器时。)

示例3、示例4

对于功能性测试,首先注意的是要使用干净的空数据库。测试的重复性很关键,一个空的数据库可以确保这一过程的正确性。我通常会在测试开始的时候清除所有数据,而不是结束的时候。这样在测试失败的时候,可以方便查看数据来诊断问题。就以这样的方式,重复你的测试就可以了。

目前流行使用一个叫DbUnit的工具,用来表达数据文件并可以轻松的加载测试数据。这时有两个问题需要注意。第一,你使用的数据库是否存在数据库架构本身和测试数据之间的重复。因为无论是架构的改变,还是测试数据不再在测试类本身的改变,都会导致数据集文件的变化。可以参见示例3,DbUnit的XML文件。

另一个问题,新手常常会问验证是否可以避开数据库直接进行。数据回路测试(round-trip the data)是测试环节中一个重要的部分,因为你要确保你的数据可以被回读。这个问题本质上是你在同时测试两个项目,因此当出现故障时,你不能确定是哪里出了问题。如果你使用TDD(这是肯定的),那么问题就是运行与暂停之间的频率不如以往高,不再需要以往那样的快速反馈了。

示例5

这里我将这两种测试方法结合起来,可以避免它们的缺点。第一个是我写的一个纯粹的读写测试,可以将数据手动输入而比依赖测试本身。这样的工作看起来重复繁琐,写入路径还可能使测试代码绕过一些逻辑关系。

例如,插入一个“ON重复键”(ON DUPLICATE KEY)就不必这样做了。我们假设记录不存在,测试的数据状态完全可控。然后该测试将使用产品代码回读测试中插入和标记的内容,并且回读的内容可以被验证。请参见示例4的读取测试。

一旦读取路径可用,写入测试将使用生产代码生成数据回路同时用来写入和读取。因为我们已经知道读取路径完好,所以只需要关心写入路径就可以了。当读取路径出现故障时也会导致写入测试的失败。但是当写入路径出现故障我们就可以找出问题的所在。此外,如果你使用DSL测试验证读取路径,将会大大节省你的时间。请参见示例5的回路测试。

 


标签:数据库软件测试技术

本站文章除注明转载外,均为本站原创或翻译。欢迎任何形式的转载,但请务必注明出处、不得修改原文相关链接,如果存在内容上的异议请邮件反馈至chenjj@cahobeh.cn


为你推荐

  • 推荐视频
  • 推荐活动
  • 推荐产品
  • 推荐文章
  • 慧都慧问
扫码咨询


添加微信 立即咨询

电话咨询

客服热线
023-68661681

TOP