其他测试框架 测试开发之路 ---- 框架中数据的管理策略

孙高飞 · 2016年05月01日 · 最后由 steve 回复于 2021年09月02日 · 12764 次阅读

本系列其他文章:
第一部分:测试开发之路 ---- 框架中数据的管理策略
第二部分:测试开发之路 ---- 数据驱动及其变种
第三部分:测试开发之路 ---- 可读性,可维护性,可扩展性
第四部分:测试开发之路 ---- 可读性,可维护性,可扩展性 (续)


第一个要讲的是测试数据的管理,因为在我以往的公司中,我发现这方面是大家最容易忽略,但却是影响成败的最关键的几个因素之一。

1. 数据的分类

  说到测试数据,我想大家第一个反应就是数据库。现如今大多数产品,尤其是互联网产品都是使用数据库来保存数据的。以下的例子中,我均已数据库为例。那么在测试中,测试数据的准备和维护就成了一个很重要的方面。同样的,自动化测试中,测试数据的管理也成为了一个难点。管理不好,你根本没法自动化,因为你的脚本不能够重复执行,注意重复执行的重要性。不能重复执行的脚本,不配称为自动化。 也是不能加入持续集成流程中的。这也是我痛恨的那些为了 KPI 而被创造出来的,高大上的,“所谓的测试平台” 的特性。

  好了,既然提到了测试数据,那么我们先把测试数据分个类吧。

按使用方式分类

  1. 共享数据
  2. 隔离数据。
共享数据:所有的 case 或者是一些 case 共同使用的测试数据。
  1. 优点:速度快,数据只需要创建一次就可以给很多 case 使用。
  2. 缺点:
    • 数据为很多 case 准备的,你很难分清哪些数据是给这个 case 准备的,哪些数据是给另一个 case 准备的。case 的可读性低
    • case 之间互相有影响。因为待测的功能本身就会对数据库造成影响。很可能一个 case 的失败或者成功就会造成一批 case 的 fail
    • 数据本身不能扩展,稍微一改动,影响就很广泛。数个甚至数十个 case 的失败是很常见的。维护脚本的成本比较高

OK,貌似我们看到了使用共享数据的方式除了速度快以外貌似没什么出众的地方了,而且缺点貌似也很严重,大家会不会想,那么我们就不要用这种方式了好不好? 其实也是不对的,只要使用得当,这种方式在某些场景下也是比较好的方案。具体我后面再说

隔离数据:每个 case 都有独享测试数据,case 之间互不影响,说白了就是为每个 case 都做 setup 和 teardown 的操作。case 执行前创造数据,执行后销毁数据。
  • 优点:case 之间互不影响,数据之间互不影响。case 的稳定性,可维护性,可读性等都大大提高
  • 缺点:速度慢。。。。灰常慢。。。因为每个 case 都有很多的磁盘 IO 操作。。。维护数据的时间比调用功能的时间都要长的情况并不奇怪。 OK,这种方式其实是我们在测试中运用的最多的方式。虽然它很慢,而且对很多人来说实现起来也比较难。但是它带来的可维护性实在太诱人。我再也不用整天维护那些不稳定的脚本了。慢点就慢点吧。反正我们做接口测试和 UI 自动化测试的持续集成策略也是定时运行的。 跑个 10 几分钟,几十分钟的我也不在乎。 只要不是做监控代码变动的策略,一切好说。

按创建数据的类型分类:

调用开发接口:
  • 优点:在脚本中实现起来相对简单,不用深入理解后台数据库。
  • 缺点:
    • 耦合性太高,依赖产品的其他接口创造数据的方式注定了 case 是非隔离性的。注意隔离性是 case 质量的一个重要指标。一旦创造数据的接口 bug 了,你说得有多少个 case 失败。而且在真实环境中,需要调用 N 个接口去创造你需要的数据。无法判断到底哪个接口的 bug。这已然变成了端到端测试了。能够快速定位 bug 位置,也同样是 case 质量的重要指标。
    • 如果做隔离数据,产品中的接口往往很难满足你销毁数据的需要,举个最常见的例子。这个世界存在一种删除机制叫做逻辑删除,也是就是产品的接口并不是真正的删除了数据库中的数据,而是用一个逻辑标示位,标示这条数据被删除了。不要再反馈给用户了。 这样其实就做不到 “隔离数据了”

  好吧我说了太多这种方式的缺点,因为我曾经是真的被坑的很惨。 所以我是不建议用这种方式的。

