我的测试之间的相互联系很强,是不是设计错了?

Happy0403 2016-05-13 12:34:19
假设我开发一个C/S型软件,在开发过程中一直用测试来检查代码是否完成我想做的操作了。而且我时不时又会对底层代码进行修正。所以我希望每完成一项小功能,就运行一遍所有测试,以避免出现新功能能用,旧功能却出错的情况出现。

这样做的话,测试用例会非常多,我一般每个函数都会有一个对应的测试用例。
当然,测试用例多不是问题,在一般情况下大部分测试用例的执行时间是很短的,所有测试用例加起来也不会超过1s。
但是有一些用例,执行得特别慢!例如模拟真实环境的测试。因为这些用例可能还要联网,可能还要等待打印机,甚至可能要人为的设置延时等待30s等等。这些用例虽然不多,但是十分耗时。

我遇到的绝大部分测试框架在单线程模式下运行很好。这些框架都是规规矩矩地等待一个用例运行完毕之后,清理产生的垃圾,再运行下一个用例。
但是我希望测试用例能并行运行!因为我会很经常地修改代码并且编译、运行测试,所以我不希望每完成一个新功能、每做一次底层修改就要等上10分钟的测试。

但是有些用例会使用到同一个资源(例如SQL数据库),所以在并行运行测试的时候他们之间会相互影响,导致结果不正确。

所以我想问:是否存在一种现成的能较好地解决以上冲突的测试框架。或者说,我这样设计测试用例其实是错误的,只要遵守某些设计原则,就不会遇到上面的问题了?




举个栗子吧:
我写了2个非常底层的用例,是针对Store模块两个表的功能的测试用例:

大括号里是这个用例调用的函数。
Test.Store.Table1 {
Store.Table1.Insert
Store.Table1.QueryLastInstered
Store.Table1.Update
Store.Table1.Delete
}

Test.Store.Table2 {
Store.Table2.Insert
Store.Table2.QueryLastInstered
Store.Table2.Update
Store.Table2.Delete
}

我用这2个测试用例来检查Server端的Store模块对Table1和Table2的增删查改操作是否正常。为了突出矛盾,我将正常情况下使用的Query改为QueryLastInserted:查询最后一个插入的记录。

我还写了2个测试服务端功能的测试用例:

大括号里是这个用例调用的函数。
Test.Data.Push {
大括号里是这个用例或者函数调用的函数。
Server.Data.Push {
Store.Table1.Insert
Store.Table2.Insert
}
}

Test.Data.Pop {
Server.Data.Pop {
Store.Table1.QueryLastInstered
}
}

这个测试用例检查服务端的Push函数是否正常工作。其中Push这个东西会向Table1和Table2都写入东西,Pop会查询Table1里的最后一个插入的记录。

我还写了1个模拟用户真实操作的测试用例:

Test.Simulate.Message {
Client.SendMessage {
Server.Data.Push {
Store.Table1.Insert
Store.Table2.Insert
}
}
Client.ReceiveMessage {
Server.Data.Pop {
Store.Table1.QueryLastInstered
}
}
}

这2个测试用例用来测试最终功能在真实环境下是否能正常使用。
这个测试用例会模拟鼠标键盘操作,然后打开浏览器,进入我们的网站(位于Internet),发送一条消息,耗时十分长。更有甚者,由于某些要求,项目要求服务器在获取用户请求之后等待1分钟,用户才能收到自己发出去的消息。
这样一来,最后这个用例耗时会十分长。一个这样的测试用例还好,问题是项目中有几个这样的测试用例,就十分头疼了。

考虑代码无问题的情况:
如果按顺序运行测试用例,那不会有任何问题,就是时间有点儿久。
如果异步运行测试用例,那么即使所有的代码都正确,最后一个测试用例仍有可能没法通过,因为乱序执行嘛~

考虑代码有问题的情况:
如果前面的用例失败了,那么后面的用例根本就不用继续了。因为底层都出问题了,还测高层干什么~

所以我想,如果可以指定测试之间的关系(依赖、竞争),那么测试的时间就可以大大缩减。

所以我想问:是否存在一种现成的能较好地解决以上冲突的测试框架。或者说,我这样设计测试用例其实是错误的,只要遵守某些设计原则,就不会遇到上面的问题了?


