单元测试中,单元的选取原则?

按测试用例的设计方法,软件测试分为白盒测试和黑盒测试。 按测试策略和过程,软件测试分为单元测试、集成测试、确认测试和系统测试。 按软件系统工程,测试是软件质量保证的最后的一关。

高质量的程序取决于以下几个方面:

    高质量的设计 规范的编码 有效的测试

开发部的测试   效果不好:为什么?

没有时间测试 不知道怎样测试 不好组织 缺乏方法和工具    

这种情况下,往往把单元测试的任务堆积到系统测试阶段。

如果把单元测试的任务堆积到系统测试阶段,将会怎样?

大量的故障堆积在项目中后期:项目后10%的工作,占用了项目90%的时间。 故障难以定位 故障飘忽不定 开发、测试人员疲于奔命 

最高的成本收益比 减少联调和后续测试的时间 BUG更容易定位 更有信心去修改老代码 

单元测试可以是开发者本人执行,也可以是独立的专业测试人员执行。 两者各有优势。 建议开发人员必须完整地做单元测试,同时测试人员针对重点模块实施独立的单元测试。

1、单元测试的目标和任务

按阶段进行测试是一种基本的测试策略

定义:     单元测试是对软件基本组成单元进行的测试。

时机:     单元测试和编码是同步进行,但在TDD中,强调测试在先,编码在后。一般在代码完成后由开发人员完成,QA人员辅助。

1.1 为何要进行单元测试?

尽早发现错误   (错误发现越早,成本越低.    发现问题比较容易    修正问题更容易 ) 检查代码是否符合设计和规范

为什么要进行单元测试?

1.单元测试是不是太浪费时间了?

不经过单元测试,直接进入集成测试,系统正常工作的可能性非常低,大量的时间被花费在跟踪那些简单的Bug上,会导致集成为一个系统时增加额外的工期。 编写完整计划的单元测试和编写实际的代码所花费的精力大致相同。但是,一旦完成了这些单元测试工作,很多Bug将被纠正,在确信他们手头拥有稳定可靠的部件的情况下,开发人员能够进行更高效的系统集成工作,这才是真正意义上的进步。 调试人员的不受控和散漫的工作方式只会花费更多的时间而取得很少的好处。

2.单元测试仅仅是为了证明这些代码作了什么吗?

这是那些没有首先为每个单元编写一个详细设计文档而直接跳到编码阶段的开发人员提出的一条普遍的抱怨。这样的测试完全基于已经写好的代码,这无法证明任何事情。 单元测试基于详细设计文档,这样的测试可以找到更多的代码错误,甚至是详细设计的错误。 因此,高质量的单元测试需要高质量的详细设计文档。

3.我是一个很棒的程序员,是不是可以不进行单元测试呢?

每个人都可能犯错误。 真正的完整的系统往往是非常复杂的,不能寄希望于没有进行广泛的测试和Bug修改过程就可以正常工作。

4.有集成测试就够了,集成测试将会抓住所有的Bug。

系统规模愈来愈大,复杂度愈来愈高,没有单元测试,开发人员很可能会花费大量的时间仅仅是为了使该系统能够运行。 任何实际的测试方案都无法执行。 在系统集成阶段,对单元功能全面测试的负载程度远远的超过独立进行的单元测试过程。 最后的结果是测试将无法达到它所应该有的全面性,一些缺陷将被遗漏,并且很多Bug将被忽略过去。

5.单元测试的成本效率不高?

无论什么时候做出修改都要进行完整的回归测试。 在生命周期中尽早的对产品进行测试将使效率和质量得到最好的保证 Bug修改越晚,费用就越高,单元测试是一个在早期抓住Bug的机会。 相比后阶段的测试,单元测试的创建更简单,维护更容易,并且可以更方便的进行重复。 从全程的测试费用来考虑,相比复杂且旷日持久的集成测试,或是不稳定的系统,单元测试所需的费用是最低的。