直接使用 sql:就是直接写 sql 创造和销毁数据。
  • 优点:隔离性bug 追踪都很好。
  • 缺点:如果交给测试人员在脚本中写 sql 的话,难度,可读性都不太乐观,而且太依赖测试人员本身的能力,出错率较高。不过好在我们可以在测试框架上做一些手脚,解决这个问题。

  好了这种分类我也说完了。可以看出我是比较偏向使用 sql 创造数据的。第一种分类的时候虽然我说共享数据比较坑,但是在某些场景中还是很有用的。但是第二种分类中,我十分的强烈的不建议使用调用开发接口创造数据的方式。case 一旦多了,一个 bug 就能让你崩溃。想象一下如果 case 库里有 5 千条脚本,一个 bug 搞出了 100 以上的脚本 fail 是什么感觉吧(我们曾经是 7 千,迭代一开始,就得专门找俩人维护脚本,什么也不干)。

  OK,说完了两种分类,那么我们说说如何在我们的测试中使用这些数据管理方式吧。想了想,还是以我现在给我们公司写的这个框架举例子好了。

in-line 方式:

  其实我是实在不知道该怎么给这种方式起名了,所以借用了 xunit test partten 一书中的定义。而且我也实在不知道 in-line 方式翻译成中文该怎么说,所以就这么叫它吧。它的使用方式很简单,也很原始。 你直接在脚本中,或者在各种框架中的 setup 方法,teardown 方法中直接写代码创建这些数据。例如 testng 中就有 beforeMethod,beforeClass 以及 beforeSuit 等标签帮你初始化测试环境。你可以使用原始的 JDBC 语句,也可以使用例如 mybatis 这一类的 ORM 框架。强烈建议用 ORM,配置个级联操作直接给脚本调用就行了。在脚本里写 sql 简直是噩梦。

注册式:

  这个方式不太好理解,什么叫注册式呢?就是你把测试数据注册到框架中,并说明是共享数据,还是隔离数据。这些数据的作用域是什么。接下来的事情就交给框架做了,框架帮你在测试执行前创建测试数据,测试结束后销毁数据。完全不用测试人员关心。这是我比较推崇的方式,我在接口测试中使用的就是注册式加 in-line 方式管理数据的,说明一下,用的是直接写 sql 的方式入库的,只不过 sql 由框架生成,我们不用管。 好了,这么说实在有点难懂。 让我们来看一下例子吧。

  看过我在 Tester Home 的第一篇帖子的人应该对注册式数据管理有印象。 没看过的可以看一下,下面是链接:
NO_CODE 接口测试框架

  在我的框架中,我创建了一个叫做 DataBaseFile 的注解(注解为 java 语言特性,非 java 工程师请 google),注解里定义了两个属性,一个叫 filePath。规定了数据文件的路径,这个数据文件做什么的呢?看下面截图。

  这是一个 excel 文件,大家看这个是不是很像数据库的表结构。 答案是对了,其实这个文件就是从 navicat for mysql 导出来的。我们的思路是在 UI 上创建数据,然后用像 navicat 这种数据库客户端导出一个 excel 文件。框架会读取这个文件拼出三种 sql 并封装在一个对象里。这三种 sql 分别是 select,insert,delete。这三种 sql 就可以用来维护我们的测试数据了。这样就解决了测试人员写 sql 的问题。
  OK,让我们看看 DataBaseFile 注解的第二个属性 ---- 作用域。这个属性是一个枚举类型,这个枚举暂时有两种值,method 和 class。其实这个属性规定了测试数据的作用域。如果测试类指定了 method 作用域,那么这个数据就是 “隔离数据”,框架会在每一个测试用例执行前创建数据,测试结束后删除数据。如果指定了 class 作用域,那么框架会在这个类的所有测试方法开始前创建数据,所有的测试结束后销毁数据。其实这就是 “共享数据” 了,测试类中所有的 case 共享这些数据。 有些时候这个策略是比较有用的。 比如被测功能不会对数据库造成影响的情况,例如查询某些订单的功能。测试这个功能的一批用例,就是可以使用同样的数据的,只不过可能我这个用例是按 id 查,下个用例按 name 查,其他的可能对查询结果做正序排序或者倒叙排序。所以我在一开始也说共享数据在某些情况下也是蛮有用的。其实还应该有个 suit 作用域,只不过我暂时没用上。

  OK,知道了这些是不是就比较好设计实现了。 只需要在 testng 的各种 before 方法上做手脚就可以了。 具体思路就是创建一个基类,在基类里维护一个 List,list 里装的就是读取 excel 文件后分析出的三种语句的集合。在 before 和 after 方法里使用 java 反射技术读取子类的注解。这样就可以控制子类的测试行为了。 是不是还不算复杂?

  抱歉现在在丈母娘家,用的媳妇电脑。源代码在公司的电脑里呢,51 过后我把具体实现贴上来吧。

