在软件测试认识学习中存在的误区
发布于 2021-05-11 20:07 ,所属分类:软件测试工程师学习资料
测试在软件开发过程中一直都是备受的,即使在传统的软件工程中,也有一个明确、独立的测试阶段。随着软件危机的频频出现以及人们对于软件本质的进一步熟悉,测试的地位得到了前所未有的提高。测试已经不仅仅局限于软件开发中的一个阶段,它已经开始贯穿于整个软件开发过程,人们已经开始熟悉到:测试开始的时间越早,测试执行的越频繁,所带来的整个软件开发成本的下降就会越多。Extreme PRogramming更是把测试推到了极限的位置,一切软件开发活动都要从首先编写测试代码开始。
但是,相对于测试这个词的流行程度而言,有关测试教育方面的工作做的还远远不够,很多关于测试的文章都是针对某种测试工具使用方面的,而测试工具厂商也往往出于商业的目的对于测试工具的作用夸大其词。这样,很多的软件从业者就很轻易陷入一些误区,导致了测试并没有在他们所在的软件开发项目中起到有效的作用。下面几个小节将对于一些比较具有代表性的误区进行剖析,并对于测试背后所蕴含的一些设计思考进行了阐述,希望能够起到抛砖引玉的作用。
误区之一
在测试领域中也一样如此,一个软件开发团队往往认为只要自己使用了某种软件测试工具,那么就应该可以获取测试带来的种种好处,这种想法当然是错误的。因为,要想对一个软件或者模块进行有效的测试,首先该软件或者模块应该是可测试的。可测试性是反映软件质量的一个内在属性,不会因为你使用了某种测试工具进行了测试行为,就使得被测试的软件具有了可测试性。假如被测试的软件本身并不具备可测试性,那么使用多么昂贵的测试工具进行测试所能够带来的收益都是微乎其微的。
要想真正获取测试带来的巨大好处,并且使得测试工具能够发挥最大的效率,要害就是要使软件本身具有很好的可测试性。这种能力的获取是一个逐步的过程,是不可能一蹴而就的。最要害的一点就是要不断实践,不断学习一些优秀的经验,不断的反思。要想获取好的结果,就必须要付出努力,这是亘古不变的真理。Extreme Programming中的测试先行的实践倒是一个很好的起点,具体可以参见参考文献[3]。
对于测试工具的选择,只要满足需要并能够自动运行测试用例就可以了。不要一味的追求复杂的功能和不必要的灵活性。对于大多数项目来说,一些非常闻名的源码开放的测试工具就足够了,比如:java方面的单元测试工具JUnit和C++方面的单元测试工具CppUnit。关于验收测试方面,目前没有比较好的满足各方面需要通用的测试工具,不过使用脚本语言,循序渐进的自行开发一个适合自己的验收测试工具也不是一件困难的事情,一句话:只有提高了自身团队内在的素质,外在的工具才能够发挥作用。
误区之二
假如一个软件模块必须要通过图形界面才能够触发它的应用逻辑时,那么要对这个软件模块进行测试时就必须要使用图形界面。但是图形界面又是很难测试的。看起来似乎很难办。让我们换一个角度考虑一下,其实我们真正想要测试的是软件模块本身的应用逻辑,而不是图形界面的触发逻辑。假如我们在设计时能够把被测试的软件模块本身进行很好的封装,定义良好的服务提供接口,那么我们就完全可以通过软件模块本身提供的接口进行测试。这样就可以绕过难以测试的图形界面。造成上述软件模块很难测试的原因正是由于在设计时把软件模块本身的应用逻辑和图形界面这两个无关的逻辑耦合在了一起。把这两个逻辑分离,不仅可以对该软件模块进行更轻易、更有效的测试,而且也使得该软件模块具有了很好的可重用性和可移植性。
那么对于不好测试的图形界面,我们该怎么办呢?原则很简单,假如某种东西不好测试,那么就让它做肯定不会出错的事情,而把可能会出错的逻辑剥离出来,放到一个可以测试的模块中。对于图形界面来说,就是仅仅保持一个很薄的图形界面逻辑,它的工作就是把用户的请求简单的转发给真正处理该请求的软件模块(一般称之为applicationFacade)。转发逻辑足够简单以至于它肯定不会出错,所以我们也无需对它进行测试。关于这方面更多的信息,请参见参考文献[5]。
假如在进行软件开发时能够首先编写测试代码,那么就会迫使你从易使用性,易测试性的角度开考虑问题,从而你就会专注于软件模块的高层抽象和职责。这样就会定义出清楚的、明确反映意图的模块接口来,另外,为了使得测试能够进行,你就会主动把那些导致不好测试的耦合去掉。这样的结果不仅仅是获得了可测试性,并且也产生了更好的设计和系统架构。
但是确实存在一些不好测试的东西并且很难只让它执行一些非常简单的逻辑,比如嵌入式系统中的BSP(板级支持包)。开发它们所使用的语言、环境以及它们本身的特性等决定了它们是很难测试的。这里说的难测试其实是一个测试代价问题,具体的说就是要付出更多的时间和努力。这就需要你在付出的代价和测试带来的收益之间进行平衡。假如付出的代价所带来的收益(更少的调试、维护、发布成本)是巨大的,那么付出的代价就是非常值得的。
误区之三
曾经看到过有关验收测试的这样一个案例,验收测试者使用昂贵的商用测试工具对一个具有图形界面的软件进行测试。测试的方法是通过编写测试脚本驱动鼠标在图形界面上随机的点击(当然每一次的点击,都点到了图形界面上可以接收事件的区域),然后等待着被测试软件的崩溃。当然这种测试方法可以作为验收测试的一个方面,但是决不是唯一的一个方面。还有更重要的内容被忽视了。
在针对类进行的单元测试中,也经常会看到一些错误的测试方法。很多的测试者往往针对类中的每个特定的实现细节进行测试。类中的特定的实现细节是很轻易变化的,在快速的迭代式开发中更是如此。一旦你测试的类中的某个实现细节发生了变化,你原先的测试代码就要进行相应的更改,否则就失去了意义。这种频繁更改的代价是巨大的。类是一种抽象,它反映了更高层面的内聚性,它应该有明确的职责和定义良好的服务接口,它的职责和对外的接口相对于内部的实现细节来说要稳定的多,并且我们要验证的正是这个类是否具备了它的职责。因此,在对类进测试时,我们应该针对类的接口来验证类是否实现了它的职责而不是其他。这样写出来的测试代码要稳定的多,也有效的多。
细想一下,造成轻易陷入针对实现细节测试的原因主要是由于先实现了类,然后才去进行测试。假如先实现了类的功能,然后在去对类进行测试,潜意识中就会不由自主的想去验证已经完成的类的某种实现细节。假如能够在编写实际类前,首先编写针对该类的测试代码,情况就会有很大的不同,因为这会迫使你从类的使用者的角度去考虑问题。结果就是会把点放在类的易用性上,放在类的职责上面,放在类提供服务的接口上面,而不是某种实现细节。
总之,测试代码的编写应该从被测试的对象是否满足需要的层面进行,而不是其他。
误区之四
我们还以经常用来和软件进行类比的建筑为例,首先给大家一个感性的熟悉。单元测试可以类比为一个建筑的质检人员对建筑进行的检测, 他的重点是建筑的内部结构、地基、框架以及墙壁是否垂直等。他的检测是要保证建筑的各个部分是正常的、安全的,换句话说,就是要保证施工满足建筑上面的质量标准。验收测试可以类比为建筑的使用者来对建筑进行的检测。首先,他认为这个建筑是满足规定的工程质量的,这是有建筑的质检人员来保证的。使用者的重点是住在这个建筑的中的感受。他关心建筑的外观是否美观、各个房间的大小是否合适,窗户的位置是否合适,是否能够满足家庭的需要等。这里,建筑的使用者执行的就是验收测试,他是从用户的角度出发的。建筑的质检人员执行的就是单元测试,他是从构建者的角度出发的。
正是这种角度的不同决定了单元测试和验收测试之间的区别。它们是对系统的不同的方面进行的测试,二者是互相补充的。不管我们在系统的构建中使用了多么聪明的方法,不管我们的系统是多么的灵活,但是首先我们的产品必须是可用的,否则我们所做的就是浪费时间,从这一点上来说验收测试要比单元测试显得更加重要。
还以上一小节给出的案例为例,案例中所使用的测试方法仅仅是从系统是否健壮的角度出发进行的,即使系统从不崩溃也不能证实那是一个可用的系统。因为测试根本就不是从用户使用的角度出发的,测试者本应该和用户一起来编写验收测试。单元测试保证我们把事情作对,而验收测试则保证我们做正确的事情。
关于单元测试和验收测试之间的明确划分,没有一个通用的标准,只有通过自己的不断实践来增加这方面的经验。你进行的有关测试的实践越多,你就会越清楚的感觉到单元测试和验收测试之间的界限所在。下面给出一些指导原则,在你编写测试代码时可能会有帮助。
假如一个单元测试要跨越类的边界,那么它可能应该是一个验收测试
假如一个单元测试变的非常复杂,那么它可能应该是一个验收测试
假如一个单元测试经常要随着用户需求的变化而改变,那么它可能应该是一个验收测试
假如一个单元测试比它要测试的代码本身要难以编写,那么它可能应该是一个验收测试
END
海学通教育是艺霖科技基于对IT产业的理解和IT教育实践的洞察,整合国内外众多优秀合作伙伴的教育资源和产品,依托前沿软件技术,通过与高校、政府合作,面向大学生、毕业生及社会个体提供更加符合IT行业发展需求的实训服务,包含IT企业内训,个体软件测试技术项目实训。并为企业提供技术过硬,职业化本领更强的可持续化发展人才。
开设的重点专业为全栈软件测试开发工程师。并与华为、软通、中软、阿里云、浪潮、IBM等知名企业及众多的高新产业信息技术企业建立了紧密的合作关系,保证人才的培养和输出。
END.
假如你想学习软件测试,
那就来海学通教育
打开更多想象力。
⬇️&留言讨论
相关资源