一个尽责的单元测试方法将会在产品开发的某个阶段发现很多的Bug,并且修改它们的成本也很低。 系统开发的后期阶段,Bug的检测和修改将会变得更加困难,并要消耗大量的时间和开发费用。 无论什么时候做出修改都要进行完整的回归测试,在生命周期中尽早的对产品代码进行测试将是效率和质量得到最好的保证。 在提供了经过单元测试的情况下,系统集成过程将会大大的简化。开发人员可以将精力集中在单元之间的交互作用和全局的功能实现上,而不会陷入充满很多Bug的单元之中不能自拔。 使测试工作的效率发挥到最大化的关键在于选择正确的测试策略,这包含了完全的单元测试的概念,以及对测试过程的良好的管理,还有适当的使用好工具来支持测试过程。

开发流程时间表与修改Bug代价的关系图

编程过程中,每写1000行代码会犯几十个错误 编程与编译运行结束后,每1000行代码中大约残留有2-6个Bug 寻找与修改程序错误的代价占总体开发投资的30% -60% Bug在整个研发流程中被发现的越早,修改的代价就越低

单元测试,对单个的软件单元或者一组相关的软件单元所进行的测试,是代码级的测试。

Unit:函数,源代码文件,类

把测试比作是清洗一台机器:

系统测试就是清除机器外面的尘土。 集成测试就是保证机器各个部件的接头处干净。 单元测试就是清洗各个零件的内部。

应该尽早地进行软件单元测试。 应该保证单元测试的可重复性。 尽可能地采用测试自动化的手段来支持单元测试活动。

1.2 单元测试的目标和要求

目标: 单元模块被正确编码

信息能否正确地流入和流出单元; 在单元工作过程中,其内部数据能否保持其完整性,包括内部数据的形式、内容及相互关系不发生错误,也包括全局变量在单元中的处理和影响。 在为限制数据加工而设置的边界处,能否正确工作。 单元的运行能否做到满足特定的逻辑覆盖。 单元中发生了错误,其中的出错处理措施是否有效。 指针是否被错误引用、资源是否及时被释放。 有没有安全隐患?是否使用了不恰当的字符串处理函数等。

单元测试的一系列活动:

    建立单元测试环境,包括在集成开发环境中安装和设置单元测试工具(插件); 测试脚本(测试代码)的开发和调试; 测试执行及其结果分析。

目标:确保模块被正确地编码。 依据:详细设计描述。 过程:经过设计、脚本开发、执行、调试和分析结果等环节。 执行者:由程序开发人员和测试人员共同完成。 采用那些测试方法:包括代码控制流和数据流分析方法,并结合参数输入域的测试方法。 测试脚本的管理:可以按照产品代码管理的方法进行类似的配置(并入代码库),包括代码评审、版本分支、变更控制等。 如何进行评估:通过代码覆盖率分析工具来分析测试的代码覆盖率、分支或条件的覆盖率。

软件单元功能与设计需求一致。 软件单元接口与设计需求一致。 能够正确处理输入和运行中的错误。 在单元测试中发现的错误已经得到修改并且通过了测试。 达成了相关的覆盖率的要求。 完成软件单元测试报告。

任务1:模块独立执行通路测试

检查每一条独立执行路径的测试。保证每条语句被至少执行一次。

误解或用错了算符优先级。 混合类型运算。 变量初始化错误、赋值错误。 错误计算或精度不够。 表达式符号错等。

任务2:模块局部数据结构测试

检查局部数据结构完整性

不适合或不相容的类型说明。   变量无初值。   变量初始化或缺省值有错。  不正确的变量名或从来未被使用过。   出现上溢或下溢和地址异常。

输入的实际参数与形式参数是否一致。 (个数、属性、量纲) 调用其他模块的实际参数与被调模块的形参是否一致。 (个数、属性、量纲)  调用预定义函数时所用参数的个数、属性和次序是否正确   全程变量的定义在各模块是否一致。  外部输入、输出   ( 文件、缓冲区、错误处理 )