transaction roll back:

  这种模式是用来销毁测试数据的不二神器,专门在单元测试和小型集成测试中用来销毁测试数据的。 不过此模式依赖软件设计支持这种模式。也是就是大家说的需要软件有可测试性。具体怎么搞呢,就是要求开发在设计的时候就把测试考虑进去,不能在持久化层就把事务写死在被测方法里。而是把事务专门提取出一层来,或者使用 spring 这种提供了事务管理的框架管理软件的事务。这样的话,我们就可以在测试脚本中显示的控制事务。 在测试结束的时候,直接一个 roll back 就搞定了。 管你被测功能到底对数据库做了什么,我不 care~,直接暴力的全部回滚。 注册式数据管理方式的缺点就是它无法删除被测功能本身创造出来的数据。需要使用 in-line 的方式显示的删除这部分数据。 但是 transaction roll back 就方便多了。我心中完美的管理方式其实就是注册式加上 transaction roll back。 所以现在我们都要求开发再设计之初就考虑到这方面的事。 这也是方便他们做单元测试。 可惜这种方式不能用在接口测试和 UI 自动化中。

  之后我会在可测试性那一章中,专门提及 transaction roll back 的,等不及的同学可以自行 google 这种模式。它出自 xunit test pattern。

  OK,今天先说到这吧,媳妇叫我了。 以后如果有补充的我在修改帖子。 感谢大家的阅读。

如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
共收到 91 条回复 时间 点赞
ABEE ycwdaaaa (孙高飞) 在 TesterHome 的发帖整理 中提及了此贴 01月12日 13:47

大部分还是赞同的,但是对于隔离数据的生成方式个人还是比较推崇通过接口来造数,sql 造数不轻易使用,sql 造出来的数据跟实际的数据出现偏差或遗漏的概率还是比接口造出来的风险要大的😂

103楼 已删除
在路上 服务端接口测试指南 中提及了此贴 05月08日 17:28
孙高飞 测试开发之路 ---- 框架中数据的管理策略 中提及了此贴 10月19日 11:34

@ycwdaaaa 求源码 膜拜一下

孙高飞 测试开发之路----概要 中提及了此贴 03月13日 13:13

今天学习了您的文章,感觉您这个框架主要针对的是手工接口测试人员的优化,在接口测试阶段,接口测试人员可以利用这个框架,将测试数据准备到 xml 文件中,批量的利用这个框架来执行自己的测试用例,您看我这么理解对吗?@ycwdaaaa

孙高飞 回复

感谢提供思路,你的文章真的是干货满满!棒!

叶子 回复

时隔这么长时间我也有点忘了哈, 在 inline 里你可以写 sql 去做删除和更改,你想恢复什么样的数据自己写 sql 就好了。 不过我现在的做法是用 assertJ-DB。 监控数据的变化,然后自动的把数据恢复到之前的状态。 你可以看看我之前还写过一个文章。 说 AssertJ-DB 的

16 年的帖子现在才有幸看到,博主提到的接口产生的数据,使用 in line 方式删除。那如果接口影响的是原本的已有的数据呢,比如说修改密码:修改密码接口的参数有账号、原始密码、新密码,例:原始密码 123456、新密码是 12345678,第一次执行该接口没问题,顺利通过,那我下次是如何能够还是使用原始密码 “123456” 就通过修改密码的接口呢?不知道你说的 in-line 方式能不能达到还原数据的作用。