...全文
2077 6 打赏 收藏 转发到动态 举报
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
Happy0403 2017-09-15
  • 打赏
  • 举报
回复
谢谢各位的解答,我大概懂了。
  • 打赏
  • 举报
回复
这么跟你说吧,可能会更明白一点。我经常跟程序员说: 如果我跟你写了文档(哪怕是200个字的文字的、一个简图的文档),甚至如果我仔细告诉你如何做,那么出了问题你就要承担责任。如果我没有告诉你细节怎么做,如果我没有对细节进行阶段性测试,我只是标题党地给你一个含糊的功能名词儿需求,那么出了问题我一定会承担全部责任,绝不会说是手下的人能力稍有不行,我绝对会对外承认自己的技术管理失误了。 通过这一点,你就把问题分清楚了。 打造一个自动测试机制也是如此。你要分清高低档次,你要让被测试的系统“解除责任”。而不是在你测试发生困难时去纠结人家被测试的系统有没有“划分责任依赖”的问题。你在测试用例开发上,要站在管理理论上,时间线的控制上,而不是站在低级的技术上想问题!
  • 打赏
  • 举报
回复
如果满脑子只有技术,如果动不动就用什么“方法、函数、通讯、模拟操作”之类的说法来说自动测试,你发现没有,扯大一堆技术术语之后,有些人就会用“怀疑你的技术”来打击测试。他们说“编程是技术话,测试用例来检验编程技术,那么你这个自动测试编程的技术我又怎么检验?”。这里扯“鸡生蛋、蛋生鸡”的目的,是把技术拉回到深渊中。 编程开发的目的不是发布、而是通过测试,而测试的目的才是进度控制和产品发布。把握这个原则,你在编写测试用例、测试引擎时,就紧紧把握这个目的,变通各种编程手段。不要把编程时的那些纠结的问题带到自动测试开发中,而应该用一种比较超脱、比较“清静无为”的方式来看到自动测试,让测试干比较纯洁的事情,比较简单的事情。
  • 打赏
  • 举报
回复
引用 楼主 weizehua 的回复:
这个测试用例会模拟鼠标键盘操作,然后打开浏览器,进入我们的网站(位于Internet),发送一条消息,耗时十分长。更有甚者,由于某些要求,项目要求服务器在获取用户请求之后等待1分钟,用户才能收到自己发出去的消息。 这样一来,最后这个用例耗时会十分长。一个这样的测试用例还好,问题是项目中有几个这样的测试用例,就十分头疼了。
自动测试首先不是针对代码、也不是针对用互操作,而是针对开发进度。例如50分钟的开发进度,你总该有一个测试来声明其目标。当然你若同时也加入能控制10分钟、15分钟的开发进度测试用例,那是你自己的事情。 因此测试肯定就在编码开发之上!如果你的思维方式是认为“测试都是跟着编码的屁股后边的”,那么就会产生疑惑了。例如一个“项目要求服务器在获取用户请求之后等待1分钟”的例子,如果项目过两天又要求等待15毫秒呢?你是不是需要先在测试用例设计上给出一个“可调时间”的参数,然后再来用测试用例指导开发(而不是把测试当作跟在开发屁股后边被动的事情)? “头疼”,恰好说明测试需要提高其档次。测试来指导开发,测试设计的创意高于开发者的创意,测试技术高于开发技术,这就是解决了各种令人头疼的问题。
引用 楼主 weizehua 的回复:
考虑代码无问题的情况: 如果按顺序运行测试用例,那不会有任何问题,就是时间有点儿久。 如果异步运行测试用例,那么即使所有的代码都正确,最后一个测试用例仍有可能没法通过,因为乱序执行嘛~
默认情况下,我们应该让测试代码并发几十个线程且乱序执行。但是并发测试之前,首先要执行顺序测试。 但又极个别的测试用例,我们可以设置一个标签声明其“无法并发测试”,让测试引擎排除并发测试。只要这样的情况很少(不到5%)就可以了,没有必要要求100%并发测试。
引用 楼主 weizehua 的回复:
考虑代码有问题的情况: 如果前面的用例失败了,那么后面的用例根本就不用继续了。因为底层都出问题了,还测高层干什么~ 所以我想,如果可以指定测试之间的关系(依赖、竞争),那么测试的时间就可以大大缩减。
我是比较反对这个观点的。这说明你的测试还是层次比较低,从技术出发。 测试是从开发进度控制出发,或者从产品发现了bug的应急处理出发,而且遇到任何 bug 都是应该立刻停机、立刻集中精力解决眼前的bug的(只有极个别情况下,你可以设置一个 reopen 标签,将测试推迟到以后的某个时间点才开始测试)。 测试发现了非常棘手的问题时,你可以写出新的“小”测试来逐步逼近最近问题。你可以指定“运行最近3天的、1天的、1小时的”测试。但是不应该从技术出发!不要去想当然地从测试用例上指定技术“高低”。 测试是管理,它基于技术,更应该超脱于技术。
davy_chen 2016-06-22
  • 打赏
  • 举报