任务4:模块边界条件测试

检查临界数据处理的正确性

普通合法数据的处理。   普通非法数据的处理。  边界值内合法边界数据的处理。  边界值外非法边界数据的处理。   其它

任务5:模块的各条错误处理通路测试

预见、预设的各种出错处理是否正确有效。

输出的出错信息难以理解。   记录的错误与实际遇到的错误不相符。  在程序自定义的出错处理代码运行之前,系统已介入。   异常处理不当。   错误陈述中未提供足够的定位出错的信息。

静态测试技术:不运行被测试程序,对代码通过检查、阅读进行分析。

2.1 编码的标准和规范

标准:建立起来必须遵守的规则 规范:建议最佳做法,推荐更好方式

实施代码规范的原因:  可靠性  可读性和可维护性  可移植性

一次检查少于200~400行代码 努力达到一个合适的检查速度:300~500LOC/hour 有足够的时间、以适当的速度、仔细地检查,但不宜超过60~90分钟 在审查前,代码作者应该对代码进行注释 使用检查表(checklist)肯定能改进双方(作者和复审者)的结果 验证缺陷是否真正被修复

定义:采用讲解、讨论和模拟运行的方式进行的查找错误的活动。

引导小组成员在走查前通读设计和编码。  限时,避免跑题。   发现问题适当记录,避免现场修改。  检查要点是代码是否符合标准和规范,是否有逻辑错误。

定义:采用讲解、提问方式进行,一般有正式的计划、流程和结果。主要方法采用缺陷检查表。

 以会议形式,制定会议目标、流程和规则,结束后要编写报告。   按缺陷检查表逐项检查。   发现问题适当记录,避免现场修改。   发现重大缺陷,改正后会议需要重开。   检查要点是缺陷检查表,所以该表要根据项目不同不断积累完善。

应准备好需求描述文档、程序设计文档、程序的源代码清单、代码编码标准和代码缺陷检查表

项目组成员包括测试人员

限时、不要现场修改代码

限时、不要现场修改代码

代码标准规范,无逻辑错误

代码标准规范,无逻辑错误

定义:通常在审查会后进行,审查小组根据记录和报告进行评估。

充分审查了所规定的代码,并且全部编码准则被遵守。  审查中发现的错误已全部修改。

动态测试需要真正将程序运行起来,需要设计系列的测试用例保证测试的完整性和有效性。  

白盒测试  黑盒(灰盒)测试

运行单元程序有时需要基于被测单元的接口,开发相应的驱动模块和桩模块。

 驱动模块(drive):对底层 或子层模块进行测试所编写的 调用这些模块的程序。  桩模块(stub):对顶层或 上层模块进行测试时所编写的 替代下层模块的程序。

单元测试模型的设计。 测试项目的设计。

(1)单元测试模型设计

构造最小运行调度系统,即驱动模块,用于模拟被测模块的上一级模块。 模拟实现单元接口,即单元函数需调用的其他函数接口,即桩模块。 模拟生成测试数据或状态,为单元运行准备动态环境。 对测试过程的支持,对测试结果的保留,对测试覆盖率的记录等。

单元测试环境的示意图如下:

测试项目是测试用例的一个总则,主要是根据测试需求设计测试点,不包含具体实践的用例。 在测试项目的设计中,主要从功能覆盖和代码覆盖两个角度进行考虑。

               功能覆盖属黑盒的范畴,用来指出测试用例是否已经覆盖了程序应该提供的功能。逻辑覆盖率是考核单元测试质量的一个关键指标。

覆盖率指标:核心代码覆盖率达到100%,共享资源库的代码覆盖率达到100%,非核心代码覆盖率达到90%。

调试与测试的对象及采用的方法有很大程度上的相似,调试还用到断点控制等排错方法,但其目的却完全不同。测试是为了找出软件中存在的缺陷,而调试是为了解决存在的缺陷。  

