`
lane_cn
  • 浏览: 53697 次
社区版块
存档分类
最新评论

单元测试应该测什么,不应该测什么?

阅读更多

刚才看了idior的一篇文章:Enterprise Test Driven Develop。看后有一些感想,在这里写下这篇文章,讲讲我对这个问题的看法:自动化的单元测试应该测什么。

最近有朋友提出意见,觉得我写的文章比较空洞,写的很长,但是很不实在。可能原因是这样的:代码太少了。今天就从一段代码开始吧,这段代码描述电信营业系统中的缴费开机的过程:

User user = User.getUserByServiceId("13309790280");//通过电话号码找到用户
Account account = user.getAccount();//与用户关联的帐户
user.pay(100);//用户缴费100元

//判断用户余额+帐户的信用度-用户欠费是否大于0
if (user.getBalance() + account.getCredit() - user.getDebt() > 0)
{
    Service service 
= user.getService();//与用户相关的服务
    
//判断这个服务是否处于欠费停机状态
    if (service.getState() == "欠费停机" || service.getState() == "限制呼出"
    
{
        …
//向交换系统发出开机指令
    }

}

这是电信营业系统中最常见的的一个业务。电信系统最基础的模型应该说是"三户模型",三户模型描述的是客户(Customer)、帐户(Account)、用户(User)以及服务(Service)等等概念的一个关系模型。实际的模型比代码里的复杂,这里简化了很多,主要用来举个例子。

要开发一个电信系统,首先要做的就是在系统中实现最基础的几个模型,比如三户模型、联机指令模型、业务办理模型、合作伙伴模型……,其中三户模型处于非常重要的地位。首先要做的是在软件系统中真实的反映这个模型,绝不可以将其隐含扩散在各个业务过程中。然后就可以在这个基础上,从一到二、从二到三、从三到万,实现各个子系统和复杂多变的业务需求。

按照TDD的开发思路,我们应该先写测试代码,再来写实际程序,用测试来推动开发的前进。这里先把代码写出来,表达一下业务。下面我就说一下,单元测试代码应该测什么。

我们拿User举个例子,现在我们要写User类的测试代码。

需要测什么?

我们需要测试User类的外在表现。比如我们要测试pay方法,应该这样:

我们建立一个User对象,这个User余额是0,欠费38元。现在缴费100元,缴费完成后,余额应该是62元,欠费应该为0,这是一个Case。

我们建立一个User对象,这个User余额是30,欠费0。现在缴费50元,缴费完成后,欠费应该仍然是0,余额应该是80元。这是第二个Case。

我们建立一个User对象,这个User的余额是0,欠费150元。现在缴费70元,缴费完成后,欠费应该是80元,余额应该是0。这是第三个Case。

我们应该测试的是User类的外在表现,而不应该过问他如何实现。

在测试的时候,我们需要一个可以重复的稳定的环境(真实环境往往不行),有时候无法直接建立User对象(比如User对象要依赖一个数据集),有时候真实的环境很难实现一些测试条件(比如边界值、非正常值)。这时候,我们就可以使用Mock、Stub这样的方法,把User建立起来,也把环境建立起来,然后测试User的表现。

不需要测什么?

还是拿User举例子,还是测试pay方法,我们不应该测试这些东西:

缴费如何实现,这个费用保存到哪个数据表的哪个字段里去了,是否符合某种数据关系。

缴费以后的余额、欠费按照什么变量加减或者从某个数据字段中得到自己的值。这个不需要测。User类应该负责自己的费用问题,不应该把任何业务逻辑暴露给其他类(费用保存到哪里、什么数据结构,User应该负责)。外界只关心User的表现。

缴费后应该不应该向交换机发送开机的指令,这个就更不需要测试了,这是User的调用者应该负责的事情。

测试代码保证了什么?

测试代码只保证接口是正确的,至于业务正确不正确不是最关心的事情。比如User的测试代码,User把费用保存在数据表里、还是写在文件里,他是不关心的。甚至根本没有持久保存,他也不管,只要接口正确就通过。当然,内在实现上的错误总会通过接口表现出来。假如User没有把用户缴费保存起来,当我们在另外的空间中建立相同ID的另一个User对象时,就会得到错误的余额和欠费。

单元测试究竟有什么用?

从某种角度上说,单元测试并不能保证业务的正确性,而只能保证接口的正确性(严格的说,其实连接口的正确性也无法保证,他只能保证接口"没有这些错误")。如果一个类总是自己在默默的工作着,不提供接口告诉外界他干了什么,测试他的业务是很难的(也不应该去测试,否则必然要插手他的业务)。那么单元测试究竟有什么用呢?

单元测试保证模块修改后的兼容性。可以通过单元测试来判断一个模块在修改后是否与修改前保持兼容、多大程度上不兼容、影响范围有多大。开发者就可以更加专注于模块内部的业务。单元测试无法代替人工的工作,他能够做到的是衡量一个模块修改后会不会影响其他模块的工作。这对程序的维护和升级有非常大的好处。
 

分享到:
评论

相关推荐

    单元测试说明模板

    单元测试是软件测试的基础,是软件开发过程中不可或缺的一部分。 单元测试的目的是为了确保软件的每个组件都能够正确地执行其功能,并且在集成时不会出现问题。单元测试可以帮助开发人员早期发现代码中的错误和缺陷...

    软件单元测试报告.doc

    软件单元测试报告 软件单元测试报告是软件开发过程中的一种重要文档,它记录了软件单元测试的结果和过程。下面是该报告的知识点总结: 一、软件单元测试报告的组成部分 软件单元测试报告通常由以下几个部分组成:...

    软件单元测试入门与实践,软件单元测试入门与实践 周立功,C,C++

    在RTT(Real Time ThreadX)操作系统环境下,单元测试的重要性不减。虽然RTT是实时操作系统,但其内核组件和用户应用程序同样需要经过严格的测试。通过单元测试,开发者可以确保每个任务、中断服务例程或内核服务的...

    单元测试

    3. 模块化:单元测试的目标是隔离测试,因此需要确保被测单元与系统其他部分解耦。这通常需要使用依赖注入(Dependency Injection)技术,使测试时可以替换掉真实的依赖,用模拟对象(Mock Object)或存根(Stub)来...

    单元测试报告模板.doc

    《×××单元测试报告》是对软件开发过程中某一模块或组件进行独立验证的文档,它详细记录了单元测试的过程、结果以及可能遇到的问题。单元测试是软件开发中的关键环节,旨在确保代码的各个部分按预期工作,从而提高...

    精心汇总的5类软件模版下载(单元测试计划、单元测试报告、测试方案、功能测试报告、性能测试报告)

    本资源包精心汇总了五类重要的软件测试文档模版,包括单元测试计划、单元测试报告、测试方案、功能测试报告以及性能测试报告,这些都是软件测试工作中不可或缺的部分。 1. **单元测试计划**: 单元测试计划是软件...

    软件测试小论文----单元测试及测试工具的研究与应用

    任何软件开发团队都不愿意因为节约了早期单元测试的时间导致开发的整个产品失败或重来。 在软件测试中,单元测试的学习具有较大的难度。在软件测试课程中,对于单元测试的学习具有较大的难度。因此,需要正确熟练的...

    什么是单元测试?如何做好单元测试?

    什么是单元测试?如何做好单元测试? 单元测试是指,对软件中的最小可测试单元在与程序其他部分相隔离的情况下进行检查和验证的工作,这里的最小可测试单元通常是指函数或者类。   单元测试都是以自动化的方式执行...

    软件单元测试讲义ppt

    1. 单元测试应该是独立的:每个测试用例应独立于其他测试,避免因相互依赖而产生的复杂性。 2. 可重复性:每次运行测试,结果都应一致,不受环境、时间等因素影响。 3. 自动化:单元测试应自动化执行,便于集成到...

    C++单元测试三大框架的比较

    C++单元测试三大框架的比较软件测试1、TUT结构框架简单。添加新的测试工作量小;无须注册测试;可移植性好(因其只需两个头文件,就可以完成测试工作);便于装卸;提供接口可以扩展其输出方式等。最大的优点:轻量级,...

    单元测试培训文档.pptx

    3. **低估单元测试的价值**:一些团队认为单元测试带来的收益并不明显,反而会占用大量的开发时间,从而选择不编写单元测试。 4. **业务逻辑过于简单**:对于一些简单的业务逻辑来说,开发者可能会觉得编写单元测试...

    C++单元测试简单示例

    首先,我们需要理解什么是单元测试。单元测试是对软件中的最小可测试单元进行检查和验证的过程。对于C++,这可能是一个函数、一个类的方法或者一个独立的对象。它的目标是确保每个独立的部分都能按照预期工作,从而...

    CMMI单元测试用例及测试结果记录

    CMMI单元测试用例及测试结果记录 CMMI(Capability Maturity Model Integration,能力成熟度模型集成)是一种软件开发能力成熟度模型,旨在提高软件开发组织的能力和成熟度。其中,单元测试是CMMI模型中的一个重要...

    单元测试 Vector Cast Train资料

    2. **单元测试基础**:单元测试通常遵循 Arrange-Act-Assert(AAA)模式,即先设置测试条件,执行被测代码,然后验证预期结果。Vector Cast提供了方便的API和测试驱动开发(TDD)支持,帮助开发者编写简洁且易于理解...

    单元测试之道Java版.pdf(高清)

    根据提供的文件信息,“单元测试之道Java版.pdf(高清)”主要介绍了在Java开发环境中进行单元测试的方法、策略及最佳实践等内容。以下将基于该文件的标题、描述、标签以及部分内容来详细阐述相关的知识点。 ### ...

    单元测试之道(Java):使用JUnit进行单元测试

    单元测试之道(Java):使用JUnit进行单元测试。单元测试是提高代码质量的有效手段,但大部分开发人员由于种种原因都不乐意进行单元测试。

    Struts2SpringUnitDemo单元测试

    Struts2SpringUnitDemo是一个示例项目,展示了如何在Java应用程序中将Struts2和Spring框架进行集成,并进行单元测试。这两个框架都是Java Web开发中的关键组件,Struts2负责控制层逻辑,Spring则提供了全面的依赖...

Global site tag (gtag.js) - Google Analytics