博主好,对于非常复杂的业务,设计到主从数据库、redis、hbase,还有同步服务等等很多个数据库才能完成一个场景,这种隔离数据成本会不会比较大。

陈小憩 接口自动化设计的疑问点整理 中提及了此贴 09月21日 10:05
孙高飞 论自动化测试脚本的质量与效率 中提及了此贴 08月11日 16:42

#90 楼 @A_tester 这种技术暂时还是比较坑的,你想用的话得等了。 暂时我们都还是写 sql 或者做数据库 diff 等方式维护测试数据。自动生成 case 首先没有业务逻辑性。bug 优先级比较低。再一个用例数量太多了。 一出 bug 好几百的失败,分析不过来。 同时运行时间也是个挑战

#89 楼 @ycwdaaaa 对,好像看到的就是说,根据参数组合批量生成数据,所以你们的测试数据都是手工准备的吗
#88 楼 @jet 对于请求里面的业务数据的话,没有固定的规则,因为数据都可以变,所以你们的测试数据都是手工准备的吗

#87 楼 @A_tester 你说的可能是自动生成 case 的机制。有一定规则下把参数做多种组合,会生成非常多的 case。

#87 楼 @A_tester 我觉得需要什么样的数据,验证什么样的结果,这个过程必须由人脑 work out。自动生成是指你自己制定好规则后,借助某些工具,或者是一些小脚本,根据需要去批量生产而已。

#86 楼 @ycwdaaaa 怎么看到论坛里其他帖子说什么,测试数据自动生成什么的,什么全对偶法,难道是我理解错了?每个用例手工准备数据的话,接口 case 多的话,大部分时间就会花在数据准备上了,而且如果换个环境的话,就又得准备一次,有没什么好的方法或者工具可以使用,批量造数据

#85 楼 @A_tester 预期结果和请求数据是没办法自动生成的。 除非你调用其他产品接口做这些

@ycwdaaaa 请问下你们测试用的请求数据和预期结果数据是手工准备维护的,还是自动生成的,特别是预期结果怎么自动生成

孙高飞 测试开发之路 ---- 数据驱动及其变种 中提及了此贴 12月10日 11:45

#80 楼 @phicomm123 可以自己造啊。。。。或者找 DBA 把线上数据脱敏后 dump 下来。。。。

@ycwdaaaa 那咋整 求教。。。

#78 楼 @phicomm123 恩,那不一定非要到线上搞数据下来。。。

@ycwdaaaa 比如要跑查询订单的接口 那不是先要在数据库里造订单数据吗。。。

#76 楼 @phicomm123 为啥要搞线上数据库。。。

赞! 问一下,数据库插数据的话,我们这边线上不给数据库操作权限,咋整?你们这边是有权限的还是有其他方案。。。

思路很好,可以拜读下源码吗?让我等菜鸟学习一下实现可好?

孙高飞 [该话题已被删除] 中提及了此贴 06月28日 18:51
孙高飞 [该话题已被删除] 中提及了此贴 06月28日 18:51
孙高飞 [该话题已被删除] 中提及了此贴 06月28日 18:51
孙高飞 [该话题已被删除] 中提及了此贴 06月28日 18:51

#68 楼 @tcat 这个倒也算正常吧,case 挂了就跟开发确定一下吧。没别的办法

#67 楼 @ycwdaaaa 结构其实变化不是很大,就是逻辑经常变,今天需要插这几个表的几个字段,或许下次迭代就不插了或者换字段了

#66 楼 @tcat 这个没办法的。。。要是太频繁变化的其实也不适合做自动化了。话说你们数据库和 redis 结构也总是变化么?

#65 楼 @ycwdaaaa 其实现在我也是这样弄,不过感觉要太深入开发那边了,基本要了解接口的所有逻辑。一旦开发那边变更,这边也得变更,接口少还好,多了维护不过来,每期接口变动也比较大

#64 楼 @tcat 这个我们还真没涉及过, 要我现在想,也就是你自己写代码去操控 redis 了

#63 楼 @ycwdaaaa

  • 第一个问题补充下,就是有些数据是不落地的,不存在数据库的,但这些存在 redis 中数据是接口需要去读取或修改的,比如一些权重,这种你们有涉及吗

