精华内容
下载资源
问答
  • unittest模块是Python自带的一个单元测试模块,我们可以用来做单元测试。unittest模块包含了如下个子模块: 测试用例:TestCase 测试集:TestSuite 加载用例:TestLoader 执行用例:TextTestRunner  首先编写...
  • 关于Android单元测试几种框架

    千次阅读 2015-06-30 15:57:19
    现在,已经有大量的Android自动化测试架构或工具可供我们使用,其中包括:Activity Instrumentation, MonkeyRunner, Robotium, 以及Robolectric。另外LessPainful也提供服务来进行真实设备上的自动化测试。  ...

     现在,已经有大量的Android自动化测试架构或工具可供我们使用,其中包括:Activity Instrumentation, MonkeyRunner, Robotium, 以及Robolectric。另外LessPainful也提供服务来进行真实设备上的自动化测试。

      Android自身提供了对instrumentation测试的基本支持,其中之一就是位于android.test包内的 ActivityInstrumentationTestCase2类,它扩展了JUnit的TestCase类来提供Android activities的功能测试。在应用测试中,每一个activity首先会被Instrumentation初始化,然后再加载到Android模拟 器或设备的Dalvik虚拟机中来执行。

      Android SDK自带一个测试工具MonkeyRunner,它提供的API和执行环境可以运行Python语言编写的测试代码。它提供API来连接设备,安装/卸 载应用,运行应用,截屏,比对图片来判断特定命令执行后的屏幕是否包含预期信息,以及运行对应用的测试。MonkeyRunner使用 ActivityInstrumentationTestCase2, ProviderTestCase,ServiceTestCasek, SingleLaunchActivityTestCase及其他类来定义测试用例,并使用InstrumentationTestRunner类来运行 测试。

      Robotium是另一种通过InstrumentationTestRunner来完成Android交互式测试的架构,它横跨多个 activities,支持功能测试,系统测试和接收测试。Robotium支持Activities、Dialogs、Toasts、Menus、 Context Menus甚至Honeycomb,并且它可以同Maven和Ant集成来完成持续集成测试。Robotium被称之为针对Android应用的又一个 Selenium。

      Robolectric另辟蹊径,它并不依赖于Android提供的测试功能,它使用了shadow objects并且运行测试于普通的工作站/服务器JVM,不像模拟器或设备需要dexing(Android dex编译器将类文件编译成Android设备上的Dalvik VM使用的格式),打包,部署和运行的过程,大大减少了测试执行的时间。Pivotal实验室声称使用Robolectric可以在28秒内运行1047 个测试。

      LessPainful将Android测试又推进了一步,它提供了一个多设备平台自动化测试的服务。用户上传应用(*.apk)和用 Cucumber(一种业务相关的DSL)编写的测试文件,选择测试运行需要的设备配置,最后测试将自动执行并生成测试报告。它支持的设备包括 Garmin Asus,几款HTC,LG,Samsung Galaxy,Sony Xperia和Motorola Motodefy。


    有进一步兴趣可以百度一下相应的单元测试框架进行深入的了解


    展开全文
  • 单元测试与集成测试

    万次阅读 多人点赞 2019-09-17 08:25:00
    按测试策略和过程,软件测试分为单元测试、集成测试、确认测试和系统测试。 按软件系统工程,测试是软件质量保证的最后的一关。 高质量的程序取决于以下个方面: 高质量的设计 规范的编码 有效的测试 开发部...

    软件测试分类

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

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

    1. 高质量的设计
    2. 规范的编码
    3. 有效的测试

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

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

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

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

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

    软件缺陷的修复费用

    单元测试(why)

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

    单元测试(who)

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

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

    测试的4个阶段:单元测试----->集成测试----->系统测试----->验收测试

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

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

    时机:     单元测试和编码是同步进行,但在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. 测试脚本(测试代码)的开发和调试;
    3. 测试执行及其结果分析。

    单元测试的主要内容:

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

    单元测试的一般准则:

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

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

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

    Checklist:

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

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

    检查局部数据结构完整性

    Checklist:  

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

    任务3:模块接口测试

    检查模块接口是否正确

    checklist:  

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

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

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

    Checklist:  

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

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

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

    Checklist:  

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

    2、 静态测试

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

    三步曲:  走查(Walk Through)  审查(Inspection)  评审(Review)

    2.1 编码的标准和规范

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

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

    2.2 代码评审

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

    1.代码走查(Walk Through)

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

    注意:  

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

    2.正式会议审查(Inspection)

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

    注意:

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

    走查与审查的比较

     

    走   查

    审   查

    准备

    通读设计和编码

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

    形式

    非正式会议

    正式会议

    参加人员

    开发人员为主

    项目组成员包括测试人员

    主要技术方法

    缺陷检查表

    注意事项

    限时、不要现场修改代码

    限时、不要现场修改代码

    生成文档

    会议记录

    静态分析错误报告

    目标

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

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

    3.评审(Review)

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

    注意:  

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

    3 、动态测试

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

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

    驱动程序和桩程序

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

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

    单元测试设计

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

    (1)单元测试模型设计

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

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

    (2)测试项目设计

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

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

                    代码覆盖也称逻辑覆盖,包括语句覆盖、分支覆盖、路径覆盖,是一种常用的白盒测试方法。

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

    4、调试与评估

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

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

    5、单元测试的管理

    过程:

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

    单元测试的文档

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

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

    集成测试定义

    定义

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

    集成测试对象

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

    集成测试目的与意义

    考虑以下问题:

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

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

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

    集成测试(when)

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

    集成测试(who)

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

    集成测试原则

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

    集成测试内容

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

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

    测试类型

    对象

    目的

    测试依据

    测试方法

    单元测试

    模块内部的程序错误

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

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

    大量采用白盒测试方法

    集成测试

    模块间的集成和调用关系

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

    程序结构设计

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

    系统测试

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

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

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

    黑盒测试

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

    7.1 集成测试前的准备

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

    7.2 集成测试的模式

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

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

    各自的优缺点

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

    7.3 大棒集成方法(Big-bang Integration)

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

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

     非增量式集成测试实例

     

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

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

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

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

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

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

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

    1.自顶向下法(Top-down Integration) 

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

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

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

     

    自顶向下增量测试 

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

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

    深度优先组装方式:

    广度优先组装方式:

    自顶向下法——优缺点

    优点:

    不需要测试驱动程序;

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

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

    缺点:

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

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

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

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

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

    练习:

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

     

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

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

    2.自底向上法(Bottom-up Integration)

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

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

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

    自底向上增量式测试

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

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

    自底向上法——优缺点

    与自顶向下法刚好相反。

    优点:

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

    缺点:

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

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

    适用范围:

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

    3.混合策略(Modified Top-down Integration)

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

    7.5 三明治集成方法(Sandwich Integration)

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

    三明治集成策略

     集成步骤

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

    优缺点分析    

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

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

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

    改善的三明治集成方法

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

    集成策略框图

    几种集成方法性能的比较

     

    自底向上

    自顶向下

    混合策略

    大棒

    三明治

    改进三明治

    集成

    基本程序能工作时间

    需要驱动程序

    需要桩程序

    工作并行性

    特殊路径测试

    容易

    容易

    容易

    中等

    容易

    计划与控制

    容易

    容易

    集成策略选择

    7.6  持续集成

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

    7.7 集成测试流程

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

    集成测试流程

     (1)集成测试计划

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

    输出:集成测试计划

    活动步骤

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

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

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

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

    输出:集成测试设计方案

    活动步骤

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

    (3)实施阶段

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

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

    活动步骤

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

    (4)执行阶段

    输入

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

    输出

    • 集成测试报告

    活动步骤

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

    相应过程的测试文档

     

    展开全文
  • 单元测试

    千次阅读 2017-06-06 11:40:08
    单元测试单测定义单元测试(Unit Testing)又称为模块测试, 是针对程序模块(软件设计的最小单位)来进行正确性检验的测试工作,程序模块在面向对象编程中一般是指方法。单元测试一般由开发人员来编写,用来保证程序...

    单元测试

    单测定义

    单元测试(Unit Testing)又称为模块测试, 是针对程序模块(软件设计的最小单位)来进行正确性检验的测试工作,程序模块在面向对象编程中一般是指方法。

    单元测试一般由开发人员来编写,用来保证程序及功能的正确性。

    为什么需要单测

    编写单元测试代码并不是一件容易的事情,那为什么还需要去话费时间和精力来编写单元测试呢?

    • 减少Bug:如今的项目大多都是多人分模块协同开发,当各个模块集成时再去发现问题,定位和沟通成本是非常高的,通过单元测试来保证各个模块的正确性,可以尽早的发现问题,而不时等到集成时再发现问题。
    • 放心重构:如今持续型的项目越来越多,代码不断的在变化和重构,通过单元测试,开发可以放心的修改重构代码,减少改代码时心理负担,提高重构的成功率。
    • 改进设计:越是良好设计的代码,一般越容易编写单元测试,多个小的方法的单测一般比大方法(成百上千行代码)的单测代码要简单、要稳定,一个依赖接口的类一般比依赖具体实现的类容易测试,所以在编写单测的过程中,如果发现单测代码非常难写,一般表明被测试的代码包含了太多的依赖或职责,需要反思代码的合理性,进而推进代码设计的优化,形成正向循环。

    就个人而言,感受最深的就是,有了单测后重构代码起来心里压力小多了,其次是通过单测减少了很多低级错误。

    单测带来的一些问题

    单测在解决了一些问题的同时也容易产生一些问题

    • 学习成本:单测框架的学习需要一定的成本
    • 开发成本:项目初期,往往最重要的是快速上线,时间非常紧张,这时容易出现单测代码难以编写,代码经常变化导致单测代码也需要更着同步变化,一定程度上会拖慢项目的进度,可以在项目中后期再补上重要部分的单测代码
    • 推广实行:项目中推广单测有一定成本,单纯为了覆盖率的单测是没什么意义的,所以在项目中推广单测时,要考虑到项目成员是否接受单测,能否编写出较好的单测代码,否则单测容易流于形式,达不到理想的效果。

    个人经验,在项目中要施行单测,需要做到以下几点:

    • 说服领导,给出合理的考核指标(如单测覆盖率等要求,需要结合现状给出合理的指标)
    • 提供单测指标统计的大盘,显示项目单测指标,督促大家完成指标
    • 对项目结构配置等进行调整,提供单测工具类,基础类,让单测易编写,能运行,速度快
    • 对项目组成员进行单测编写方法分享,使成员熟悉单测技术
    • 提供单测代码示例,示例要够复杂,方便成员参考
    • 定时检查成员单测代码,提供改进意见,防止流于形式

    单测工具介绍

    JUnit

    Java用的最多的单测框架,使用非常简单,主流IDE基本都集成了JUnit,具体用法就不介绍了,可以花十分钟看看官方文档http://junit.org/junit4/

    Runner

    JUnit的Runner是指继承了org.junit.runner.Runner的类,是用来真正执行单测方法的类,JUnit有提供默认的Runner,如org.junit.runners.JUnit4,也可以通过@RunWith注解来指定自定义的Runner,如@RunWith(SpringRunner.class)

    Runner的介绍可以参考这篇文章:
    http://www.mscharhag.com/java/understanding-junits-runner-architecture

    通过自定义Runner,可以简化单测的开发,例如,在Spring没有提供Runner时,为Spring应用编写单测,需要自己初始化Spring上下文,然后从上下文中获取要测试的Bean,使用起来比较麻烦。

    对于自定义Runner来说,一般会继承JUnit的org.junit.runners.BlockJUnit4ClassRunner,BlockJUnit4ClassRunner主要提供了下面的功能:

    • 反射创建单测类实例
    • 找出单测方法(被@Test注解的方法)
    • 其它JUnit注解支持,如@After、@Before等等
    • 反射执行单测方法

    SpringRunner通过继承BlockJUnit4ClassRunner,在其基础上提供了自动初始化Spring上下文,单测类中的@Resource等注解的处理,等等一系列方便编写Spring单测的功能。

    如果我们想实现在单测方法前后执行一些逻辑,我们除了可以使用@Before注解,还可以通过实现自定Runner来实现:

    import org.junit.runners.BlockJUnit4ClassRunner;
    import org.junit.runners.model.FrameworkMethod;
    import org.junit.runners.model.InitializationError;
    import org.junit.runners.model.Statement;
    
    public class TestRunner extends BlockJUnit4ClassRunner {
    
        public TestRunner(Class<?> klass) throws InitializationError {
            super(klass);
        }
    
        @Override
        protected Statement methodBlock(FrameworkMethod method) {
            //FrameworkMethod 是单测方法的包装类
    
            //获取父类处理的结果,以便使用JUnit提供的注解的功能
            Statement block = super.methodBlock(method);
    
            //自定义的逻辑
            Statement newBlock = new Statement() {
                @Override
                public void evaluate() throws Throwable {
                    //这里可以在单测方法执行前做一些自定义逻辑
                    System.out.println("TestRunner before : " + method.getName());
    
                    block.evaluate();//单测方法执行,包含@Before等注解处理逻辑
    
                    //这里可以在单测方法执行后做一些自定义逻辑
                    System.out.println("TestRunner after : " + method.getName());
                }
            };
    
            return newBlock;
        }
    
    }
    import org.junit.Test;
    import org.junit.runner.RunWith;
    
    @RunWith(TestRunner.class)
    public class BTestClass {
    
        @Test
        public void test(){
            System.out.println("test b");
        }
    
    }
    
    //运行输出
    //TestRunner before : test
    //test b
    //TestRunner after : test
    

    在JUnit内部,其实就是用类似的方式来实现@Before、@After等等注解功能的,通过层层的包装Statement类,来实现功能的扩展。

    Rule

    Rule是JUnit4.7新增加的功能,是JUnit的另一种扩展机制,可以扩展单测方法的执行。上面TestRunner的功能也可以通过Rule机制来实现:

    import org.junit.rules.TestRule;
    import org.junit.runner.Description;
    import org.junit.runners.model.Statement;
    
    public class EchoRule implements TestRule {
    
        @Override
        public Statement apply(Statement base, Description description) {
            Statement newBlock = new Statement() {
                @Override
                public void evaluate() throws Throwable {
                    //这里可以在单测方法执行前做一些自定义逻辑
                    System.out.println("EchoRule before : " + description.getMethodName());
    
                    base.evaluate();//单测方法执行,包含@Before等注解处理逻辑
    
                    //这里可以在单测方法执行后做一些自定义逻辑
                    System.out.println("EchoRule after : " + description.getMethodName());
                }
            };
            return newBlock;
        }
    
    }
    import org.junit.Rule;
    import org.junit.Test;
    
    public class BTestClass {
    
        @Rule
        public EchoRule rule = new EchoRule();//必需要是public的
    
        @Test
        public void test() {
            System.out.println("test b");
        }
    
    }
    
    //输出
    //EchoRule before : test
    //test b
    //EchoRule after : test

    可以看到Rule更多的是对单测方法执行前后的一些逻辑的扩展,@Rule注解的属性必需是public的实例属性,如果想在所有单测方法执行前后进行处理(类似@BeforeClass、@AfterClass逻辑),可以通过@ClassRule注解来做到,被@ClassRule的属性必需是static public的属性

    Rule机制相对Runner的好处在于,Runner只能指定一个,而一个单测类可以指定多个Rule,Spring也有Rule的实现,在即想使用其它框架的Runner又想使用Spring的单测扩展时,可以使用其它框架的Runner,然后使用Spring的Rule,来组合使用,如:

    import org.junit.ClassRule;
    import org.junit.Rule;
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.mockito.runners.MockitoJUnitRunner;
    import org.springframework.test.context.junit4.rules.SpringClassRule;
    import org.springframework.test.context.junit4.rules.SpringMethodRule;
    
    @RunWith(MockitoJUnitRunner.class)
    @ContextConfiguration(locations="classpath:spring-root.xml")
    public class BTestClass {
    
        @ClassRule
        public static final SpringClassRule SPRING_CLASS_RULE = new SpringClassRule();
    
        @Rule
        public final SpringMethodRule springMethodRule = new SpringMethodRule();
    
        @Test
        public void test() {
            System.out.println("test b");
        }
    
    }

    JUnit自带了一些方便使用的Rule实现,可以参考下面的文档
    https://github.com/junit-team/junit4/wiki/Rules

    Mock框架

    在真实项目中,往往需要依赖很多外部的接口,如HSF等接口,而我们在运行单测的时候RPC接口可能还未开发完成或者因为环境问题,无法访问,这时我们想要测试自己部分的逻辑,就需要使用到Mock框架,来屏蔽掉外部系统的影响。

    使用Mock通常会带来以下一些好处:

    • 隔绝其他模块出错引起本模块的测试错误
    • 隔绝其他模块的开发状态,只要定义好接口,不用管他们开发有没有完成
    • 一些速度较慢的操作,可以用Mock Object代替,使单测快速返回
    • 隔离环境对单测执行的影响,实现在没有外部服务时也能运行单测

    常见的Mock框架有EasyMock、Mocktio、JMockit、PowerMock等,个人只简单用过Mocktio和JMockit,就功能上,JMockit的功能更强,能Mock静态方法等,但是根据之前的使用来看,比较难以驾驭,因为JMockit使用的是Java5的Instrumentation机制,会在运行时修改字节码,导致碰到问题时比较难以调试,相对的网络资料也比较少,而Mocktio的使用比较简单明了,因此推荐使用Mocktio

    关于Mocktio的使用可以参考文档:
    [https://static.javadoc.io/org.mockito/mockito-core/2.7.22/org/mockito/Mockito.html
    https://juejin.im/entry/578f11aec4c971005e0caf82](https://static.javadoc.io/org.mockito/mockito-core/2.7.22/org/mockito/Mockito.html
    https://juejin.im/entry/578f11aec4c971005e0caf82)

    因为Mocktio是使用Cglib来创建代理的,所以对于被Mock的对象来说,要求和Cglib创建代理的要求一样,如不能是final类、不能代理private方法等等限制

    有时候可能需要mock void方法,可以使用下面的方式

    OssCache cache = Mockito.mock(OssCache.class);
    
    Mockito.doNothing().when(cache).putToKey("key", "val");
    Mockito.doThrow(new RuntimeException("exp")).when(cache).deleteObj("key");
    
    cache.putToKey("key", "val");
    try {
        cache.deleteObj("key");
        fail("mast throw exception");
    } catch (RuntimeException e) {
        assertTrue("exp".equals(e.getMessage()));
    }
    
    Mockito.verify(cache).putToKey("key", "val");
    Mockito.verify(cache).deleteObj("key");

    当Mockito的注解使用起来比较方便,具体注解的使用参见前面链接的文档,Mockito处理注解是通过MockitoAnnotations.initMocks(target)来处理的,而Mockito提供的Runner和Rule其实就是简单的在单测方法执行前执行该行代码,所以可以通过@RunWith(MockitoJUnitRunner.class)或@Rule public MockitoRule mockitoRule = MockitoJUnit.rule()方式来使用Mockito注解功能,当和Spring Test一起使用时,因为一般会使用Spring的Runner,所以可以通过Rule的方式来使用Mockito的注解功能

    关于Mockito的大概原理如下

    主要通过ThreadLocal将我们要mock的方法和对应的返回值关联起来

    内存数据库

    在项目中经常会使用到Mysql等数据库,但是在单测运行时,如果访问Mysql等外部服务器,会造成:

    • 单测运行慢
    • 单测运行依赖环境,在无法访问Mysql时,单测无法运行
    • 单测可能会运行的非常频繁,造成Mysql中非常多的垃圾数据
    • 单测依赖数据库中某些特定的数据,造成换个Mysql数据库时单测运行失败

    那么如何解决上面的问题,一种方式是Mock掉所有DAO的类,这种方式需要写非常多的Mock,单测写起来比较麻烦,且DAO层面问题无法测试到;另一种方式就是使用内存数据库,内存数据库兼容SQL,启动速度快,数据存放在内存中单测运行后自动丢弃,非常适合单测时使用

    常见的内存数据库有很多,但是鉴于单测场景,考虑到安装方便(直接Maven依赖),了解到的有HSQL、H2、Derby等,H2的官网上有个对比表http://www.h2database.com/html/main.html

    考虑到目前我们使用的是Mysql数据库,而H2有Mysql模式,对Mysql的语法支持的最好,所以建议使用H2数据库来作为单测数据库,但是H2并不支持所有的Mysql语法,还是有不少的Mysql语法或函数并不支持,对于建表语句而言,可以使用语法转换工具https://github.com/bgranvea/mysql2h2-converter

    Spring对嵌入式数据库支持的非常好,可以通过下面的配置来创建嵌入式数据库数据源,同时可以指定初始化表和数据库的脚本

    <jdbc:embedded-database id="dataSource" generate-name="true" type="H2">
        <jdbc:script location="classpath:/sql/test_schema.sql" />
        <jdbc:script location="classpath:/sql/test_init_data.sql" />
    </jdbc:embedded-database>

    具体使用可以参考Spring的文档https://docs.spring.io/spring/docs/current/spring-framework-reference/html/jdbc.html#jdbc-embedded-database-support

    除了H2,还可以使用MariaDB4j,MariaDB的Java包装版本(用Java代码安装MariaDB精简版然后启动,比较重)
    https://github.com/vorburger/MariaDB4j

    Spring Test介绍

    当应用使用了Spring时,编写单测时需要每次手动的初始化Spring上下文,这种方式不仅繁琐,而且不能复用Spring上下文,导致单测执行时间变长,为此,Spring提供了对单测的支持,也就是Spring Test模块

    Spring和JUnit的整合,提供了对应的Runner和Rule,我们平常使用的比较多的是Spring的Runner,即SpringJUnit4ClassRunner或者SpringRunner(Spring4.3),Spring的Runner会根据配置自动初始化Spring上下文,并在单测方法执行时对其进行依赖注入,避免手动的getBean操作,简单使用如下

    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration("classpath:spring-test-main.xml")
    public class Test {
    
        @Resource
        private SomeBean bean;
    
        @Test
        public void test(){
            String someVal = bean.someMethod();
        }
    
    }

    Spring Test提供@ContextConfiguration来让我们指定要初始Spring上下文的配置,支持Spring的各种配置方式,如XML、JavaConfig等等方式,@ContextConfiguration和@RunWith等注解都可以注解在基类上,所以可以提供一个基础类来简化单测的编写

    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration("classpath:base-context.xml")
    public class XXXTestBase {
    
    }
    
    @ContextConfiguration("classpath:extended-context.xml")
    public class YYYTest extends XXXTestBase{
    
    }

    默认情况下,子类可以基础父类的@ContextConfiguration配置,同时可以追加自己的配置,当程序非常模块化时,可以通过指定特定的配置文件来减少初始化Bean的数量,以便提高单测的执行速度

    @TestExecutionListeners注解是Spring Test用来注册TestExecutionListener的注解,提供的类似于JUnit的Before、After的扩展方法,父类的@TestExecutionListeners注解配置通样可以被子类基础,子类也可以提供自己个性的@TestExecutionListeners配置

    //可以通过@Order指定TestExecutionListener的顺序
    public interface TestExecutionListener {
        void beforeTestClass(TestContext testContext) throws Exception;
    
        void prepareTestInstance(TestContext testContext) throws Exception;
    
        void beforeTestMethod(TestContext testContext) throws Exception;
    
        void afterTestMethod(TestContext testContext) throws Exception;
    
        void afterTestClass(TestContext testContext) throws Exception;
    }

    单测一般不需要显示的配置@TestExecutionListeners注解,默认@ContextConfiguration会自动注册如下Spring Test自带的TestExecutionListener

    org.springframework.test.context.web.ServletTestExecutionListener
    org.springframework.test.context.support.DependencyInjectionTestExecutionListener
    org.springframework.test.context.support.DirtiesContextTestExecutionListener
    org.springframework.test.context.transaction.TransactionalTestExecutionListener
    org.springframework.test.context.jdbc.SqlScriptsTestExecutionListener

    可以看到,Spring Test很多方便的功能都是通过TestExecutionListener来实现的,比如说DependencyInjectionTestExecutionListener来为单测类实例进行依赖注入的

    public class DependencyInjectionTestExecutionListener extends AbstractTestExecutionListener {
    
        @Override
        public void prepareTestInstance(final TestContext testContext) throws Exception {
            if (logger.isDebugEnabled()) {
                logger.debug("Performing dependency injection for test context [" + testContext + "].");
            }
            injectDependencies(testContext);
        }
    
        protected void injectDependencies(final TestContext testContext) throws Exception {
            Object bean = testContext.getTestInstance();
            AutowireCapableBeanFactory beanFactory = testContext.getApplicationContext().getAutowireCapableBeanFactory();
            beanFactory.autowireBeanProperties(bean, AutowireCapableBeanFactory.AUTOWIRE_NO, false);
            beanFactory.initializeBean(bean, testContext.getTestClass().getName());
            testContext.removeAttribute(REINJECT_DEPENDENCIES_ATTRIBUTE);
        }
    
    }

    在单测中经常会使用到Mockito的注解,所以可以在单测基础类中使用Mockito的Rule,这样子类就可以使用Mockito的注解了

    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration("classpath:base-context.xml")
    public class XXXTestBase {
        @Rule
        public MockitoRule rule = MockitoJUnit.rule();
    }
    
    @ContextConfiguration("classpath:extended-context.xml")
    public class YYYTest extends XXXTestBase{
    
        @Resource
        @@InjectMocks
        private SpringXXXBean xxxBean;
    
        @Mock
        private XXXHsfBean xxxHsfBean
    
    }

    在执行单测时,涉及到数据库操作时经常要在单测方法执行前在数据库中准备好单测数据,Spring Test提供了非常方便的注解来在单测方法前初始化数据,如下所示

    @RunWith(SpringRunner.class)
    @ContextConfiguration(locations = "classpath:spring-test-root.xml")
    public class BTestClass {
    
        @Resource
        private TestMapper mapper;
    
        @Test
        @Sql("BTestClass_testAAA.sql")
        //默认会在BTestClass相同的目录下查找BTestClass_testAAA.sql文件执行
        public void testAAA() {
            List<TestModel> all = mapper.getAll();
    
            Assert.isTrue(all != null && all.size() == 1);
        }
    
    }

    @Sql注解可以注解在类上,表示每个单测方法前都执行该SQL脚本,但是要注意单测方法插入到数据库的记录默认并不会在单测执行完后回滚,所以如果SQL脚本中有插入操作,容易出现主键冲突,因为脚本会在每次单测执行时都执行

    @Sql可以指定脚本的执行时机,如在单测方法执行前或执行后,通过executionPhase参数控制

    在单测时,可能某些单测只能依赖MySQL,可以通过Spring的Profile功能来实现默认使用H2,但可以通过注解的方式来显示给某些单测指使用MYSQL数据源

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:jdbc="http://www.springframework.org/schema/jdbc"
        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
                http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd
                http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.2.xsd
                http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd
                http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-4.2.xsd">
    
        <beans profile="H2">
            <jdbc:embedded-database id="dataSource" generate-name="true" type="H2">
                <jdbc:script location="classpath:/sql/test_schema.sql" />
            </jdbc:embedded-database>
        </beans>
    
        <beans profile="MYSQL">
            <bean name="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
                <property name="url" value="${db.url}" />
                <property name="username" value="${db.username}" />
                <property name="password" value="${db.password}" />
                <!-- mysql jdbc 6.0的driver改包名了 -->
                <property name="driverClassName" value="${db.driver.class}" />
                <property name="initialSize" value="1" />
                <property name="maxActive" value="50" />
                <property name="minIdle" value="1" />
                <property name="maxWait" value="60000" />
                <property name="testOnBorrow" value="false" />
                <property name="testOnReturn" value="false" />
                <property name="testWhileIdle" value="true" />
                <property name="timeBetweenEvictionRunsMillis" value="60000" />
                <property name="minEvictableIdleTimeMillis" value="25200000" />
                <property name="removeAbandoned" value="true" />
                <property name="removeAbandonedTimeout" value="1800" />
                <property name="logAbandoned" value="true" />
                <property name="filters" value="mergeStat" />
            </bean>
        </beans>
    
    </beans>
    @RunWith(SpringRunner.class)
    @ContextConfiguration(locations = "classpath:spring-test-root.xml")
    @ActiveProfiles(profiles = "H2", inheritProfiles = false)
    public class BaseTest {
    
        @Rule
        public MockitoRule rule = MockitoJUnit.rule();
    
    }
    
    @ActiveProfiles(profiles = "MYSQL", inheritProfiles = false)
    public class BTestClass extends BaseTest {
    
        @Resource
        private TestMapper mapper;
    
        @Test
        @Sql("BTestClass_testAAA.sql")
        public void testAAA() {
            List<TestModel> all = mapper.getAll();
    
            Assert.isTrue(all != null && all.size() == 1);
        }
    
    }

    可以通过Spring元注解功能来使代码更语义化一些

    /**
     * 选择使用H2数据库还是使用Mysql数据库, 底层使用的是Spring的Profile功能
     * 
     * 可以通过
     * 
     * @see spring-test-datasource.xml
     * @author tudesheng
     * @since 2016年9月13日 下午7:02:38
     *
     */
    @Documented
    @Inherited
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.TYPE)
    @ActiveProfiles(inheritProfiles = false)
    public @interface DBSelecter {
    
        /**
         * profiles, 取值只能是DBTypes.H2, 或者是DBTypes.MYSQL, 默认DBTypes.H2
         */
        @AliasFor(annotation = ActiveProfiles.class, attribute = "profiles")
        String[] value() default { DBTypes.H2 };
    
        /**
         * profiles, 取值只能是DBTypes.H2, 或者是DBTypes.MYSQL, 默认DBTypes.H2
         */
        @AliasFor(annotation = ActiveProfiles.class, attribute = "profiles")
        String[] type() default { DBTypes.H2 };
    
    }
    
    @RunWith(SpringRunner.class)
    @ContextConfiguration(locations = "classpath:spring-test-root.xml")
    @DBSelecter(DBTypes.H2)
    public class BaseTest {
    
        @Rule
        public MockitoRule rule = MockitoJUnit.rule();
    
    }
    
    @DBSelecter(DBTypes.MYSQL)
    public class BTestClass extends BaseTest {
    
        @Resource
        private TestMapper mapper;
    
        @Test
        @Sql("BTestClass_testAAA.sql")
        public void testAAA() {
            List<TestModel> all = mapper.getAll();
    
            Assert.isTrue(all != null && all.size() == 1);
        }
    
    }

    在使用MYSQL等外部数据库时,单测的执行很容易产生脏数据,可以通过@Rollback注解来标注单测方法执行完后,回滚数据库操作,减少对外部测试数据库的污染

    最后,某些单测方法执行后可能会污染Spring的上下文,比如通过反射将某个容器内的Bean的属性给替换调了,可能会对其它的单测造成影响,这个时候,可以通过@DirtiesContext标注该单测方法会污染Spring上下文,需要在单测执行前或执行后重新初始化Spring上下文,慎用,容易增加单测的执行时间

    常用工具类

    Spring的AopTestUtils:提供了一些获取原始代理对象的接口
    Spring的ReflectionTestUtils:提供了一些反射的方便方法,可以用少量的代码来反射修改参数熟悉

    工程实践

    Demo工程

    参考demo工程
    http://gitlab.alibaba-inc.com/shengde.tds/unit_test_demo

    问题和经验

    • Spring Test上下文污染问题:
      某些单测执行时可能会污染Spring上下文,如通过反射修改了Spring上下文中的某些单例对象
      可以通过@DirtiesContext标记单测方法,促使Spring Test重新初始Spring上下文
    • 时间问题
      单测类中经常有些方法是和时间有关的,不太好测试,这时需要将时间获取API抽象出来
      //这个放在src/main/java中,并替换代码中所有获取当前时间代码为Time.currentTimeMillis()

      public abstract class Time {
      
          private static Time time = new Time() {
              @Override
              public long currentTime() {
                  return System.currentTimeMillis();
              }
          };
      
          public static long currentTimeMillis() {
              return time.currentTime();
          }
      
          public abstract long currentTime();
      
      }
      
      //这个放在src/test/java中,专供单测使用,在单测时,通过反射替换掉Time.time静态变量,就可以做到时间可控了
      public class SettableTime extends Time {
      
          private long time = 0;
      
          public SettableTime(long time) {
              super();
              this.time = time;
          }
      
          public SettableTime setTime(long time) {
              this.time = time;
              return this;
          }
      
          @Override
          public long currentTime() {
              return time;
          }
      
      }
    • 外部RPC服务依赖问题
      现在项目中有很多外部的服务依赖,在Spring初始化上下文时需要初始化RPC相关的Bean和服务,这会导致单测执行慢、单测执行依赖外部服务的稳定等问题,所以我们希望在单测的时候不使用外部的服务,同时也不对外提供RPC等服务,可以将外部RPC服务的定义到单独的Spring配置文件,然后在单测中将这些服务定义用Mock实现来替换,HSF通过java接口来定义服务,所以可以很方便的用cglib来创建代理类,替换掉HSF的HSFSpringConsumerBean对象,如:

      /**
       * 外部接口mock类, 方便测试
       * 
       * 
       * @since 2016年6月27日 上午11:21:08
       *
       */
      public class MockerFactory<T> implements FactoryBean<T> {
      
          private static final Logger logger = LoggerFactory.getLogger(MockerFactory.class);
      
          private Enhancer enhancer = new Enhancer();
          private Class<T> clazz;
      
          public MockerFactory(Class<T> clazz) {
              this.clazz = clazz;
          }
      
          @Override
          @SuppressWarnings("unchecked")
          public T getObject() throws Exception {
              this.enhancer.setCallback(new MockerInterceptor());
              this.enhancer.setSuperclass(clazz);
              return (T) this.enhancer.create();
          }
      
          @Override
          public Class<?> getObjectType() {
              return clazz;
          }
      
          @Override
          public boolean isSingleton() {
              return true;
          }
      
          private class MockerInterceptor implements MethodInterceptor {
      
              @Override
              public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
                  logger.info("调用Mock, 类:{}, 方法:{}", clazz.getSimpleName(), method.getName());
                  return null;
              }
      
          }
      
      }
      
      //xml
      <bean class="com.didichuxing.lang.atlantic.srv.test.util.MockerFactory">
          <constructor-arg index="0" value="xxx.hsf.interface" />
      </bean>
      //这里可以修改MockerFactory的代码,使其的参数和构造方式修改为HSFSpringConsumerBean
      //这样可以简单的替换掉配置文件中的HSFSpringConsumerBean即可
    • 一些会通过afterPropertiesSet等初始化外部资源的bean
      某些Spring Bean会通过afterPropertiesSet等方法中初始化MQ获取其它外部的依赖,通常不要将这些类配置为注解方式,而是通过XML配置的方式来使用,这样单测的时候可以非常方便的将其Mock掉,保证单测简单快速的执行
      尽量保证Spring配置文件的模块化,如将HSF消费者和HSF提供者单独使用一个Spring配置文件,这样单测只用替换少量的配置即可,不用总是维护两套配置文件,同时执行单测时也可以选择只初始化少量模块,加快单测的执行速度
      AutoConfig问题,在阿里非常多的应用使用AutoConfig,但是使用AutoConfig后,因为配置文件是在打包时替换,导致启动时比较麻烦,可以通过将AutoConfig的属性集中成一个properties文件,使用AutoConfig替换该properties文件,然后Spring再使用placeholder的方式来引入被替换的properties文件,这样,在单测的时候,可以方便的使用自己的配置文件来替换掉需要AutoConfig才能替换的文件

    其它单测框架

    http://blog.2baxb.me/archives/1398

    展开全文
  • IntelliJ IDEA单元测试入门

    万次阅读 多人点赞 2016-08-09 20:10:17
    参考文章地址地址:JUnit4单元测试入门教程 IDEA单元测试及代码覆盖率 IDEA添加jar包的三方式 本文按以下顺序讲解JUnit4的使用 下载jar包单元测试初体验自动生成测试类执行顺序@Test的属性

    参考文章地址地址:JUnit4单元测试入门教程

                                    IDEA单元测试及代码覆盖率

                                                    IDEA添加jar包的三种方式

     

     

    本文按以下顺序讲解JUnit4的使用

    • 下载jar包
    • 单元测试初体验
    • 自动生成测试类
    • 执行顺序
    • @Test的属性
    • 代码覆盖率

    下载jar包

    在github上,把以下两个jar包都下载下来。下载地址:点击打开链接

     

    下载junit-4.12.jar,junit-4.12-javadoc.jar(文档),junit-4.12-sources.jar(源码)。

     

    下载hamcrest-core-1.3.jar,hamcrest-core-1.3-javadoc.jar(文档),hamcrest-core-1.3-sources.jar(源码)。

     

    最前面那个pom是Maven的配置文件,如果你需要的话也下载下来。

     

    单元测试初体验

    先创建个简单的项目体验下单元测试是怎么一回事吧。

    我创建一个项目叫JUnit4Demo,刚创建好的工程目录如下图,然后在External Libraries中导入刚下载的那两个jar包。

                            

    通过Libraries添加Jar包

    1.打开 File -> Project Structure ->Modules-> 在Dependencies 下添加jar包

                  

    2、+ -> Library... -> java -> 选择jar的路径添加。   添加jar包后如下图所示。

                       

    3、创建一个类com.hera.util.Math,然后输入一个求阶乘的方法:

                        

    4、创建一个队Math方法的单元测试:

            创建一个和src同级别的文件夹叫test(逻辑代码放src里,测试代码放test里是个好习惯)。
            接着在IntelliJ IDEA里还要把这个test文件夹要设置成测试文件的根目录,右键选中
            Mark Directory As - Test Sources Root。

                                         
               创建一个测试类:

                IntelliJ IDEA提供了一个快捷操作Cmd + Shift + T作为类和测试之间的导航。同时允许用户在那里创建一个测试类。IntelliJ IDEA提供了一个快捷操作Cmd + Shift + T作为类和测试之间的导航。同时允许用户在那里创建一个测试类。

              为测试类MathTest添加测试方法:

                  

                     

                    运行: run MathTest 。右下方一条绿色条说明测试通过,如果把120改成别的数字那么就会测试不通过显色红色条。JUnit4有一句话叫:“keeps the bar green to keep the code clean”。

            解释一下MathTest,就六个地方要讲:
                      第一,导入了org.junit.Test;和org.junit.Assert.*;这两个包,注意后者是静态导入import static。
                      第二,testFactorial是在要测试的方法名Factorial前加个test(这也是个好习惯)。
                      第三,所有测试方法返回类型必须为void且无参数。
                      第四,一个测试方法之所以是个测试方法是因为@Test这个注解。
                      第五,assertEquals的作用是判断两个参数是否相等,例子中120是预期结果,new Math().factorial(5)是实                              际结果。但是通常不应该只比较一个值,要测试多几个特殊值,特别是临界值。

                                例如Math().factorial(0)和Math().factorial(-1)等。
                     第六,assertEquals除了比较两个int,还重载了好多次可以比较很多种类型的参数。而且JUnit4包含一堆                                assertXX方法,assertEquals只是其中之一,这些assertXX统称为断言。刚不是下载了junit-4.12-                                 javadoc.jar这个文档吗,解压后打开index.html如下图还有一堆断言。

                       

          

    执行顺序

     

    JUnit4利用JDK5的新特性Annotation,使用注解来定义测试规则。
    这里讲一下以下几个常用的注解:

    • @Test:把一个方法标记为测试方法
    • @Before:每一个测试方法执行前自动调用一次
    • @After:每一个测试方法执行完自动调用一次
    • @BeforeClass:所有测试方法执行前执行一次,在测试类还没有实例化就已经被加载,所以用static修饰
    • @AfterClass:所有测试方法执行完执行一次,在测试类还没有实例化就已经被加载,所以用static修饰
    • @Ignore:暂不执行该测试方法

     

    我们来试验一下,我新建一个测试类AnnotationTest,然后每个注解都用了,其中有两个用@Test标记的方法分别是test1和test2,还有一个用@Ignore标记的方法test3。然后我还创建了一个构造方法,这个构造方法很重要一会会引出一个问题。
    具体代码如下:

    
    package com.xuhongchuan.util;
    
    import org.junit.*;
    import static org.junit.Assert.*;
    
    /**
     * Created by xuhongchuan on 2015/7/18.
     */
    public class AnnotationTest {
    
        public AnnotationTest() {
            System.out.println("构造方法");
        }
    
        @BeforeClass
        public static void setUpBeforeClass() {
            System.out.println("BeforeClass");
        }
    
        @AfterClass
        public static void tearDownAfterClass() {
            System.out.println("AfterClass");
        }
    
        @Before
        public void setUp() {
            System.out.println("Before");
        }
    
        @After
        public void tearDown() {
            System.out.println("After");
        }
    
        @Test
        public void test1() {
            System.out.println("test1");
        }
    
        @Test
        public void test2() {
            System.out.println("test2");
        }
    
        @Ignore
        public void test3() {
            System.out.println("test3");
        }
    
    }

    运行结果如下:

    BeforeClass
    构造方法
    Before
    test1
    After
    构造方法
    Before
    test2
    After
    AfterClass

     

            解释一下:@BeforeClass和@AfterClass在类被实例化前(构造方法执行前)就被调用了,而且只执行一次,通常用来初始化和关闭资源。@Before和@After和在每个@Test执行前后都会被执行一次。@Test标记一个方法为测试方法没什么好说的,被@Ignore标记的测试方法不会被执行,例如这个模块还没完成或者现在想测试别的不想测试这一块。
           以上有一个问题,构造方法居然被执行了两次。所以我这里要说明一下,JUnit4为了保证每个测试方法都是单元测试,是独立的互不影响。所以每个测试方法执行前都会重新实例化测试类。
          我再给你看一个实验:

     

     

     

     

          添加一个成员变量

     

     

    
    int i = 0;

     

    然后把test1改为:

        i++;
        System.out.println("test1的i为" + i);

    test2改为:

        i++;
        System.out.println("test2的i为" + i);

    执行结果:

    BeforeClass
    构造方法
    Before
    test1的i为1
    After
    构造方法
    Before
    test2的i为1
    After
    AfterClass

     

           可以看到test1和test2的i都只自增了一次,所以test1的执行不会影响test2,因为执行test2时又把测试类重新实例化了一遍。如果你希望test2的执行受test1的影响怎么办呢?把int i改为static的呗。

            最后关于这些注解还有一个要说明的就是,你可以把多个方法标记为@BeforeClass、@AfterClass、@Before、@After。他们都会在相应阶段被执行。

     

     

    @Test的属性

     

    最后来说一下@Test的两个属性

    • excepted
    • timeout
      excepted属性是用来测试异常的,我们回到Math类,拿其中的求阶乘方法factorial()来说。如果传进来一个负数我们是希望抛出异常的,那要测试会不会抛异常怎么办呢?
      我在测试类MathTest添加一个测试方法:    
    •                

              这个方法就是(expected = Exception.class)和fail("factorial参数为负数没有抛出异常");之间的配合。就是这个测试方法会检查是否抛出Exception异常(当然也可以检测是否抛出其它异常),如果抛出了异常那么测试通过(因为你的预期就是传进负数会抛出异常)。没有抛出异常则测试不通过执行fail("factorial参数为负数没有抛出异常");

     

     

              然后说下timeout属性,这个是用来测试性能的,就是测试一个方法能不能在规定时间内完成。
    回到Math类,我创建一个数组排序的方法,用的是冒泡排序。

     

     

            
    public void sort(int[] arr) {
        //冒泡排序
        for (int i = 0; i < arr.length - 1; i++) { //控制比较轮数
    
            for (int j = 0; j < arr.length - i - 1; j++) { //控制每轮的两两比较次数
                if (arr[j] > arr[j + 1]) {
                    int temp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = temp;
                }
            }
        }
    }
          然后偶在测试类MathTest创建测试方法,随机生成一个长度为50000的数组然后测试排序所用时间。timeout的值为2000,单位和毫秒,也就是说超出2秒将视为测试不通过。
    @Test(timeout = 2000)
    public void testSort() throws Exception {
        int[] arr = new int[50000]; //数组长度为50000
        int arrLength = arr.length;
        //随机生成数组元素
        Random r = new Random();
        for (int i = 0; i < arrLength; i++) {
            arr[i] = r.nextInt(arrLength);
        }
    
        new Math().sort(arr);
    }
           运行结果测试不通过,且提示TestTimedOutException。
          那怎么办,修改代码提升性能呗。回到Math方法改为下sort()。这次我用快速排序,代码如下:
    public void sort(int[] arr) {
        //快速排序
        if (arr.length <= 1) {
            return;
        } else {
            partition(arr, 0, arr.length - 1);
        }
    }
    
    static void partition(int[] arr, int left, int right) {
        int i = left;
        int j = right;
        int pivotKey = arr[left]; //基准数
    
        while (i < j) {
            while (i < j && arr[j] >= pivotKey) {
                j--;
            }
    
            while (i < j && arr[i] <= pivotKey) {
                i++;
            }
    
            if (i < j) {
                int temp = arr[i];
                arr[i] = arr[j];
                arr[j] = temp;
            }
        }
    
        if (i != left) {
            arr[left] = arr[i];
            arr[i] = pivotKey;
        }
    
        if (i - left > 1) {
            partition(arr, left, i - 1);
        }
    
        if (right - j > 1) {
            partition(arr, j + 1, right);
        }
    
    }
             然后再运行一下测试类MathTest,绿色条出现了,测试通过妥妥的。

     

     

    编辑测试设置

           我们可以通过Run → Edit Configurations或工具栏上的标签来调整我们的测试运行配置。

            

     

           在Configuration选项卡,用户可以选择需要运行的测试。例如,您可以从一个类、程序包、测试套件或甚至模式中运行所有的测试。这里的Fork模式让用户在一个单独的进程运行每个测试。

     

            在代码覆盖标签你可以调整覆盖率设置。目前IntelliJ IDEA支持两种测量覆盖率引擎。默认情况下它使用自己的引擎,当然用户也可以选择JaCoCo引擎。用户也可以在这里选择覆盖率模式。Tracing{span{ mode模式会增加消耗,但测量会更精确。

                     

    运行覆盖

             收集覆盖率,用户需要通过Run → Run 'MyClassTest' with Coverage或工具栏上的选项运行特定模式的测试。

            当覆盖模式运行至少一个测试之后,IDE将会在Project工具窗口显示每个程序包、类的覆盖率数据,同时在Coverage工具窗和编辑器中也会显示。

             

     

    编辑器中的覆盖率

    如果用户添加另一个方法到MyClass,并运行覆盖率测MyClass,就会发现,没有被测试覆盖到的代码都将高亮显示为红色。覆盖的代码颜色则是绿色。如果一些代码是只覆盖部分,那没将显示为黄色。

     
     

     

           

     

    展开全文
  • Android 手机自动化测试工具有哪几种? 3 条评论  分享 按投票排序按时间排序 28 个回答 78赞同 反对,不会显示你的姓名 知乎用户,...
  • 单元测试、集成测试、系统测试和验收测试、冒烟测试、回归测试、随机测试、探索性测试和安全测试 前言:项目前期、中期至发布后测试启动前后我们一般要经历的几种测试方法。
  • 单元测试1-为什么需要单元测试

    千次阅读 2016-10-10 11:35:11
     软件开发的标准过程包括以下个阶段:『需求分析阶段』→『设计阶段』→『实现阶段』→『测试阶段』→『发布』。其中测试阶段通过人工或者自动手段来运行或测试某个系统的过程,其目的在于检验它是否满足规定的...
  • 几种测试技术

    千次阅读 2018-07-24 16:28:03
    一、单元测试技术 1.定义:单元测试又称为模块测试(程序测试),即集中力量来检验软件设计的最小单位——模块。  单元测试(unit testing),是指对软件中的最小可测试单元进行检查和验证。 2.目的:单元测试的...
  • JUnit单元测试

    千次阅读 2017-05-03 11:33:47
    软件测试有很多分类,从测试的方法上可分为:黑盒测试、白盒测试、静态测试、动态测试等;...那么今天我们就来说说什么是单元测试,为什么要进行单元测试,以及如更好的何进行单元测试单元测试目的是什
  • 根据不同的测试阶段,测试可以分为单元测试、集成测试、系统测试和验收测试。体现了测试由小到大、又内至外、循序渐进的测试过程和分而治之的思想。  单元测试的粒度最小,一般由开发小组采用白盒方式来测试,主要...
  • 从整体的角度可以分为单元测试、集成测试、系统测试、确认测试。 下面内容来自网络相关资料的整理:...(2)单元测试任务包括:1模块接口测试;2模块局部数据结构测试;3模块边界条件测试;4模块中所有独立执行通路...
  • 软件测试 -- 单元测试包含哪些内容

    千次阅读 2014-02-20 17:04:00
    1. 模块接口测试:模块接口测试是单元测试的基础。只有在数据能正确流入、流出模块的前提下,其他测试才有意义。模块接口测试也是集成测试的重点,这里进行的测试主要是为后面打好基础。测试接口正确与否应该考虑...
  • 本文内容涉及单元测试,需要读者具有单元测试的基础知识,如果没有,请移步至我之前的博客文章: 【单元测试】开篇 【单元测试】Test Double简介 2. CMocka概述 官网:https://cmocka.org/ CMocka 是一款...
  • Qt单元测试-单元测试1

    千次阅读 2018-05-23 14:05:10
    转载:http://blog.51cto.com/9291927/2114179Qt高级——QTestLib单元测试框架一、QTestLib简介1、QTestLib简介QTestLib是Qt提供的一针对基于Qt编写的程序或库的单元测试框架。QTestLib提供了单元测试框架的基本...
  • 文章目录为什么不想写单元测试为什么要写单元测试什么时候写单元测试怎么写单元测试 为什么不想写单元测试 单元测试太浪费时间了。 随着系统的复杂度增加,你的一次改动可能引发出5个bug,或者你的bug被发现的时间...
  • 单元测试和功能测试

    千次阅读 2018-01-06 11:33:47
    单元测试和功能测试区别 很多时候,系统开发好比建筑房屋。尽管这种类比不很恰当,但为了理解单元测试与功能测试的区别,我们可以扩充这种类比。单元测试好比房屋建筑现场的建筑监理员。他关心房屋的各个内部系统...
  • 单元测试(unit testing),是指对软件中的最小可测试单元进行检查和验证。对于单元测试中单元的含义,一般来说,要根据实际情况去判定其具体含义,如C语言中单元指一个函数,Java里单元指一个类,图形化的软件中...
  • android单元测试

    千次阅读 2012-08-06 22:24:10
    1、何为单元测试  作为一个第一次使用单元测试的童鞋,还是有必要了解下何为单元测试单元测试有啥好处!  在计算机编程中,单元测试(又称为模块测试)是针对程序模块(软件设计的最小单位)来进行正确性...
  • Angular 单元测试讲解

    万次阅读 2018-05-23 00:08:13
    Angular_单元测试 测试分类 按开发阶段划分 按是否运行划分 按是否查看源代码划分 其他 ATDD,TDD,BDD,DDD ATDD TDD BDD DDD Angular单元测试 Karma的介绍 jasmine介绍 单元测试的好处 使用jasmine和karma创建一...
  • python单元测试简介

    万次阅读 2020-03-18 08:00:00
    您可能知道测试很好,但是在尝试为客户端代码编写单元测试时要克服的第一个障碍是缺少任何实际的单元。JavaScript代码是为网站的每个页面或应用程序的每个模块编写的,并与后端逻辑和相关的...
  • 单元测试是检查一个独立工作单元的行为。在JAVA应用程序中,独立工作单元经常是(但不总是)一个独立的方法。相比之下,集成测试和验收测试检查的是各种组件如何交互。一个工作单元就是一项任务,不直接依赖于其他...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 193,760
精华内容 77,504
关键字:

单元测试包含哪几种