求知 文章 文库 Lib 视频 iPerson 课程 认证 咨询 工具 讲座 Modeler   Code  
会员   
 
  
 
 
     
   
分享到
关于自动化测试
 
作者:余昭辉,发布于2012-2-10
 

概述

常见的三类自动化测试有:单元测试,集成测试以及功能测试。

单元测试

单元测试是一个白盒测试,一般是针对一个方法单元进行的测试,单元测试要求运行快,编写简单。所以一般单元测试有这么一些特质:

  • 不连接数据库
  • 不访问磁盘文件
  • 不访问远程网络

能够在很短时间内运行完毕(比如三秒内)

集成测试

集成测试可以称之为灰盒测试,是指对系统中几个模块集成起来进行测试。有很多时候,单元测试无法发现的问题,通过集成测试能发现。

功能测试

功能测试是黑盒测试,完全从系统的功能边界外,不对系统内部做任何假设,就以用户的方式对系统进行使用测试。功能测试运行是最慢的,编写和维护都非常困难。但是对交付成功的软件的价值确实最大的。

测试能给我们带来收益,但是测试也需要我们投入很多精力。如何能在投入和收益间找到平衡,就需要我们在系统中结合这三种测试。一般,系统中单元测试最多,集成测试次之,最少的是功能测试。这就是经典的测试三角。

对自动化测试的误解

自动化测试能防止bug

这是对测试最常见的误解,测试不能帮助我们防止bug,写了很多测试,并不意味着我们的系统就不会出现bug。自动化测试是防止我们在演进系统的过程中,引入新的bug。因为人工的测试非常缓慢,如果我们修改了代码,需要等待很长时间才能知道我们的修改是否正确,这就会给修改代码带来很大的风险,有可能我们就不等待人工测试的结果就交付产品。如果我们有一套能很快运行的自动化测试集,我们就能更快的验证我们的修改是否对已有功能造成破坏,是否引入了新的bug。认识到这一点,那就要调整一下心态:有可能有人看到长期以来,测试也没有帮住我们什么,就不愿意写测试,觉得不值得。我觉得这是好事,那说明我们开发能力很高,很少出现bug。如果bug很多,自动化测试并没有起到防止引入bug的作用,我们就应该调研,如何写质量更高的测试。

总结:自动化测试是一种快速反馈的手段。

测试代码不是交付的一部分

很多人认为,我们编写的产品代码才是我们要交付给最终用户的东西,而测试代码不是。所以我们可以以随便的态度编写自动化测试代码,在产品代码中应用的一些最佳实践或原则,我们可以不应用到测试代码中。这个观点也是错误的,不维护的自动化测试,比没有自动化测试更有危害。

第一,不维护的自动化测试很难跟随产品代码同演进,可能已经丧失了他原有的作用,而我们心里却以为我们有自动化测试,但实际上那只是摆设,只会误导我们。

第二,如果需求改变了,我们需要修改测试,让它体现最新的需求,但是因为测试年久失修,变得很难看懂,很难修改。那么最大的可能就是:删除测试代码,那么我们花在自动化测试上的时间就付诸东流了。只在最后阶段运行测试

其实这一条和第一条有相似之处,很多人认为既然是测试,那么就应该在测试阶段跑,而我们现在在开发产品代码,这是开发阶段,我们不应该运行测试。按照第一条最后的总结,自动化测试是一种反馈手段,那么我们更应该持续不断地,频繁的运行测试。当我们对代码有修改时,就运行测试;当发现测试失败后,立即修复,以免将这些债留到后期,那个时候修复的成本将更高昂。

实践

以可测试性为目标来编写代码

即使我们不采用测试驱动开发(TDD)的方式开发产品,但我们也应该将可测试性这条准则铭记在心。你编写的代码无法自动化测试,或难以自动化测试就必须依靠人工手动测试。人工测试会有疏漏,而且重复两次的测试可能有些少许的不同,都会疏漏一些重要的问题,或者难以重现bug。

比如我们要尽量避免与一些难以测试的部分紧耦合,比如连接数据库部分,向屏幕打印输出的部分,发送短信的部分等。比如你在一个类里,需要发送邮件,现在你需要测试这个类里的逻辑,这个时候你并不是为了测试发送邮件的客户端。如果你这个时候直接使用发送邮件客户端的静态方法,这就是一种非常强的紧耦合,如果我们想自动化测试这个类,我们就无法用花费更小,运行更快的单元测试甚至是集成测试来测试这段代码,我们就必须在功能测试这个层次来测试。

测试应该可以重复运行

第一个测试运行完毕后,修改了第二个测试所依赖的一个关键数据,测试运行不了了,必须人工干涉测试才能继续进行。这种自动化测试也是没有任何价值的。

幸好,我们有事务这个好东西,在事务开始时我们准备数据,然后运行测试。在测试完毕后,我们回滚事务,没有污染数据库。就拿基于Spring的集成测试为例:

Integration.java

@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations="classpath:applicationContext-test.xml")

@TransactionConfiguration(transactionManager = "txManager") @Transactional public abstract class IntegrationTest { }

我们添加@Transactional标签,让我们的测试在事务中运行。为了避免所有的测试类,都要带上那堆标签,为此提取一个基类。基类设为抽象的是因为,一个没有任何测试的测试类,maven运行这类测试的时候会报错误。

如果在某一个测试中我们不想让事务回滚,我们可以添加@Rollback(false)标签(这一般在调试时很有用)。

AgentServiceIntegrationTest.java

public class AgentServiceIntegrationTest extends IntegrationTest{ @Before public void setUp(){ } @Test public void should_find_agent_by_id(){ } @Rollback(false) @Test public void we_want_to_store_data_in_database(){ } @After public void tearDown(){ } }

何时添加自动化测试

调试

当你打开调试器,一步一步的调试代码来找出那个纠结的问题时,为什么不添加一个自动化测试来帮你定位问题呢。很多时候,这类调试甚至要启动一个tomcat才能进行。

打印输出

我在有些代码里看到过System.out.println("test"); 我估计是因为我们在用这种方式来寻找bug,这个时候也是添加自动化测试的良机,不要错过。

发现bug的时候

每个bug的发现,就说明你开发这段代码的时候忽视了某些问题,这个时候我们就应该添加一个测试复现这个bug,然后修复bug。而不是仅仅修复了事。


相关文章

微服务测试之单元测试
一篇图文带你了解白盒测试用例设计方法
全面的质量保障体系之回归测试策略
人工智能自动化测试探索
相关文档

自动化接口测试实践之路
jenkins持续集成测试
性能测试诊断分析与优化
性能测试实例
相关课程

持续集成测试最佳实践
自动化测试体系建设与最佳实践
测试架构的构建与应用实践
DevOps时代的测试技术与最佳实践


LoadRunner性能测试基础
软件测试结果分析和质量报告
面向对象软件测试技术研究
设计测试用例的四条原则
功能测试中故障模型的建立
性能测试综述
更多...   


性能测试方法与技术
测试过程与团队管理
LoadRunner进行性能测试
WEB应用的软件测试
手机软件测试
白盒测试方法与技术


某博彩行业 数据库自动化测试
IT服务商 Web安全测试
IT服务商 自动化测试框架
海航股份 单元测试、重构
测试需求分析与测试用例分析
互联网web测试方法与实践
基于Selenium的Web自动化测试
更多...