#62 楼 @tcat 第一个问题是的,需要从直接操控 redis. 不知道你们的缓存是怎么做的. 如果是在 redis 中没有就去数据库中查找的逻辑.其实你就可以不用管 redis 了. 第二个问题, 我是直接调用登陆接口然后把 token 拿到以后,用在自己的脚本里. 我也是木有别的好办法了,自己实现实在不太靠普.

  • 想问下如果一个接口数据需要从 redis 中读取,那我是不是还要在 redis 去创建下,而且 teardown 时还要从 redis 时删除呢
  • 另外还要如 app 端接口一般通过需要用户的 token,这个目前是调用登录接口去拿的,那这种情况我还需要自己去通过开发规则来生成 token 吗

一周的工作忙完了,静静的喝杯茶再来读读这个系列,看能否有所收获

还有,楼主好文,谢谢分享

感觉上面讨论的兄弟们都混淆了。。不知道说的对不对,抛下观点.
第一,测试开发看的是 log,log 报错的是源点,是数据错了还是脚本错了还是接口反馈的原因,这些日志都看的出来,而作为测试数据的确实 rollback 毫无影响。
第二,测试的角度是这样的,我看到了数据错误,那么我拉开发来看的时候,这个时候是需要一个证据来证明此处有错的。有的开发脾气人好好说话,有的根本不想鸟你,打个比喻报了个数据库 insert table 时 data too long 的错误,你说要改成 vachar(500),脾气不好的就会觉得 300 就够了,为什么要 500 那么长,而且可能有的字段还是 index. 这个时候,保留下来的证据 (数据) 就显得很重要了!!
一点小观点,轻拍,感谢!
毕竟大家测试这一块 业务不同,工作性质不同,看待东西的角度也是不同的.

写的很有深度,学习了

#56 楼 @1875884881 对有些人说的话别太认真

#47 楼 @quqing 落地数据文件和你当时 select 查出来的有什么区别,这就是数据库告诉我当时它的状态啊?这不是数据库验证么?照你这么说,数据文件也别信,只有人眼看见的才算数,是这样么?那还自动化个毛线啊。。听你说话,感觉好装啊。。

很不错的贴,顶一下!

#19 楼 @ycwdaaaa
哦,遇见比较多这样的,一个接口列出某分类下所有数据,一个接口给分类添加一条数据,两个用例用不同分类就不会冲突。
剩下想不到隔离办法的比例不大,所以不会冲突的在一个 Suit 里,会冲突的单独一个 Suit ,可能四、五个 Suit 就可以了,没有每条都初始一个环境

#52 楼 @quqing 好走不送

#51 楼 @ycwdaaaa 你连这位兄弟表达的意思都没理解,我只能呵呵了,好吧,你继续活在你理解的世界里吧

#50 楼 @da_sheng 这样也可以啊,不一定就非要做成注册式的。

我之前做性能测试时,每次任务开始,都是用存储过程,初始化一遍数据库。但是现在做接口测试,由于规模很小,所以直接在 setup 里面搞了。。。

#47 楼 @quqing 看了今天的回帖。我也终于明白了猴老大说的不懂装懂的是什么样子了

#47 楼 @quqing 有道理,业务测试一般会看数据落地的正确性和 service 的 tomcat 日志,而且数据的正确性是企业的核心价值也是最需我们测试人员去细心校验的

#40 楼 @1875884881 看到今天的回帖,感觉测试行业整体水平的提升,路,还很长。
这么说吧,日志只是一种参考。我相信有经验的业务测试,在执行案例时,至少但不仅限于打开 2 个工具,数据库的客户端工具、日志查看工具等等。对于业务数据落地的正确性而言,日志也许会提供一些线索,到数据库验证却是最直接有效的证据。如果你是开发,日志和数据库里的落地数据,你更相信哪个?更何况是测试工具打印的而非程序本身打印的日志。。。

#45 楼 @taflo 哈哈,有点像 docker 的意思了,只不过我们这个很 low,完全是手工用 navicat 去导

#44 楼 @sigma 哦,原来如此。这个造数据的思路不错。其实做数据库快照也是有选择的,不一定要全量哦。