软件单元功能与设计需求一致。   软件单元接口与设计需求一致。  能够正确处理输入和运行中的错误。   在单元测试中发现的错误已经得到修改并且通过了测试。   达到了相关的覆盖率的要求。   完成软件单元测试报告

在详细设计阶段完成单元测试计划。 建立单元测试环境,完成测试设计和开发。 执行单元测试用例,并且详细记录测试结果。 判定测试用例是否通过。 提交《单元测试报告》。

    《软件需求规格说明书》、《软件详细设计说明书》 -----> 《单元测试计划》 《单元测试计划》、《软件详细设计说明书》-----> 《单元测试用例》 《单元测试用例》文档及《软件需求规格说明书》、《软件详细设计说明书》-----> 《缺陷跟踪报告》/《缺陷检查表》   

7、系统集成的模式与方法

集成测试又称“组装测试”、“联合测试”。集成测试遵循特定的策略和步骤将已经通过单元测试的各个软件单元(或模块)逐步组合在一起进行测试,以期望通过测试发现各软件单元接口之间存在的问题。

理论上凡是两个单元(如函数单元)的组合测试都可以叫做集成测试。实际操作中,通常集成测试的对象为模块级的集成和子系统间的集成,其中子系统集成测试称为组件测试。

在把各个模块连接起来的时候,穿越模块接口的数据是否会丢失; 各个子功能组合起来,能否达到预期要求的总体功能; 一个模块的功能是否会对另一个模块的功能产生不利的影响; 全局数据结构是否有问题 单个模块的误差积累起来,是否会放大,从而达到不可接受的程度。   共享资源访问的测试  (   要想发现并排除在模块连接中可能发生的上述问题,就需要进行

集成测试有以下不可替代的特点:

单元测试具有不彻底性,对于模块间接口信息内容的正确性、相互调用关系是否符合设计无能为力。只能靠集成测试来进行保障。 同系统测试相比,由于集成测试用例是从程序结构出发的,目的性、针对性更强,测试项发现问题的效率更高,定位问题的效率也较高; 定位问题较快,发现问题后比较容易定位,所以能够有效地加快进度,减少隐患。

在开始体系结构设计的时候开始制定测试方案; 在进入详细设计之前完成集成测试方案; 在进入系统测试之前结束集成测试。

集成测试可以在开发部进行,也可以由独立的测试部执行。 开发部尽量进行集成测试,测试部有选择地进行集成测试。

集成测试是产品研发中的重要工作,需要为其分配足够的资源和时间。 集成测试需要经过严密的计划,并严格按计划执行。 应采取增量式的分步集成方式,逐步进行软件部件的集成和测试。 应重视测试自动化技术的引入与应用,不断提高集成测试效率。 应该注意测试用例的积累和管理,方便进行回归并进行测试用例补充。

集成功能测试 接口测试 全局数据结构测试 资源测试 任务优先级冲突测试 性能和稳定性测试

集成测试、单元测试与系统测试的差别

消除局部模块的逻辑和功能上的错误和缺陷

模块逻辑设计,模块外部说明

模块间的集成和调用关系

找出与软件设计相关的程序结构,模块调用关系,模块间接口方面的问题

结合使用白盒与黑和测试方法,采用较多黑盒方法构造测试用例 

整个系统,包括系统中的硬件等

对整个系统进行一系列的整体、有效性测试

系统结构设计,目标说明书,需求说明书等

由以上可以看出,整个软件系统的测试过程是:先对各个软件模块进行单元测试,然后把经过单元测试的各个模块组装起来进行集成测试,最后把经过集成测试的子系统合成软件版本,对照需求规格,在实际环境下,进行系统功能验证。 

7.1 集成测试前的准备

人员安排 、测试计划、测试内容 、集成模式、测试方法

7.2 集成测试的模式

渐增式测试模式与非渐增式测试模式:

非渐增式测试模式:先分别测试每个模块,再把所有模块按设计要求放在一起结合成所要的程序,如大棒模式。 渐增式测试模式:把下一个要测试的模块同已经测试好的模块结合起来进行测试,测试完以后再把下一个应该测试的模块结合进来测试。

非渐增式测试模式优缺点:工作量较小;发现模块间接口错误较晚;发现错误较难诊断,可以并行测试。 渐增式测试模式优缺点:要编写的软件较多,工作量较大;发现模块间接口错误较早;测试执行更彻底;需要较多的机器时间。

采用大棒集成方法,先是对每一个子模块进行测试(单元测试阶段),然后将所有模块一次性的全部集成起来进行集成测试 。

因为所有的模块一次集成的,所以很难确定出错的真正位置、所在的模块、错误的原因。这种方法并不推荐在任何系统中使用,适合在规模较小的应用系统中使用。  

 非增量式集成测试实例

评述:模块d1、d2、d3、d4、d5是对各个模块做单元测试时建立的驱动模块,s1、s2、s3、s4、s5是为单元测试而建立的桩模块。这种一次性集成方式将所测模块连接起来进行测试,但是一次试运行成功地可能性并不大。其结果发现有错误,但茫然找不到原因,差错和改错都会遇到困难。    

适应于一个维护型或被测试系统较小的项目。 

非增量式策略——优缺点:

优点: ①方法简单 ②允许多测试人员同时并行工作,人力物力资源利用率较高 缺点: ①必须为每个模块准备相应的驱动模块和桩模块,测试成本较高 ②一旦集成后包含多种错误,难以纠正。

7.4 自顶向下和自底向上集成方法

驱动程序/驱动模块(driver),用以模拟被测模块的上级模块。驱动模块在集成测试中接受测试数据,把相关的数据传送给被测模块,启动被测模块,并打印出相应的结果。

桩程序/桩模块(stub),也有人称为存根程序,用以模拟被测模块工作过程中所调用的模块。桩模块由被测模块调用,它们一般只进行很少的数据处理,例如打印入口和返回,以便于检验被测模块与其下级模块的接口。

自顶向下法,从主控模块(主程序)开始,沿着软件的控制层次向下移动,逐渐把各个模块结合起来。

组装过程可以采用深度优先策略和宽度优先策略

深度优先:从最顶层单元开始,持续向下到下一层,选择一个分支,自顶而下一个一个的集成这条分支上的所有单元,直到最底层,然后转向另一个分支,重复这样的集成操作直到所有的单元都集成进来。 广度优先:从最顶层单元开始,持续向下到下一层, 一个个完成下一层上所有单元集成后,再转向下面一层,重复这样的集成操作直到所有的单元都集成进来。

自顶向下增量测试 

自顶向下集成测试的整个过程由3个步骤完成:  

    主控模块作为测试驱动器。    根据集成的方式(深度或广度),下层的桩模块一次一次地被替换为真正的模块。 在每个模块被集成时,都必须进行单元测试。     重复第2步,直到整个系统被测试完成。  

能够在测试阶段的早期实现并验证系统的主要功能;

能在早期发现上层模块中的接口错误。 

需要桩程序,要使桩模块能够模拟实际子模块的功能十分困难;

底层验证被推迟; 同时涉及复杂算法,真正输入/输出的模块一般在底层,

他们是最容易出问题的模块,到测试和集成的后期才遇到这些模块,一旦发现问题导致过多的回归测试。

自顶向下增量式集成适用范围:

产品控制结构比较清晰和稳定; 高层接口变化较小; 底层接口未定义或经常可能被修改; 产口控制组件具有较大的技术风险,需要尽早被验证; 希望尽早能看到产品的系统功能行为。

(1)对如下结构采用自顶向下深度优先策略进行测试

(2)一个按广度优先测试进行集成测试

    首先,对顶层的模块A进行单元测试,这时需配以被调用子模块s1、s2、s3,以模拟被它调用的模块B、C和D。 其后,把模块B、C和D与顶层模块A连接起来,再对模块B和D配以被调用模拟子模块s4和s5以模拟对模块E和F的调用。 最后,去掉被调用模拟子模块s4和s5,把模块E和F集成后再对软件完整的结构进行测试。

自底向上法,测试从原子模块(软件结构最底层的模块)开始集成以进行测试。自底向上进行集成和测试时,需要为所测模块或子系统编制相应的驱动模块。

自底向上增量式集成测试步骤:

    起始于模块依赖关系树的底层叶子模块,也可以把两个或多个叶子模块合并到一起进行测试 使用驱动模块对步骤1选定的模块(或模块组)进行测试 用实际模块代替驱动模块,与它已测试的直属子模块组装成一个更大的模块进行测试 重复上面的行为,直到系统最顶层模块被加入到已测系统中

一个自底向上增量式集成测试的典型例子

    首先,(a)、(b)、(c)表示树状结构图中处于最下层的叶结点模块E、C和F,由于它们不再调用其他模块,对它们进行单元测试时,只需配以驱动模块d1、d2和d3,用来模拟B、A和D对它们的调用。 完成这3个单元测试后,再按(d)和(e)的形式,分别将模块B和E及模块D和F连接起来,再配以驱动模块d4和d5实施部分集成测试。 最后按图(f)的形式完成整体的集成测试。

与自顶向下法刚好相反。

不需要桩程序; 同时由于涉及到复杂算法和真正输入/输出的模块最先得到集成和测试,可以把最容易出问题的部分在早期解决; 自底向上增值的方式可以实施多个模块的并行测试,提高测试效率。

“程序一直未能作为一个实体存在,直到最后一个模块加上去后才形成一个实体”。也就是说,在自底向上集成和测试的过程中,对主要的控制直到最后才接触到。 驱动的开发工作量大;

自底向上增量式集成适用范围:

适应于底层接口比较稳定; 高层接口变化比较频繁; 底层组件较早被完成。

混合法:对软件结构中较上层,使用的是“自顶向下”法;对软件结构中较下层,使用的是“自底向上”法,两者相结合。

混合式集成 把系统划分成三层,中间一层为目标层,目标层之上采用自顶向下集成,之下采用自底向上集成

首先对目标层之上一层使用自顶向下集成,因此测试A,使用桩代替B,C,D 其次对目标层之下一层使用自底向上集成,因此测试E,F,使用驱动代替B,D 其三,把目标层下面一层与目标层集成,因此测试(B,E),(D,F),使用驱动代替A 最后,把三层集成到一起,因此测试(A,B,C,D,E,F)

优点: 集合了自顶向下和自底向上两种策略的优点

缺点: 中间层测试不充分,在真正集成之前每一个独立的模块没有完全测试过。

适用范围: 适应于大部分软件开发项目

改进的三明治集成方法,不仅自两头向中间集成,而且保证每个模块得到单独的测试,使测试进行得比较彻底 。

几种集成方法性能的比较

通常系统集成都会采用持续集成的策略,软件开发中各个模块不是同时完成,根据进度将完成的模块尽可能早的进行集成,有助于尽早发现Bug,避免集成中大量Bug涌现。   而且容易定位Bug、修正Bug,最终提高软件开发的质量与效率。

集成测试主要由系统部的系统设计人员、软件评测部完成,开发人员也参与集成测试。集成测试相对来说是挺复杂的,而且对于不同的技术、平台和应用差异也比较大,更多是和开发环境融合在一起。集成测试所确定的测试的内容,主要来源于设计模型。

 (1)集成测试计划

输入 :需求规格说明书、概要设计文档、 产品开发计划路标

确定被测试对象和测试范围 评估集成测试被测试对象的数量及难度,即工作量 确定角色分工和划分工作任务 标识出测试各阶段的时间、任务、约束等条件 考虑一定的风险分析及应急计划 考虑和准备集成测试需要的测试工具、测试仪器、环境等资源 考虑外部技术支援的力度和深度,以及相关培训安排 定义测试完成标准

(2)集成测试分析和设计

集成测试分析和设计的主要目的是制定测试大纲(测试方案)。集成测试大纲规定了今后的集成测试内容、测试方法以及可测性接口,以后所有集成测试均在该大纲的框架下进行,所以,制定一份完善的集成测试大纲非常重要。

输入:需求规格说明书 概要设计 集成测试计划

输出:集成测试设计方案

被测对象结构分析 集成测试模块分析 集成测试接口分析 集成测试策略分析 集成测试工具分析 集成测试环境分析 集成测试工作量估计和安排

输入:需求规格说明书 概要设计 集成测试计划 集成测试设计

输出:集成测试用例 集成测试规程 集成测试代码、集成测试脚本、集成测试工具(如果有)

集成测试用例设计 集成测试规程设计 集成测试代码设计(如果需要) 集成测试脚本(如果需要) 集成测试工具(如果需要)

需求规格说明书 概要设计 集成测试计划 集成测试设计 集成测试用例 集成测试规程 集成测试代码(如果有) 集成测试脚本(如果有) 集成测试工具(如果有) 详细设计 代码 单元测试报告

执行集成测试用例 回归集成测试用例 撰写集成测试报告

这篇文章的主旨是在正式进行单元测试之前帮助大家厘清一些概念。了解什么是单元测试,可以做什么,有哪些指导原则。做了又有什么好处,它又存在什么样的局限性。最后重点讲了现在做单元测试的难点。事实上这是任何单元测试都会面临的一个问题。在这里分享我的观点,与大家共勉!
  UT测的是方法,检验的是一个类对外界的。因此,大多数情况下,我们测的应该是公共方法,除非不得已才对私有方法进行测试。 方法是程序设计的最小单位。UT的局限也体现在这里,它并没有针对类之间的交互做检验。所以,不能指望单元测试做完了,就没有问题了。在这个方面的欠缺,我们可以通过自动化的功能/组件测试来完成。这也是开发者测试的一部分。
  1. 尽早的发现问题 说白了,就是不要让问题流出去。让我们的缺陷率降低,把我们的产品做的漂亮。另一方面,一些细类度的问题在这里也确实更容易发现,同时也为进行更大粒度的测试做好集成准备。
  2. 编织一层保护网
  给新的代码建立有效的保护。 保证对代码每一份改动,都不会对现有系统造成伤害。避免了引入问题。
  3.写出优雅的代码
  编写单元测试的过程,实质是使用我们自己代码的过程。我们成了第一个真正意义上的体验者。在这个过程中,我们为了使代码易用会进行不断的重构。最终的交付代码必然会更优雅。
  4. 建立程序员的自信
  我们习惯于两眼一抹黑,不管三七二十一就把代码写完了。Code阶段结束,然后不断的调试,修修补补跑起来就过了TR4。没人敢说,他代码一写完了,就能跑起来。这种做法是很没人性的,系统搞挂几次后就心里发虚,一点底气都没有。但是,这是我们的职业,我们为着自己的荣耀而战。在任何时候,都需要信心满盈。
  三、UT的基本原则
  1.一个类、一个方法、一条路径 我们一次只测一个类的一个方法。刚开始做单元测试的时候,很多人会自然而然的做成了功能测试。因为,前一部分执行的结果恰好为后一部分准备好了输入。而另一方面,连续的执行过程组成了一个明确的场景,让具体的功能变得完整可见,这正是我们期待的,让我们变得有信心。那为什么不顺其自然呢?
  1)、单元测试要保证一定的微粒度。从单元测试到功能测试,这之间的粒度会越来越大,越往后,我们会越少的关注细节。如果直接跳跃到功能测试上,会让我们遗漏掉一些问题,在以后的粗粒度测试中,它们会转变为很难重现或者不可重现的致命问题。
  2)、上述场景之所以会出现,是因为先写代码后写测试导致的。相当于代码已经集成,具备了做功能测试的一定条件。这个时候让再走回头路做单元测试,当然不如直接就做功能测试来的顺当。所以,应该一个测试、一个方法,一个方法一个测试,这样不断的一步一步的循环迭代集成来的好。
  另一方面,为了将一个方法的多个不同的执行路径分开,我们必须保证一次只测一个方法的一个路径。这样,前置条件和后置条件就会很明确,容易准备测试环境。
  2.重构以便于测试
  面对着一个方法,你感到一筹莫展。并不是你的错,而是因为这个方法很烂。测一个方法就是在使用这个方法,你自己都这样无奈,将来真正使用的人岂不是要骂娘?雁过留声,人过留名。这个时候,重构一下很值得。
  3.保证测试方法简洁
  如果连测试方法都很复杂,难道我们还要再写测试用例来保证它的正确执行不成?这样岂不是麻烦大了!所以,测试方法一定要写的尽可能的简单,写到你认为白痴都能看懂的程度。
  四、如何才能做UT
  1.代码要首先可测,然后才能测。 首先要遵守契约式设计。类的每一个方法都应该对外承担了一份契约,有明确的前置条件和后置条件。 当你对这个方法进行测试之前必须清楚明白这两个条件。一个有效的方法一定是做了什么事的。一定会产生一定的影响,我们可以通过对外围环境的改变来检测方法产生的作用是否如预期(例如,获取某一对象的属性进行检测)。
  其次是,低Ce和单一责任原则。一个方法对外的依赖应该单一,不应该取决于很多的外部环境。因为不同的外部环境越多,组合项就越多,要测的先决条件就越多。而一个方法对外部环境的影响太多,则意味着职责不单一,对于输出越难测。
  曾经听有人讲到,这些道理,你懂了就懂,不懂就不懂,说了没用。但我认为,如果你还以为这些只是大道理,如果你还想对它有点切身的感受,做单元测试是一个很好的途径。
  2.信任你该信任的。
  对于已经稳定的部分,类似于第三方包,平台部分,其至是遗留系统中已经证明是可靠的部分,都可以信任。这些是我们用例代码依赖的部分,是我们用来检验其它待测部分的基石。如果什么都要测,就会变成什么都测不了。
  3. 单元测试要尽量少的增加开发人员的负担。
  一方面,我们实在被问题单压抑的太久了。所以,从全局上来看待这个问题,如果可以确实的减少后期的维护压力,对我们自身而言当然是有益的。所谓增加的负担,不过是提早了结了一些痛苦。
  另一方面,单元测试必须自动化 ,必须简单,傻瓜化。这是我们要努力的目标。
  4.将调试的时间用来写单元测试
  没有做过自动化单元测试的人永远也不能体会其给程序员带来的自信和好处。如果你还在调试,考试大提示不如顺手加个测试。以后,保证同样的问题不会从你的眼皮下溜走。
  5. 现在的单元测试难在哪里?
  难以打桩。因为我们对其它模块的关联是这样的。
  这就是麻烦的所在,关联太多。如果我们要测,我们就要打桩。
  1. 望而生畏,太多。
  2. 无法下手,都是直接对象依赖,而不是接口依赖。
  所以,你让我来测这样的代码,我是不会干的。
  因为,我希望的是这样的:
  但是,我们现在的代码欠债太多了。没有条件和能力再回去对这些代码进行单元测试。而且,这些功能经过这么多年的维护,大多已稳定。做的性价比也不高,不够实惠。所以,不必要做。
  但在新功能开发过程中,这些老代码依旧会如恶梦一样纠缠着我们。让写单元测试过程中常常面临着举步维艰的境地。我们不得不在让代码变得可测与对代码的侵入性测试之间进行抉择。

我要回帖

更多关于 一年级数学第八单元测试题 的文章

 

随机推荐