回复
你的问题牵扯的事情很多,不过按照你最后的问题来回答倒是很简单,就是没有满足你要求的现成的框架,你的测试设计是错误的。 没有说你的测试用例是错误的是因为用例本身也是有执行环境要求的,所以如果环境要求符合,不能说你的测试用例错误。但是你的想法中确实有很多需要改变的。 1、框架做框架的事情,而如果你自身的用例和系统就是设计成了相互牵连的,靠外部的框架,是无法解耦的。就好比想让一个鸡舍实现鸡下金蛋的功能。鸡舍能提供良好环境促进鸡产蛋,但鸡舍也只是促进,并不能改变事物本质; 2、回归测试案例选择的问题,测试是分很多层次的,并非执行的越多越好,执行过多是资源浪费,而且从效力上来说,也许就像在死人身上再补上几刀,除了提高心理上的确认度外,没有实质性的用处。所以应该把你设计的测试用例分批次执行,随改随测的案例选用那些与外部关联不大、执行效率高、针对性强的。而把那些需要网络、外设、耗时长的,可以安排在每日甚至是每周的例行测试中完成。 3、这点与你的问题关系不大,但是看到你涉及到打印机等外设、互联网等不可控环境,这些都是在自动化测试中应该尽量避免的,因为这些因素会给自动化测试的设计、执行、排错等带来很多麻烦。除非这些因素无法绕过去,那也应该遵循第2条中的建议。 至于其他测试用例设计原则就不多说了,虽然也和你的问题有关系,只说最后一点,自动化测试的用例设计要遵循简单的原则。一个简单的问题:自动化测试的实现其实也是一种软件开发,自动化测试来保证被测试系统的正确性,谁又来保证自动化测试实现的正确性?构成答案的一个重要因素就是,自动化测试自身的简单性,例如被测试程序要经过一系列复杂过程得到结果,而在自动化测试中的预期结果是直接被人为指定的。越简单,出错的概率越低。
白虹李李 2016-05-25
  • 打赏
  • 举报
回复
个人觉得是你的要求太完美。 或者换句话说吧,一般在工作中都会遇到无法兼顾的情况,要么就慢,要么就难(设计)。 真正兼顾的是不可能的。 你要是选择快,对测试数据和测试执行顺序做特殊的调整,刚才你举的例子就不能真的让他乱序执行,要排顺序来并行。或者部署几套测试环境来错开会相互干扰的测试条目。 现有的测试框架,应该是不能直接支持多线程的并发测试计划安排的。。。最多只能一条线安排下来。 你可以试图自己实现一套框架,不过我觉得完全没必要。 要么你就选择简单,不要试图每修改完一个功能就做一次完整的测试。而是只跑快的用例,大的用例晚上再跑。 个人觉得已经足够了。

5,179

社区成员

发帖
与我相关
我的任务
社区描述
软件工程/管理 质量管理/软件测试
功能测试压力测试安全性测试 个人社区 湖南省·长沙市
社区管理员
  • 软件测试
  • 虫无涯
  • 小博测试成长之路
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

欢迎大家加入到软件测试的社区,在这里,希望大家勇于发表自己的看法,欢迎大家分享自己在软件测试工作过程中遇到的问题以及工作经验分享。

1.想转行的小伙伴,遇到问题没有及时回复的,可以私聊小博进行反馈

2.大家对社区有好的建议,都可以在社区发帖进行反馈

推荐大家学习的软件测试入门笔记:软件测试入门学习笔记

试试用AI创作助手写篇文章吧