Paul Bailey提问:
我最近遇到了一个测试问题,我不确定应该如何设计一些有效的测试用例来进行测试,以及应该重点考虑一些什么样的逻辑?
这个功能的需求是这样的:
某个服务可以处理一个字符串,并返回处理之后的字符串。输入的字符串可以是任意长度,也可以包含任何字符。而输出字符串不能为null或空字符串,且需要被截断为最大15个字符的长度,并且连续的重复字符需要减少为单个字符(去重)。美元符号($)需要替换为英镑符号(£),下划线(_)和数字4需要删除。返回结果集不能为null。
示例输入字符串:AAAc91%cWwWkLq$1ci3_848v3d_K
Chris回复:
这应该不是一个在现实生活中会遇到的问题,但作为一个被人为设计出的问题,这还是很有趣的,我们可以试着梳理思考的思路,分析一些可靠的测试场景。
我是如何思考这个问题的:
首先,我的第一个问题是你是谁,你为什么想知道这些测试场景?要知道不同公司和业务对测试的要求是不同的,有的甚至都不需要进行太多的测试,好比我现在玩的一款免费游戏,而有的则需要进行严格的甚至苛刻的测试,比如军事安全系统等,因此这需要根据你的具体情况来分析我们进行深度挖掘测试场景的必要性。
其次,我需要知道这个需求实际上解决了什么业务问题。并且在现实生活中,仅仅知道这些问题还不能了解其全貌,还必须了解这些问题是如何解决的。对于软件研发来说,也就是一些解决方案和实现方式。例如,用的什么编程语言?在什么平台上运行?它与哪些功能相互作用?等等。如果你认为这无关紧要,那么看看“输入字符串可以是任何长度”这句话,然后想想当我在你的计算机上用10GB硬盘将100TB的文本文件推送到你的Python代码中时会发生什么。
我想看看代码,如果我能深入内部逻辑,那么我就可以了解它试图以目前的方式去做什么,而不必依赖于基于问题的盲目猜测。这样也将激发更多的测试想法,并让我更加全面地了解这个问题中可能的漏洞。
接下来,让我们拆开来更加深入地研究这个问题。
A. 某个服务可以处理一个字符串,并返回处理之后的字符串。
我想知道字符串是什么,可以是什么,可能是什么,还能是什么等等,因为这有助于我理解什么是可以的,什么是可能的。对于想破坏它的人的输入控制是什么?
B. 输入的字符串可以是任意长度,也可以包含任何字符。
当然这不是真的。有长度限制吗?什么系统能够处理世界上有史以来最长的字符串?这显然是愚蠢的——因此,值得我们去测试它能处理的实际长度,或者非常值得我们对输入长度进行控制,以便我们能够拒绝非常极端的数据,并更好地预测我们需要在其他地方也添加什么控制逻辑。
我还假设这是任何的Unicode字符。世界上有很多字符不是计算机可以识别的,一般来说,我们可以用大多数编程语言来处理它们。我们可能需要把克林贡语翻译成某种编码,这样我们就可以处理它,然后把它翻译回克林贡语,或者其他什么语言,这该如何处理呢?或者实际上更可能的是,我们只限于输入大多数键盘上的字母、数字和“特殊字符”。同样,上游输出的限制是什么,或者我们可以假设黑客或其他破坏者可能会进行的疯狂输入是什么?
C. 输出字符串不能为null或空字符串。
D. 需要被截断为最大15个字符的长度。
E. 连续的重复字符需要减少为单个字符(去重)。
F. 美元符号($)需要替换为英镑符号(£)。
G. 下划线(_)和数字4需要删除。
H. 返回结果集不能为null。
因为我不知道它为什么要这么做,我们只能假设它是一个黑盒子,在那里我可以进行输入,由它输出结果。输入的是单个字符串,输出的是字符串的“集合”(不管这意味着什么)。
核心问题:我们不知道什么样的输入会产生什么样的输出,所以我们无法可靠地形成完整的覆盖范围。如果不能创造必要的数据场景,比如说,将美元符号处理成英镑符号,我们如何测试它是否正常呢?
因此,让我们假设这是程序的伪代码,如问题中所述的顺序:
- 接受最多10000个字符的Unicode输入字符串
- 截断为15个字符
- 将一个字符的连续字符串替换为该字符的单个副本
- 将所有$替换为£
- 删除_和4这两个字符
- 返回字符串
我没有包括H点,因为结果可能为空的问题并不突出。我不知道为什么null是一件如此糟糕的事情,所以我不知道我为什么要测试它。
首先要注意的是,这里可能存在空字符串。比如输入数字4,输出结果就为空。当输出为空时,程序应该做什么?请记住,空输出是不允许的,但在这里明显是有可能的。
第二件需要注意的事情是,要截断到最多15个字符,但要知道我们的字符数可能远远多于15个。这也意味着我们可能会丢失原始字符串中第15个字符以外的字符。
测试用例 | 输入 | 输出 |
---|---|---|
先截取15个字符,再删除_和4 | __15charshere**444XXX | 15charshere** |
先删除_和4,再截取15个字符 | __15charshere**444XXX | 15charshere**XX |
看到了吗?这些逻辑执行的先后顺序是很重要。这意味着需求问题的描述有一些奇怪之处,因为两个输出都被截断了,而且它们都满足“最多15个字符”。但对于同一个输入,它们的输出结果却是不同的。当然,我们可以通过观察实际的执行情况来进一步分析这个问题,以看看实际会发生什么或可能发生什么。如果能用我们测试人员的一点创造性思维,得到一些有趣的结果,那就真的体现了测试的价值了。
我希望我已经证明,这个问题中对需求的描述和他们提供的规则并不完全匹配。但以下是我们可以测试的一些内容,只看产品的功能能力。接下来我将介绍一些测试用例的示例,你可能想参考一下,希望能覆盖地比较完整。
规则 | 描述 | 输入 | 输出 |
---|---|---|---|
C | 输出null | “” | 会有什么错误? |
D | 边界值刚好15个字符 | x3x5x7x9x12x15x | x3x5x7x9x12x15x |
D | 超过16个看看是否会被截断 | x3x5x7x10x13x16x | x3x5x7x10x13x16 |
E | 字符串中开头的字符连续移除 | AAABC | ABC |
E | 字符串中中间的字符连续移除 | ABBBC | ABC |
E | 字符串中末尾的字符连续移除 | ABCCC | ABC |
E | 多种分隔符 | AA_AA.AA AA4AA | AA. AA |
E | 缩减为空字符串 | 444 | 会报什么错? |
F | OFAT健壮性功能测试 | $ | £ |
F | 接D | _$… | ££££££££££££££ |
F | 接E | $ | £ |
G | 清空 | _4 | 会报什么错? |
G | 在开头 | 4A_ | A |
G | 在中间 | ABC_ABC | ABCABC |
G | 在结尾 | ABCABC_ | ABCABC |
这是一个很有趣的案例,它的功能可能是某种什么类型的分离器?这也是对规则执行先后顺序的另一个角度的测试用例,因为如果在删除连续字母之前删除下划线,那么执行结果会有所不同。我们可以在这里做各种测试!
考虑到我还没有了解到该功能背后的基本知识,其实可测试的用例还有很多。我们可以把所有的规则结合起来进行分析,看看它们是否配合得很好,还是存在一些矛盾的逻辑。这只是测试所描述的一个小小的功能而已,想象一下,如果是真实的系统可能会是什么样子。我希望这些例子能让你对其他可能的测试用例有所了解。
如果继续考虑其他场景来测试每一条规则,我们还可以测试哪些呢?我相信我上面写的例子并没有涵盖大部分内容。
这样看来其实测试结果的风险是很大的。这能怎么办呢?我们还可以设计哪些输入数据来验证我们的想法呢?
同时,还需要考虑一些你意想不到的风险。我们又可以设计出怎么的数据来覆盖这些特殊场景呢?