#43 楼 @taflo 哦哦,这个倒不是,我和你理解的不一样,我理解比较浅薄(就是单纯的数据库占用空间大,哈哈),因为之前我做 UI 自动化时,使用 mybatis 查询我们符合条件的贷款人数据,那个 SQL 比较复杂,查询非常慢,之后在一个管理页面通过翻页去找查出来的这个人..所以之后就做了个基础库,只提供自动化必要的数据,然后通过接口制造一些数据,最后就是管理页面仅有一条符合条件的数据,因为数据制造对于自动化来说是一大块~

#42 楼 @sigma 我还是有点不理解,很大是个什么概念?我理解的很大是指每次运行脚本时间是之前一次的数倍,也是说数据很大导致测试环境整体性能下降。如是这样的情况,就像你说的 “做了基础库,目的就是减小测试环境的数据库的数据量” 我觉得这个结局方案不错啊。其实我觉得很多事情不一定要在一个 “轮子” 里完,如能我觉得是值得欣赏和借鉴的。

#38 楼 @taflo 呃,我没说清楚哈,是这样,我们之前公司数据库数据量很大,之后做了基础库,目的就是减小测试环境的数据库的数据量

#34 楼 @yuweixx 我就不明白了,为什么一个失败重跑的问题,他能纠结成这样

#30 楼 @quqing 个人感觉日志可以解决问题啊,日志系统把自动化用例执行步骤,接口响应值,缓存层的值,DB 端关键数据的值都打印出来了,就是证据的。。这些数据难道不足以判断这段程序的执行过程么?

#34 楼 @yuweixx 不是一个维度的问题,不讨论了

#37 楼 @sigma 目前的我只能说找 DBA 同学们吧,他们是专家。我理解数据量很大一般只会出现在性能测试环境,恕我浅薄。

#36 楼 @taflo 备份一份数据库实例?要是数据库数据量很大咋办?

在每个 release 版本 cut 的时候做一个数据库快照,可以解决证据和清理的问题,当然这需要 DBA 同学们的协助

#34 楼 @yuweixx 文中提到了逻辑删除,定义为不建议使用这种方式;其实我也不赞成逻辑删除,还有更好的方式。

#33 楼 @quqing 帖子中有提到一种数据的逻辑删除,只是标识这些数据被用过了,而不一定要真正销毁。@ycwdaaaa quqing 的意思是,在提 bug 时,附上测试数据,让 bug 容易复现,可以更轻松的定位和修改 bug,这样可能更好。
另外,我发现 ycwdaaaa 的帖子后面基本都提到了老婆,看来夫妻生活很和谐啊,哈哈

#31 楼 @ycwdaaaa 你又混淆概念了,出了问题,测试当然要协助开发定位问题的原因。但前提是说服开发这确实是个问题!

#30 楼 @quqing 指望开发 debug 测试脚本。想多了

#30 楼 @quqing 这种就是出了问题不管三七二十一直接扔给开发的工作思路。

举个例子,批量跑接口测试,有些调用的接口会插入数据,结果某些插入的数据是有问题的,按照这篇文章的观点,运行结束就删掉数据,可能会出现以下场景:
开发问:我要看结果,持久化的数据到底是什么样的
测试说:测试数据跑完就自动删了
开发说:那我怎么知道这不是误报,进度这么紧,我可不想把时间浪费在排查误报的问题上
测试说:因为这世界上有种东西叫 debug
开发问:为什么 debug
测试回答:因为测试数据跑完就删了
开发问:那为什么跑完就删
测试回答:因为这世界上有种东西叫 debug
开发无奈:这是咋回事?

#27 楼 @ycwdaaaa @quqing 他的意思可能是难复现的问题。比如 UI 测试出错时候,截个屏。接口测试出错,保留下 datafile 这种。

#22 楼 @quqing 我理解在持续集成环境中要求保存数据当作证据给开发人员的。都是不管三七二十一只要脚本失败了就扔给开发的工作模式

