三、可测试性和健壮性

  首先想说说可测试性,而这其中先要交代的是测试的方法。

  大家都知道,在一个系统的开发过程中,有很多测试环节,而这些测试环节与设计与开发环节又都是相互对应的,大概是这样:

  单体测试----->详细设计
  结合测试----->概要设计
  业务测试----->需求分析

  但是,在不同的开发环境中,所采用的测试方法也都是不一样的。

  通常我们都会使用人工的测试方法,尤其是对于界面上的一些元素针对特定操作的反应,只有真正能够得出想要的结果,那样才能够算是做好了这个功能。

  但即使是人工的测试,详细的程度也会有所不同:在对日项目中,因为会有人针对详细设计编写详细的单体测试设计书,然后会有测试人员按照这份文档,对界面上的每个功能都做详细的检查,看所提供的功能是否复合设计书上的要求。而对于整合测试,同样会有类似的文档以及更高一级的测试人员来完成相应的工作。并且,日本使用计算机的程度普遍比较高,到了用户那里,同样会测试出一些问题。经过详细的三个步骤,加上厚厚的文档,终交付使用的产品一般质量会比较高。

  而对于国内的项目,很多时间抽不出那么多人来做那么多的流程,所以一般测试都比较简略,而很多开发人员对于应该怎样测试自己的程序也不甚了解,只测试理想的情况,很多的边界情况和特殊情况都考虑的不够。再加上整合测试做的不够,一般交给用户测试的时候,会有比较多的问题。

  在这里,有人可能会说,我们做国内项目的并不是不想测试,也不是不会测试,而是时间紧、任务重,要么要质量、要么要进度,二者权衡取其重,所以我们用质量来换速度。客户明天要了,我才做好,哪有时间测试啊。

  但是,我还是觉得那样做,其实是在饮鸩止渴,项目之所会砸掉,很多都是因为用质量换进度造成的。

  上面有些扯远了,其实我在这里想要说的可测试性针对的是另一种测试方法,也是利用xUnit工具进行的自动化单元测试。

  关于此经典的东西可能是那本《测试驱动开发》了,每次拜读的时候都会受益匪浅。

  然而,在很多情况下,想要达到那样的目标都比较困难,因为那需要编写很多测试代码,而那些代码对于程序本身,或者更清楚一些,针对用户是毫无意义的,只是用来保证我们确实实现了所需要的功能。而且,开发人员编写程序代码的时间都比较紧张,怎么会有时间再去编写一份测试代码呢?

  我也是一样,似乎到现在真正编写过的自动化测试代码也不超过20个,只有在觉得时间比较充裕,而且感觉到测试的步骤很多,必须需要自动化测试来帮忙的时候才会那样做。

  其实,测试代码与其说是给自己编写的,不如说是给别人编写的,给整个项目组编写的。

  我们经常会遇到这种情况,修改一个程序,改好了之后,自己测试了没问题,但是发布了之后,发现其实有一种情况没有考虑到,或者说原有的程序中有一些特殊的处理我们不知道,结果会导致在某些情况下程序崩溃。

  如果有自动化测试代码,特别是自动化的整合测试代码,可以在某种程度上改善这种情况,每次在修改之后,只修改相关的测试代码,而不变原有的,那样执行一下,闪闪发光的小绿条和小红条会告诉我们的修改是否合理了。

  因此说,如果说自己的代码在可测试性方面完成的话,那必须有相对应、比较完善的自动化单体测试代码,并且测试的代码覆盖率达到了一定的程序,比方说80%以上。

  接下来,我想说的是什么样的程序是健壮的,看我的程序的抗击打性如何,哈哈。

  曾经在做对日项目的时候,有这么一种说法(大家一定觉得奇怪我怎么总是提对日开发,希望大家不要对一件事物全盘肯定和否定,其实对日、对国内、对欧美三种开发模式都各有各的优点,也各有各的缺点),那是叫做“猴子测试”!

  猴子怎么会测试呢?当然不会,他们所说的是,像猴子一样测试,因为猴子什么都不知道,它只会在键盘上一顿乱敲,在鼠标上一顿乱按,是吧,哈哈。

  而猴子测试方法是这样,拿过一个程序,打开界面,然后乱弄一顿,看看程序报错了没?如果程序崩溃了,那意味着你的程序的健壮性不够啊,被猴子给搞定了,哈哈。

  解决这个问题可不是那么容易的,首先必须要对所有的输入进行比较完善的验证,比方说字段的长度、是否是数字、数字的范围、是否子日期类型、日期的范围、成对日期之间的比较等等,一切都需要校验。此外还有对数据库方面的校验,比方说是否有重复的主键,是否有不可为空的输入,是否超出了数据库所定义的范围等等。另外还有对业务的校验,这个需要针对具体的情况了。如果没有校验的话,麻烦了,一方面这些非法的输入到程序中处理会出错,或者存放到数据库中的时候会出问题。而缺少对业务上的校验,可能产生的数据非常不合理,闹了笑话。总之,我们首先要做的是校验!校验!校验!

  除了验证之外,是对异常情况的处理,那不是错误,而是一种我们预料之中的一种特殊情况,可能不符合一些标准,而这里正是考验一个程序员的经验是否丰富的地方了。知己知彼、百战不殆,如果你能够知道程序在什么情况下可能会出错,并在相应的地方设置好“陷阱”给它,那么你是战无不胜的大将军了,哈哈。

  而这两种操作,对于Winform形式和Web形式的应用,或者说针对C/S和B/S的程序,总体的思想是一样的,而细节上的处理又会有不少的不同,这些也只能具体情况具体分析了。