互联网产品的特点就是“快——快速迭代”,通过产品需求的不断更新去快速的开发迭代任务,迅速占领市场,争夺流量。那么产品竞争力是什么?有人可能会说是良好的交互体验,也有认可能会说运营推广的策略,还有的人可能认为是功能的丰富化。仁者见仁智者见智,各有各自的说法。但我认为竞争力的本质其实是产品的质量,只有保证产品质量的前提下再结合上述特性才能使产品更有竞争力,更能吸引用户,达到抢夺流量的目的。因此本文的重点主要介绍的就是产品质量保证环节中最重要的环节——软件测试(其实是软件测试中测试用例设计过程)。
软件测试在整个产品生命周期中的重要性是毋庸置疑的。虽说产品的质量不是测试测出来的,但不可否认软件测试是产品质量的保证环节,是产品上线前的最后一道屏障。测试人员通过分析需求、在把握产品全局的前提下设计测试用例,且根据用例进行测试执行达到保证质量的目的。由此可见,测试用例的设计是软件测试中非常重要的一环,是QA测试分析能力的主要体现,是功能测试的武功秘籍,是软件测试的必须遵守的准则,更是产品质量的根本保障。我们都知道影响软件测试的因素很多,例如软件本身的复杂程度、开发人员(包括策划、交互、开发和测试的人员)的素质、测试方法和技术的运用等等。因为有些因素是客观存在的,无法避免。有些因素则是波动的、不稳定的,例如开发队伍是流动的,老司机走了,新人不断补充进来;一个具体的人工作也会受到情绪的影响(最近比较烦)等等。如何保障产品质量的稳定呢?大家心中可能已经有了答案(毕竟已经铺垫了这么多),是的你猜对了,大声的说出你的答案吧,对,就是测试用例。只要有了测试用例,无论是谁来测试,只要参照测试用例来执行,都能保障产品的质量,可以把人为因素的影响减少到最小。即便最初的测试用例考虑不周全,但随着测试的进行和软件版本更新,也将日趋完善。此外,测试用例还能帮助产品新人了解产品的功能,毕竟只看交互稿的效果不太理想。因此,测试用例过程中的那些事是值得大家思考和总结的。
其实最初写这篇文章的目的,是将自己在项目中的测试工作进行总结及反思,记录下自己的所感所想。一方面对自己工作进行总结,锻炼下自己的写作能力,另一方面怀着哪怕有一丝可能帮助别人的奢望。
一、确定需求
可以说测试用例是需求的产物,因此在设计测试用例之前一定要确定明确的需求。只有需求明确,才能明确测试范围(功能点),才有可能设计出好的测试用例。互联网公司一般在新迭代开始前都会进行交互评审,确定下本迭代的需求。交互评审一般是非常重要的,测试用例设计的前提是需要有明确的需求。产品的功能复杂多变,交互策划同学负责不同的功能模块,因此交互策划同学在设计交互稿时很难考虑全面,毕竟企业级产品系统功能是比较复杂的。因此QA要规范流程,推动产品提前给出交互稿,我们需要提前去review,注重分析业务逻辑,在交互评审会议的时候,一定要站在全局的位置进行考虑,毕竟测试是最熟悉系统的人,遇到交互稿中的争议点,勇于站出来提出自己的见解,经过讨论会将相关的疑问提前给交互需求同学重新确认。很难想像根据一份有瑕疵的、甚至是严重争议的交互稿编写出来的测试用例是有着多么可怕的“指导”作用。因此我们在编写测试用例之前,一定需要确定需求范围,深入理解产品的交互稿,在交互评审后,可以通过会议的方式深挖需求点,QA及前后端同学、交互一起讨论,各自提出自己的见解或疑问,查漏补缺,经过讨论将相关的见解及疑问明确化,最终得到解决。通过大家的讨论去不断完善交互、不断补充交互、最终保证交互稿应该不存在任何的歧义或含糊的地方,这样将有力的推动测试用例的编写。
二、测试用例需要不停的改变
昨天的你不是今天的你,没有任何事物是一成不变的,测试用例也是如此,尽管我们通过第一步已经尽可能的去完善交互稿,但是需求也是不断变更的,会进行局部的调整,因此我们的测试用例也要同步的更新,千万不要交互稿更新了、开发的实现也是按变更的需求实现的,唯独用例还是旧的,这样在开发冒烟自测时就会起到误导,如果开发按照用例去修改将不满足需求,但执行用例时就不会发现错误,导致走查甚至上线后才发现问题,为时晚矣,因此测试用例要与需求同步。QA都是思维比较发散的精英人士,因此在根据交互稿设计用例时经常会有较深入的理解,比如某些功能不太合适,某些功能实现之后会出现数据不一致的场景、某些操作比较麻烦...等等较多的想法,这个时候如果你认为合适就勇敢的去找交互pK吧,一定要大声说出来,很有可能交互就会被你说服,用你的设计,这样会不会很有成就感,但一定记得修改测试用例,保持同步更新。当在执行测试用例时,我们会去探索测试或是测试过程中自然而然的出现了一些测试用例中没有用例对应的bug,这个时候我们就要思考下,为什么没有?是分析的不够,还是自己思维有限没有想到?总结下、分析下,应用到以后的用例设计中。同时也要把这些bug对应的用例更新到测试用例中去,有人可能会有疑问,我都发下bug了,开发已修复了,为什么还要补充呢?反正也不执行了,但是同志,你测的功能不可能永远都是你测,即使是你测了,但由于逻辑惯性下次这些用例你可能还会遗忘。因此需要本着负责任的态度,积极的将其补充到用例中去,一为了以后别人测这部分功能做个参考,二也是对这些用例加深了印象。测试用例的跟新周期不是随着项目的上线而终结的,应该是只要有价值的用例,我们都应该更新。当然,产品下线了,就不需要更新了,毕竟这是真的没用了。
三、用例评审方式
用例评审是测试用例确定的前提,是保证项目质量非常重要的一环,因为这是测试、开发、产品三方确认的环节,不仅是保证开发实现功能符合产品需求,避免遗漏需求的功能点,而且还可以补充用例场景、帮助开发理解用例。用例评审可以提早暴露三方有歧义的功能点,及早改正修复。用例评审的目的及意义大家已经知道了,那么如何做好用例评审呢?其实用例评审的内容每个项目组可能各有不同,毕竟实际场景不同。其实用例评审理想状态下是应该评审所有用例,达到确认所有需求功能点。但在实际项目中,应该很少项目组可以做到这一点,毕竟快速迭代的大环境下,大家都是惜时如金的,不希望浪费在很简单的需求点。因此,用例评审主要评审冒烟用例和复杂业务逻辑的功能点,评审冒烟用例大家都知道,毕竟是主要分支必须要通的,也是开发自测时的冒烟执行集。因此,有必要去评审,三方确认。复杂业务逻辑的功能点可能异常分支较多,冒烟用例中很难盖全,所以在用例评审时,我们可以主动提出特别是异常场景的情况,帮助开发去考虑实现(如果你不提及,开发很有可能就不考虑,这样在提测后发现,以bug的形式去修复,时间成本就非常大而且也增大了我们的工作量,毕竟bug越少我们测起来就越爽)。大家在实际项目中可能会发现开发自测的通过率通常是100%,但是我们冒烟测试却不是。这个是和令人深思的问题,一样的环境,一样的用例,为什么是不一样的结果?难道是因为执行的人不一样(开个玩笑,当然不是),准确的说应该是执行的方式不一样。为什么会执行的方式不一样?可能说是用例描述的不清晰,这可能是原因之一,但其实大部分用例我们写的还是很认真的,还是比较通俗易懂的。造成歧义的关键我认为是用例评审时的问题,要么是我们描述的不清晰,要么就是开发听的不认真,其中第二个原因我认为是主要原因(我还是比较相信大家的实力的)。因此,在用例评审时,我们声音要洪亮、吐字清晰的前提下,要把控氛围,吸引开发同学去听,引导他们去提意见。比如某功能较复杂,你认为有些地方会出错,或是会出现歧义,再用例评审时你可以询问相关开发,听听他的理解,再同步产品看看他的意见。这样的好处就是三方同步,而且还能吸引大家的注意力让他们听用例,避免用例遗漏。再有就是可以采取强硬措施,如果开发在用例评审时对用例没有歧义,那么过后用例将不做修改,如果实现与用例不一致,按bug处理(这样的做法还是为了用例评审的高效,即便很难执行,但是我们在用例评审如果这样说还是可以起到一定作用的),再有就是在实际用例执行中这样实行,那么应该就会引起开发的重视(比如说执行用例时,发现不一致,我们可以和开发确认,为什么不一致,如果开发以为用例是别的意思,和他认为的不一致,那么这就是bug,并再提醒用例评审需认真,反复强调,引起他们的重视),端正开发用例评审时的态度,避免用例的理解歧义,提高用例评审的效果,提高版本的提测质量。
四、测试用例编写的浅薄建议
如何写好测试用例可以说是QA比较关心的话题,网上也有很多资料,各有各的想法。我感觉只要是适合的就可以了,只有写的用例符合开发可以看懂,没有歧义,尽量覆盖较多分支等要求就是比较好的用例。给出平时项目中自己写用例的一些心得,不是说写的好只是总结写,用于取之,感觉不对大家可以通知我,给个学习机会。
4.1、tc平台上编写用例,是方便用例管理及开发和测试进行测试执行,因此建议按照功能创建目录最好是严格按照交互稿中功能目录进行创建,这样在用例评审及测试执行时可以很快定位到该用例对应交互稿中的功能点,方便对模糊用例或有歧义的地方进行两方确认。如果用例目录结构比较混乱,降低可读性。
4.2、测试用例的划分要单一,建议是一个用例验证一个功能点即单个用例覆盖最小化原则,这样的好处是用例简单易懂且可读性较好,而且用例不通过时也不会有歧义,方便开发冒烟自测及测试执行。如果用例验证的功能点较多,例如功能A有三个子功能a、b、c,我们就需要在一个用例中验证这三个功能点,对于用例的创造者可能问题不大,毕竟是自己写的也能理解和验证所有的功能点。但是对由于其他执行者比如开发,可能提高他们在冒烟自测中漏测的概率,大家应该都有一致的认知:开发都是比较粗心的,如果开发执行该用例过程中少验证一个比如c功能,然后他认为这个用例是过的(他不知道该验证点)。在测试冒烟过程中,测试验证开发漏测得功能点是错误的,认为这个用例是失败的,这样就会导致两方的歧义或争论。因此,在设计用例时应该遵循单个用例覆盖最小化原则,用三个用例去覆盖。
4.3、测试用例中举例的数据要明确,特别是前提数据和执行步骤后验证的数据。比如说期次A、B、C,将期次A拖动到B后,则顺序应为B、A、C。这样用例则执行时比较清晰,可操作性较高,对于执行后的结果也比较清楚。如果我们这样写有三个期次,将一个期次拖动到某个期次下,则顺序应正确显示。这样比较隐晦难懂,且目的不明确。
4.4、测试用例应该需要明显的验证手段。在编写测试用例中我们的预期结果不能仅仅描述程序的可见行为,还应该验证数据库,最佳的验证方案就是验证数据库中表的更新、字段的更新。因为预期结果不仅仅是程序的可见行为。例如,以企业云为例,对于已创建课程,点击【删除】按钮,系统提示“删除成功”且在课程列表中消失。这样是不是就可以了?当然不是,应为课程关联的可能有其他数据,存在其他关联关系,我们执行删除课程,可能仅仅是将课程从课程表中删除了,这样满足了“系统提示“删除成功”且在课程列表中消失”预期结果,但是与其关联的关系很有可能没有删除,那么这些数据可能就会成为幽灵数据,如果其他功能没有依赖该关系,那么数据就是无效数据被遗弃在数据库(数据库很大,还好毕竟功能是好的没有bug)这是比较好的情况。但是如果其他功能依赖于该关联关系,那就比较麻烦了,会引起bug。简单介绍下场景:比如说课程A关联某个数据B,删除数据B是会校验数据B与其他数据是否存在关联,若存在在无法删除。那么如果删除A是没有删除AB之间的关联关系(且该关联关系只有删除课程时才会被删除),那么我们就无法删除数据B,这样就造成了一个bug(虽然满足预期结果)。因此,在实际用例中还应该包括对预期结果的显示验证手段:1.在数据库中执行sql语句进行查询该数据是否删除2.确认删除该数据时还应确认删除其他的数据,并执行sql语句进行查询与其依赖的数据是否真的删除。最终再判断是否满足我们的预期。
4.5、用例设计应该解耦,用例之间的耦合性越高就越难测试,降低回归测试的效率。
例如:如果
Test_a_b_c
是一个
自动测试
用例,并按照a
->b->c
的顺序来执行的,当a
存在
Bug
时,整个测试用例就失败了,而b
和c
并未被测试执行到。如果此时a
的
Bug
由于某些原因需要很长时间才能修复,则
Test_a_b_c
始终被认为是因为a
的
Bug
而失败的,而b
和c
则始终是没有被覆盖到,这里存在潜在的危险和漏洞。当你在产品就要发布前终于修复了a
的
Bug
,并理所当然地认为
Test_a_b_c
应该通过时,b
和c
的问题就会在这时爆发出来,这是不得不继续加班修复b
和c
的问题。不是危言耸听,当b
/c
的代码与a
的
Bug
修复相关时,当你有很多如此设计的测试用例时,问题可能会更糟。因此
,
Test_a_b_c
这样的设计,减少地仅是一次性设计和自动化的投入,增加地却是需要多次投入的测试执行的负担和风险,所以需要决策时
(
事实上这种决策是经常发生的,尤其是在设计测试用例时
)
选择
Test_a_b_c
还是
Test_a
、
Test_b
和
Test_c
,需要慎重考虑投入的代价。
提出一些个人的经验、建议,考虑的不是很全,希望大家提出意见和补充。
网易云新用户大礼包:https://www.163yun.com/gift
本文来自网易实践者社区,经作者付二帅授权发布。