#25 楼 @quqing 我的观点是不需要保留数据的。因为这世界上有种东西叫 debug。首先如果测试脚本失败了。作为测试人员肯定要去分析一下原因。为什么失败了,环境错误?网络问题?case 之间互相影响了?还是脚本本身的 bug?起码要 debug 一下看看到底怎么回事对吧?如果这件事无法达成共识那么也不用聊了。如果最后排出这些原因。怀疑是开发的问题,那么分析是哪部分代码出的问题。UI 自动化失败的话那就看一下对应的接口测试报告。确认是前端的 bug 还是 server 的 bug。去代码库看看相应路径,是不是有代码变化。什么变化引起的 bug。自己分析下原因后发现是自己搞不定的才提交给开发。bug 管理工具中提出完整的重现步骤。这是一个测试开发起码要做的。这个可以达成共识对吧。
那么再说开发追踪 bug 的问题。如果你们是异步合作模式,开发去 bug 管理工具上获得详细的重现步骤。如果根据步骤不能重现问题,有可能是测试没写好。也有可能是双方环境不一致。如果开发一定要在测试环境中看一下测试结果。根据之前测试人员 debug 的结果。会没有数据保留么?debug 的时候在数据清除之前就打断很难么?就算测试人员忘了保留数据。我们都是自动化的,跑一边脚本几秒钟的事很难么。所以我们需要在框架里特意的保存数据么?

#25 楼 @quqing 看来对于接口测试的结果校验以及相关证据的保留是非常重要的,又得保证自动化的持续集成(数据初始化->运行测试->数据处理->清理测试环境)又得保证保留相关的证据,我是感觉很头疼哇,我目前还停留在考虑接口测试校验返回值后的数据库层面的验证,不过想做得简单点,@ycwdaaaa他的框架给了我启发,但是我又不想加入类 ORM 的这种框架,而且像把框架做得耦合度低一些,类可插拔式的...

#23 楼 @ycwdaaaa 首先,我不是针对你,而是针对你的观点,错误的观点可能会误导一大批新人。
其次,你还是没正面回答我的问题,销毁数据后,你是怎么保留证据的,如果测试数据没有了,你会尝试找哪些原因说服开发确实有问题?如果你能说出好的方法,我还是会学习并感谢你的分享的。
@ityoung 测试开发和测试确实分工不同,但测试开发的成果好坏,会影响到测试。

#22 楼 @quqing 测试开发,不是测试。

#22 楼 @quqing 测试失败了。不尝试找原因直接扔给开发的我也是醉了

#21 楼 @ycwdaaaa 很愿意了解你销毁数据后是怎么保留证据的,断言和日志就不要提了,开发不会 care 的。。。

#20 楼 @quqing 不知道你怎么看出来我实战经验不足的。不过看你问的测试结束后销毁数据就是销毁证据。我就能看出你的水平了

说明你理论知识尚可,实战经验不足啊,关于如何删除数据,什么时候删除数据,好好琢磨解决方案吧

#17 楼 @sanlengjingvv 数据隔离指的是?我遇到的有些场景。不删除数据是不行的。例如有的接口是列出所有的 data。另一个接口是创建一个 data。创建接口生成的数据就会影响到列出 data 的接口。所以我不太知道怎么给这种情况做数据隔离。我只能删掉它

#14 楼 @ycwdaaaa 测试结束后销毁测试数据,等价于销毁证据,怎么破案?

你碰到很多用例之间冲突的问题不能用数据隔离解决吗?
启动一个容器 1 秒左右,没试过每条脚本启动一个这么频繁的情况下会怎么样

#15 楼 @sanlengjingvv 好思路。docker 起容器很快的。就是我没试过有多快。不知道每运行一条脚本就恢复一下数据库是不是成本太高了。要用多长时间?我回去可以试一下。目前我们数据库没有单独运行在一个容器里。多谢你的思路

测试环境在虚拟机上,所以销毁数据用的是快照
有一个干净环境的快照vagrant snapshot save init
每次测试流程都是恢复到 init ,执行测试,测试完保存一个用于查错的快照

vagrant snapshot restore init
begin test
vagrant snapshot save $tag

或者用 docker

docker run --name api-test init
begin test
docker commit api-test init:$tag

#13 楼 @quqing 是我笔误了么?我应该一直说测试结束后销毁

你先搞清楚是测试结束后销毁数据还是测试执行前销毁

#11 楼 @sigma 恩,差不多是这样的。不过我上个东家的老大提出过质疑,例如测试人员必须对数据库很了解,增加了学习成本。不过我个人觉得,不了解数据库你怎么验证接口呢。光靠验证返回值明显不靠谱。

