我的测试之间的相互联系很强,是不是设计错了?
假设我开发一个C/S型软件,在开发过程中一直用测试来检查代码是否完成我想做的操作了。而且我时不时又会对底层代码进行修正。所以我希望每完成一项小功能,就运行一遍所有测试,以避免出现新功能能用,旧功能却出错的情况出现。这样做的话,测试用例会非常多,我一般每个函数都会有一个对应的测试用例。
当然,测试用例多不是问题,在一般情况下大部分测试用例的执行时间是很短的,所有测试用例加起来也不会超过1s。
但是有一些用例,执行得特别慢!例如模拟真实环境的测试。因为这些用例可能还要联网,可能还要等待打印机,甚至可能要人为的设置延时等待30s等等。这些用例虽然不多,但是十分耗时。
我遇到的绝大部分测试框架在单线程模式下运行很好。这些框架都是规规矩矩地等待一个用例运行完毕之后,清理产生的垃圾,再运行下一个用例。
但是我希望测试用例能并行运行!因为我会很经常地修改代码并且编译、运行测试,所以我不希望每完成一个新功能、每做一次底层修改就要等上10分钟的测试。
但是有些用例会使用到同一个资源(例如SQL数据库),所以在并行运行测试的时候他们之间会相互影响,导致结果不正确。
所以我想问:是否存在一种现成的能较好地解决以上冲突的测试框架。或者说,我这样设计测试用例其实是错误的,只要遵守某些设计原则,就不会遇到上面的问题了?
举个栗子吧:
我写了2个非常底层的用例,是针对Store模块两个表的功能的测试用例:
Plain Text code
大括号里是这个用例调用的函数。
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个测试服务端功能的测试用例:
Plain Text code
大括号里是这个用例调用的函数。
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个模拟用户真实操作的测试用例:
Plain Text code
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分钟,用户才能收到自己发出去的消息。
这样一来,最后这个用例耗时会十分长。一个这样的测试用例还好,问题是项目中有几个这样的测试用例,就十分头疼了。
考虑代码无问题的情况:
如果按顺序运行测试用例,那不会有任何问题,就是时间有点儿久。
如果异步运行测试用例,那么即使所有的代码都正确,最后一个测试用例仍有可能没法通过,因为乱序执行嘛~
考虑代码有问题的情况:
如果前面的用例失败了,那么后面的用例根本就不用继续了。因为底层都出问题了,还测高层干什么~
所以我想,如果可以指定测试之间的关系(依赖、竞争),那么测试的时间就可以大大缩减。
所以我想问:是否存在一种现成的能较好地解决以上冲突的测试框架。或者说,我这样设计测试用例其实是错误的,只要遵守某些设计原则,就不会遇到上面的问题了? 自动测试首先不是针对代码、也不是针对用互操作,而是针对开发进度。例如50分钟的开发进度,你总该有一个测试来声明其目标。当然你若同时也加入能控制10分钟、15分钟的开发进度测试用例,那是你自己的事情。
因此测试肯定就在编码开发之上!如果你的思维方式是认为“测试都是跟着编码的屁股后边的”,那么就会产生疑惑了。例如一个“项目要求服务器在获取用户请求之后等待1分钟”的例子,如果项目过两天又要求等待15毫秒呢?你是不是需要先在测试用例设计上给出一个“可调时间”的参数,然后再来用测试用例指导开发(而不是把测试当作跟在开发屁股后边被动的事情)?
“头疼”,恰好说明测试需要提高其档次。测试来指导开发,测试设计的创意高于开发者的创意,测试技术高于开发技术,这就是解决了各种令人头疼的问题。
默认情况下,我们应该让测试代码并发几十个线程且乱序执行。但是并发测试之前,首先要执行顺序测试。
但又极个别的测试用例,我们可以设置一个标签声明其“无法并发测试”,让测试引擎排除并发测试。只要这样的情况很少(不到5%)就可以了,没有必要要求100%并发测试。 我是比较反对这个观点的。这说明你的测试还是层次比较低,从技术出发。
测试是从开发进度控制出发,或者从产品发现了bug的应急处理出发,而且遇到任何 bug 都是应该立刻停机、立刻集中精力解决眼前的bug的(只有极个别情况下,你可以设置一个 reopen 标签,将测试推迟到以后的某个时间点才开始测试)。
测试发现了非常棘手的问题时,你可以写出新的“小”测试来逐步逼近最近问题。你可以指定“运行最近3天的、1天的、1小时的”测试。但是不应该从技术出发!不要去想当然地从测试用例上指定技术“高低”。
测试是管理,它基于技术,更应该超脱于技术。 如果满脑子只有技术,如果动不动就用什么“方法、函数、通讯、模拟操作”之类的说法来说自动测试,你发现没有,扯大一堆技术术语之后,有些人就会用“怀疑你的技术”来打击测试。他们说“编程是技术话,测试用例来检验编程技术,那么你这个自动测试编程的技术我又怎么检验?”。这里扯“鸡生蛋、蛋生鸡”的目的,是把技术拉回到深渊中。
编程开发的目的不是发布、而是通过测试,而测试的目的才是进度控制和产品发布。把握这个原则,你在编写测试用例、测试引擎时,就紧紧把握这个目的,变通各种编程手段。不要把编程时的那些纠结的问题带到自动测试开发中,而应该用一种比较超脱、比较“清静无为”的方式来看到自动测试,让测试干比较纯洁的事情,比较简单的事情。 这么跟你说吧,可能会更明白一点。我经常跟程序员说:
如果我跟你写了文档(哪怕是200个字的文字的、一个简图的文档),甚至如果我仔细告诉你如何做,那么出了问题你就要承担责任。如果我没有告诉你细节怎么做,如果我没有对细节进行阶段性测试,我只是标题党地给你一个含糊的功能名词儿需求,那么出了问题我一定会承担全部责任,绝不会说是手下的人能力稍有不行,我绝对会对外承认自己的技术管理失误了。
通过这一点,你就把问题分清楚了。
打造一个自动测试机制也是如此。你要分清高低档次,你要让被测试的系统“解除责任”。而不是在你测试发生困难时去纠结人家被测试的系统有没有“划分责任依赖”的问题。你在测试用例开发上,要站在管理理论上,时间线的控制上,而不是站在低级的技术上想问题! to lz:
其实问题的关键在于,为啥你会时不时的对底层代码进行修正。
好好理一下业务逻辑的细节处理,画个流程图 数据流图,不用很规范,但是自己得看得懂。 把整个处理逻辑调用关系理清楚了再写底层代码。
--------------------------分割线-----------------
论坛大神:天网
有一句名言:废话是永远正确的
这个帖子里草帽路飞UU的回复是个很经典的案例。
一分钟能打那么多字有人信么,有本事你不要复制黏贴那么快丫!
顶一个
页:
[1]