#10 楼 @ycwdaaaa 哈哈,确实,之前其实我不是很理解你为啥说 [不要依赖产品的接口造数据,尤其是共享数据],看了你的回复发现就是避免运行时依靠研发开发的业务接口去制造数据 [产品接口 bug 的机率倒是挺大的],这点我之前确实没考虑过,感觉这样一来,写好的类 excel 文件就相当于一组测试数据 template suite,之后进行接口回归时只需要重复的去跑这套模板就好了~

#9 楼 @sigma 第三个问题。其实用产品接口生产一个订单,生成一个随机订单 ID。你下一个接口需要这个 ID,我理解的对么?如果是这样的话。其实用 SQL 创建数据的时候就可以把 ID 写死了。你脚本里 hard code 这个 ID。虽然 hard code 的方式总感觉不太好。但是 ID 这个东西除了唯一标示以外没什么用。修改他的机率太小了。相反,产品接口 bug 的机率倒是挺大的。我个人的想法,

#7 楼 @ycwdaaaa
1、对于通用的制造数据 excel,我理解是相当于 beforeMethod 中都要运行一遍 sheet=insert*,testMethod 中运行 sheet=select or businesslogic,afterMethod 运行 sheet=delete*,那么 beforeMethod 中需要写一些逻辑了,而且还是类参数化的那种(目前我是 DataProviderClass 直接 Iterator 提供给@Test的 method),你这样做灵活度确实高
2、对于删除数据,我目前直接使用 preHandler 和 postHandler 调用 resources 下的 sqlscript...,感觉做成你说的那个还需要完善一下我的 excelUtil,因为目前只支持单 sheet,你那个相当于多 sheet 遍历根据 sheetName 做判断,定义好格式然后去按照你定义的规则去编写 excel 中的数据,确实比手动写 sql 要方便也不容易出错
3、对于 [不要依赖产品的接口造数据],这个比如这样打个比方:
用户下了个订单,那么订单编号是自动生成的,如果不在运行时获取,预制数据的时候是不知道订单编号的,然后下一个接口的入参就是生成订单接口返回的 json 中的 orderId,当然也有可能有 7/10 个返回值下个接口用到 5/7 这种情况

#6 楼 @sigma 关于删除被测功能产生的数据。你也可以尝试我的这种做法:在读取 excel 的程序里做点手脚。凡是以 delete 开头的 sheet,不会生成 insert 语句,只生成 delete 语句。也就是说在 case 运行前不会创造这部分数据,但是 case 运行结束后会删除这部分 case。你可以专门做一个删除数据的 excel 了

#6 楼 @sigma 注册式的缺点确实是无法删除被测功能产生的数据。所以接口测试我们都是注册式加上 inline 结合着搞。最好还是不要依赖产品的接口造数据,尤其是共享数据。这么做确实会产生很多的 excel 文件。不过你可以考虑一下把 excel 文件也重复利用。例如造订单的 excel 文件做一个通用的。造用户的 excel 造一个通用的。商家的 excel 造一个通用的。很多 case 都可以使用这些 excel 文件。但是这些文件你仍然做成隔离数据。就是虽然很多 case 都用这几个文件。但是这几个文件的作用域仍然是 method。一个 case 运行前创建。运行后销毁。好处就是这些数据原则上都是隔离数据。我们也不用创建那么多的 excel 了。问题就是这些数据的内容是一样的。所有的 case 都引用这个数据。所以要求这部分数据必须稳定。不能经常变化。

#5 楼 @ycwdaaaa 接口测试的 case 隔离和共享我这边是用类似于占位符实现,虽然简陋但是还算比较有效,因为我们这边接口依赖比较严重,所以完全隔离的话,整体的业务逻辑就走不通,目前确实我也没有太好的办法(有些共享数据是接口测试运行过程中才产生的,感觉无法使用前置的方式先定义到 DataBaseFile 的 excel 中)~文章中说明的数据准备的思想很好,很值得我学习,不过我在考虑后期会不会框架维护的类 excel,类 xml 之后会比较多也比较复杂..

#3 楼 @monkey 排版完毕

#3 楼 @monkey 好的。刚学会发帖。都不会排版

可以用 markdown 修改下帖子,更有结构性看起来会更好点~

#1 楼 @stephen753 以前我们对待缓存和索引。就是在数据库中插入什么数据,就调用相应的 http 接口往缓存里插入。其实就是直接操控缓存了

Access 层的测试还要处理 cache 的 evict 这个怎么处理呢。。

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册