持续集成与单元测试

dccf123

贡献于2014-01-16

字数:0 关键词: 项目构建

持续集成与单元测试 麦哲思科技(北京)有限公司 1 分享知识 –柯能江 –高级咨询顾问,主要从事提升软件测试能力的培训与咨询 –联系方式: • Mobile:18601141202 •E-mail:cameron@measures.net.cn • Skype: kenengjiang –工程经验: • 长期基于.Net、J2EE等平台从事软件开发测试工作 • 曾为西安卫星测控中心、武汉大学计算机实验室、中科院网络 所、上海银联、深圳港航、上海航运、 富士康科技、天津软件 园等多家单位公司咨询 22 主要内容 • 持续集成技术 –持续集成的基本概念 –持续集成的作用和有点 –如何实施持续集成 • 单元测试技术 –单元测试基本方法 –单元测试实践中常见的问题 –单元测试工具 33 持续集成(CI) 44 主要内容 • 持续集成的基本概念 • 持续集成的作用和优点 • 如何实施持续集成 55 持续集成产生的背景 • 在软件行业发展的初期,软件项目中最棘手、最紧张 的时刻就是项目集成阶段。能单独工作的一些模块被 组装在一起,就不再能正常工作了,从而导致系统的 整体失败,而且很难找到失败的原因。 • 持续集成就是为解决这一问题出现并发展起来的。使 用持续集成就是频繁的集成,不再等到项目最后才集 成,而是在项目开发的过程中,就不断的在进行集成 。其结果是项目的可见性变得好了很多,因为问题能 够更快地检测出来。引入缺陷和发现缺陷之间的时间 变短了,缺陷的发现就更容易,可以很容易地查看改 变了什么,帮助找到问题的根源。持续集成与良好的 测试程序配合时,可以大大减少缺陷的数量。 66 持续集成的概念 • 持续集成一个比较简单的定义: 持续集成(CI)是一种实践,可以让团队在持续 的基础上收到反馈并进行改进,不必等到开发周期后 期才寻找和修复缺陷。通俗一点儿说,就是指对于开 发人员的每一次代码提交,都自动地把Repository中 所有代码Check out到一个空目录,并且自动运行所有 Test Case。如果成功则接受这次提交,否则告诉所有 人,这是一个失败的Revision。 • Martin fowler给出更具体的解释 持续集成是一种软件开发实践,团队中的每 个成员不断的集成他们的工作,通常每个人至少每日 集成——导致每天有多次集成。每次集成由自动构建 (包括测试)来验证,迅速发现集成过程中的错误。 很多团队发现这种方式使得集成问题明显减少,并且 集成使得团队能迅速地开发一个稳定的软件。 77 持续集成的基本概念 8 CI服务器 • BVT(DOA)怎么做? • 持续集成工具 源码配置库 构建工具 • 构建工具 监听配置库的变化 调用构建工具进行构建打包 8 9 CI服务器 Dev A 构建工具 源码库 Dev B Dev C Dev CDev CDev … 持续集成的基本概念 被调用 持续集成和每日构建的区别 • 持续集成和每日构建相比还有以下特点: 1. 持续集成强调了集成频率,和每日构建相比,持续 集成显得更加频繁,目前推荐的最佳实践是每一个 小时就集成一次。 2. 持续集成强调及时反馈,每日构建的目的是得到一 个可以使用的稳定的发布版本,而持续集成强调的 是集成失败之后向开发人员提供快速的反馈,当然 成功构建的结果也是得到稳定的版本。 3. 每日构建并没有强调开发人员提交(check in)源 码的频率,而持续集成鼓励并支持开发人员尽快的 提交对源码的修改并得到尽快的反馈。 1010 主要内容 • 持续集成的基本概念 • 持续集成的作用和优点 • 如何选择持续集成服务器 1111 1212 热闹的办公室 • 开发人员:我们可能要经常手工运行自己写好的单元和 集成测试代码。而且,随着项目的往前推进,这类测 试代码的数量越来越多,有没有方法能让它自动做? • QA:我们们要经常检查开发人员完成的开发工作是否 符合设计初衷,比如JavaDoc注释是否符合要求、各个 Java包是否遵循了设计约定、Java包间的使用是否符 合设计规范,评估静态代码的设计和开发质量,检查 别人的代码真是痛苦啊!!! • Release Manager:打包和发版是我们的最重要工作内 容,也是最枯燥的内容,找个新人来接替我吧… 1313 热闹的办公室 • 测试人员:一个能够基本运行的测试版本,我等得花 儿都谢了,我千万次的问,啥时候能联调通过啊?! • 数据库管理员:天天重建数据库,天天初始化数据库 ,没有时间和精力投身于数据库本身的设计、优化上 ,长此以往…… • PM: Communication! Communication! Communication! 最头疼的问题是,如何快速地将各种构建、部署、测 试及评审结果反馈到项目成员那里! • 客户:什么江湖啊! 1414 持续集成的作用 1515 持续集成的优点 • 持续集成主张项目的开发人员频繁的将他们对源码的 修改提交(check in)到一个单一的源码库, 并验证这 些改变是否对项目带来了破坏,持续集成包括以下几 个优点: 1.支持自动化构建脚本, 使构建过程完全自动 化,让任何人都可以只输入一条命令就完成系统的构 建。 2.部分测试自动化,要求开发人员提供自测试的 代码, 让任何人都可以只输入一条命令就运行一套完 整的系统测试。 3.易于定位错误,减少“内耗 ”。 4.能够提高代码质量,且能让代码质量和和工程 进度更透明。 5.加速交付速度,改善客户关系。 1616 防患于未然 17 提交缺陷 分析缺陷 接受 修复缺陷 提交代码 验证缺陷 关闭 否 是 否 是 •有多少人被卷入了一个Bug的修复? •避免block 和 DOA break Test Leader Dev Leader Dev Test Reviewer Test 17 •缺陷的预防胜于疲于奔命的修复 主要内容 • 持续集成的基本概念 • 持续集成的作用和优点 • 如何实施持续集成 1818 如何实施持续集成 • 面对眼花缭乱的众多工具如何选择? • 面对纷繁复杂的功能如何选择? • 第一步究竟该怎么迈出去? 1919 持续集成服务器的选择 实施持续集成首先是要选择持续集成服务器。现在市 面上太多的CI服务器可供选择,虽然它们都试图自动进 行软件构建的过程,但是都有各自的优点和不足。常见 的几种持续集成服务器 CruiseControl, Continuum ,Luntbuild ,Anthill, Bamboo, TeamCity,Hudson和Buildbot 等 。 开发自动化专家 Duvall 给出了五个评估CI服务器的指 标,它们分别是:(1) 特性;(2) 可靠性;(3) 寿命 ;(4) 目标环境;(5) 易用性。 20 CI 服务器特性评估 CI服务器的特性从以下几个方面考虑: • 版本控制系统—是否支持自己所用的版本控制系统 • 项目依赖项—考虑项目构建过程中是否有其他依赖项 • 构建工具—考虑目前或者将来要使用那种构架工具 • 反馈和报告—考虑CI服务器的通知机制那个更适合项目 • 工件管理—考虑对构建成功后,对工件管理的功能 • 扩展性—对测试、 静态检查等工具的支持及集成度 21 CI服务器其他指标的评估 产品可靠性 由于下载和使用开源 CI 服务器很简单,所以可以通过试用来判断 它的可靠性。 寿命前景 在下载 CI 服务器之前,了解这个服务器未来的前景会有帮助。可 以检查该工具已经出现了多少年、在它的用户群中是否有正常数量的活 动。 目标环境 CI 服务器不能在 所有 环境下工作。需要考虑服务器支持哪个操 作系统以及具体的系统需求。 易用性 产品的易用性可能是最主观的指标。有些人愿意手工修改配置文 件,而有些人想让所有管理任务都在应用程序中执行,例如 Web 控制台 。有些服务器要求从一个屏幕单击到下一个屏幕来执行简单的管理,而 其他服务器则提供了直观的向导。 22 问题? • 我们现在项目中使用的版本控制工具是什么? • 我们现在项目中使用的构建工具是什么? • 设想如果业界没有持续集成引擎,我们还能对项目实 施持续集成吗? 2323 24 CruiseControl简介 CruiseControl是一个持续集成工具,主要提 供了基于版本管理工具(如CVS,svn) 检索版本控 制存储库感知变化或每天定时的持续集成,并提 供持续集成报告(通过网页方式访问)以Email等 方式通知项目成员,其要求是需要进行日构建的 项目已编写好全自动的项目编译脚本(可基于 Maven或Ant)。 CruiseControl持续集成服务器历史悠久, 可谓是现有各种CI服务器的鼻祖,其产品的成熟 特质、使用面广、支持的版本工具多、得到一流 的开发团队支持(ThoughtWorks)。 24 25 CruiseControl的实现机制 25 CruiseControl的实现机制 2626 配置库的轮询 • SCM工具在实施持续集成期间扮演了非常重要的角色。 如果整个研发团队中的各个成员没有将各自的工件( 代码、脚本、DDL语句、等等)提交到SCM配置库中, 否则持续集成服务器将没有办法进行构建工作。 • 别把代码吊死在自己的机器上! • 传说中有108种调度模式... • 熟悉配置库的命令行工作方式,可以使调度方式更灵 活。 2727 28 cvs/svn等进行版本的更新 • 包括了SourceControl插件的配置信息, 用于检查各个源码控制系统中是否发生变化,会用到 这里的配置信息,如果检测到变化,会触发创建过程。 的属性quietperiod(单位为秒)定义了 一个时间值。如果CC检查到了变化,会自检查到变化的源码控制 系统的最后一次check in 的时间开始等待,等待时间由 quietperiod决定,等待结束之后才触发创建(build)过程,主 要是防止有人在check in的过程当中就触发创建过程(可能check in只做了一半,这个时候触发创建显然是不正确的)。 28 29 设置Schedule元素的interval属性值为3600,即表示每小时 会计划构建一次 每小时触发一次 29 30 主要使用Schedule元素中各种构建器(如ant,nant, rake等)的time属性。time属性的格式为hhmm,例如2300就 表示晚上十一点。 每天触发一次 30 31 指定时间不构建 也可以使用pause子元素来指定在某段时间内不构建 ,如白天上班时间不构建,其它时间每隔一小时构建一 次可用如下配置表示: 31 32 主要使用Schedule元素中各种构建器(如ant,nant, make等)的time及day属性。day属性值为英文星期几且大小 写不敏感,如sunday。 每周触发一次 32 CruiseControl常见的构建模式 JAVA: • CruiseControl + Ant • CruiseControl + Maven/Maven2 C# • CruiseControl + Nant • CruiseControl.Net + devenv • CruiseControl.Net + msbuild C/C++: • CruiseControl + Ant + Cpptask • CruiseControl.Net + devenv (windows平台) • CruiseControl.Net + msbuild(windows平台) • CruiseControl + exec + make • CruiseControl + Ant + make Ruby: CruiseControl + rake PHP: CruiseControl + Phing 33 34 ant编译JAVA代码及打包(jar) 34 35 Ant+cpptask编译C++代码 35 构建相关的问题? • 选择什么样的构建工具? • 从dll hell 到 jar hell,类库如何管理? • 工件怎么管理? • 测试环境和生产环境的程序包是一样构建的吗? –一样编译吗? –上生产的程序包,能否自动纳入配置库? –上生产的程序包,能否自动打tag? 3636 部署 • 用CI 工具来部署,还是用构建工具来部署? • 本地部署 –Copy • 远程部署 –FTP –SCP • 应用服务器不支持热部署怎么办? –Reload –deploy - Tomcat –wldeploy,serverdeploy– Weblogic –wsAdmin – Websphere –Hpas-deloy – Bluestone –Telnet, –IIS reset 3737 评审及规范校验 • 编码规范检验 • 代码静态逻辑检验 • 代码行数统计 • 代码圈复杂度统计 • 自动生成的代码还要检验吗? • 检查的结果如何体现? 3838 常见的静态检查工具 JAVA: • Checkstyle:编码规范检查工具 • Findbugs:代码逻辑检查工具 •PMD:代码质量综合工具 • Sonor:代码质量综合工具 • Soot:代码逻辑优化工具 • QALab:代码质量综合工具 • Testability explorer:可测性度量工具 • Javancss:代码复杂度分析工具 • Jdepend:依赖关系分析工具 C# • FxCop:代码逻辑检查工具 • StyleCop:编码规范检查工具 • Grendarme:代码逻辑检查工具(Mono) • Splint:代码逻辑检查工具 39 常见的静态检查工具 C: •BLAST:代码逻辑检查工具 • Clang:代码逻辑检查工具 • Frama-C:代码逻辑检查工具 • Sparse:代码逻辑检查工具 • Splint:代码逻辑检查工具 • Cccc:代码复杂度检查工具 • Google-c-style.el:基于emac编辑器的C语言规范模板 • Flawfinder:代码安全审计工具(Python脚本) C++ • CppCheck 静态分析工具 • CppLint:google贡献的C++编码规范检查工具(Python脚本) • Cccc:代码复杂度检查工具 • Flawfinder:代码安全审计工具(Python脚本) • Cppncss:代码复杂度检查工具 40 常见的静态检查工具 多语言: •RATS:代码安全审计工具,C/C++/Perl/PHP/Python •YASCA:代码逻辑检查工 具,C/C++/Java/JS/ASP/PHP/HTML/CSS/ColdFusion/COBOL/ •CPD:重复代码检查工具,C/C++/Java/Fortran/PHP • Sloccount:代码行数统计工具 41 42 checkstyle进行代码规范的检查 42 43 PMD进行java代码的错误检查 rulesets/basic.xml rulesets/basic-jsp.xml rulesets/braces.xml rulesets/favorites.xml rulesets/javabeans.xml rulesets/unusedcode.xml rulesets/strings.xml rulesets/design.xml rulesets/coupling.xml rulesets/codesize.xml rulesets/imports.xml rulesets/naming.xml basic 43 44 利用FindBugs进行隐藏bug的检查 44 单元测试和集成测试 • Trust,but verify! • JUnit,TestNG,NUnit,CppUnit,Cunit,CuTest,GoogleT est… • 测试结果如何汇总? • 单元测试耗时长,怎么办? 4545 46 junit进行单元测试 46 47 httpunit进行web验证 47 48 信息的合并 • 48 覆盖率 • 需要统计覆盖率吗? • 选择什么样的覆盖率工具呢? • 把覆盖率统计也加入持续集成 • 链接测试报告 4949 常见的覆盖率工具 JAVA: •EMMA • Cobertura • Sonor C# • NCover C/C++ • Gcov/lcov/ggcov(GCC) • Xcover 50 51 导入EMMA • • 在Ant脚本中加入EMMA task 51 52 注入字节码 对编译在路径bin.main.dir中的Java类注入字节码, 并且把注 入字节码的新Java类存放到路径bin.instrument.dir 52 53 生成报告的元数据 • 53 54 生成报告 54 55 测试覆盖率界面 55 56 将报告复制到Tomcat的发布目录下 56 57 修改指向Tomcat的路径 修改CruiseControl目录下的 webapps→CruiseControl→navigation.jsp,使其指向tomcat 服务器 57 58 修改Tomcat默认端口号 如果CruiseControl与tomcat在同一电脑上,就要修改 tomcat的默认端口号,修改tomcat目录下的conf下的 server.xml 58 数据库集成 • 定期基于SCM中的最新SQL脚本(包括DDL和DML语句) 完成数据库的重建和数据初始化工作。 • 借助Apache Ant内置的支持 • 借助命令行的方式 5959 通知 • Communication!Communication!Communication! • E_mail • RSS • FTP、Socket、HTTP等 6060 61 email方式告知开发人员 61 62 RSS方式反馈 • RSS 既是被动的也是主动的反馈形式,由于这种 反馈机制减少了接收到的电子邮件消息的数量,因而 更加吸引人。RSS 提要是一份生成的 XML 文件(符合 标准),该文件基于某些事件进行更新。RSS 阅读器 随后获取此更改并创建一条指示新内容的被动的消息 。因而,如果您不愿意被大量的电子邮件所困扰,可 以改用这种方式。 62 63 启动CruiseControl服务器 63 64 输入http://XXX.XXX.XXX.XXX:8080 • 可以手动build • 也可以在指定时间时 自动build 64 65 具体效果如下: 65 66 查看测试页面 66 67 图形表示 67 实践中的持续集成 68 CruiseControl • 持续改进,Day Day up 源码版本库 ANT 监听配置库的变化 调用ANT进行构建打包 CheckStyle Findbugs JUnit SoapUI Emma 编码规范 结构分析 单元测试 集成测试 代码覆盖率 HttpUnit Web测试 68 69 社区活跃的CI引擎—Hudson Hudson 是一种革命性的开放源码 CI 服务器,它从以前的 CI服务器吸取了许多 经验教训。Netbeans、Ruby IDE等许多项 目都在使用它。 功能和特点 • 易于安装配置,上手快 • 界面友好,人性化,报表一目了然 • 超强的扩展性,插件十分丰富 • 支持分布式构建 • 社区活跃 69 70 轻量级的CI引擎—BuildBot BuildBot是轻量级的CI引擎,用python写的, 该python程序只依赖python环境和Twisted(一个 python网络框架),支持多平台环。Mozilla, Google chromium ,阿里巴巴等都在使用该工具进 行持续集成。 功能和特点 • 支持C/C++/Python • 支持CVS/SVN/Git/Mercurial • 通过Web,Email,IRC等方式工作 70 Hudson常见的构建模式 JAVA: • Hudson + Ant • Hudson + Maven/Maven2 C# • Hudson + Nant • Hudson + MSBuild C/C++: • Hudson + CMake + CppCheck (CppUnit + Gcov/Lcov) • Hudson + make + CppCheck + (gTest + Gcov/Lcov) Ruby: • Hudson + Rake PHP: • Hudson + Phing 71 72 小结 • CI是敏捷的一个最佳实践,可以提升软件质量、降低 研发风险、拒绝浪费。 • 持续集成能够解决研发工作中80%的重复性劳动 • CI不是某个人的事情,需要整个团队的参与配合,是 一种开发模式,也需要制定一些规约,还需要硬件设 备的支持。 • CI很好很强大,但是也需要持续改进。 72 小结 单元测试技术 7474 课程安排 • 单元测试基本方法 • 单元测试实践中常见的问题 • 单元测试工具 7575 软件开发的困难 • 软件就是为修改而生的… –总会有新功能加入 –总会有缺陷要修复 –时不时要优化一下代码 –最近还比较流行重构 • 修改软件是危险的举动 –我们如何得知已经正确的完成了修改? –我们如何得知没有破坏任何(既有的)东西? 7676 软件开发的困难 • 当前我们如何测试修改 1. 编译 2. 打包部署 3. 运行程序 4. 鼠标操作 5. 看看效果 6. 重复这些步骤 • 这种测试的缺点 – 不能立即获得反馈 – 时间漫长 – 运行次数不足 – 甚至不测试 7777 为什么要进行单元测试? • 尽早发现代码中的错误 • 改良项目代码的整体结构,便于修改、测试、维护 • 验证代码与设计的符合性 • 降低测试、维护升级的成本 • 使开发过程适应频繁变化的需求 • 有助于提升程序员的能力 7878 单元 测试 单元 测试 ……. 被测模块 被测模块 被测模块 集成 测试 已经过 测试的模块 设 计 信 息 系统 测试 验收 测试 软 件 需 求 系 统 其 他 元 素 已集 成的 软件 已确 认的 软件 可交 付的 软件 测试过程 7979 单元 测试 单元测试过程 • 单元测试:Unit Testing – 目标: • 检验程序最小单元有无错误 – 接口、数据结构、边界、覆盖、逻辑 • 检验单元编码与设计是否吻合 – 时机: • 编码完成后,首先要实施的测试 •TDD,编码之前。 – 方法: • 静态测试 • 白盒测试 – 责任: • 开发工程师 8080 集成测试过程 • 集成测试:Integration Testing – 目标: • 检验组成系统的模块接口有无错误 • 代码实现的系统设计与需求定义是否吻合 – 时机: • 主要的单元测试完成后,经常与单元测试同步进行 – 方法: • 黑盒测试 • 灰盒测试 – 责任: • 开发工程师 • 测试工程师 8181 系统测试过程 • 系统测试:System Testing – 目标: • 检验组成整个系统的代码、以及系统的软硬件配合有无错误 • 代码实现的系统与用户需求是否吻合 • 检验系统的文档等各种是否完整、有效 • 模拟验收测试的要求,检查系统是否符合用户的验收标准 – 时机: • 多数集成测试完成后 – 方法: • 黑盒测试 – 责任: • 测试工程师 8282 测试过程 • 验收测试:Acceptance Testing – 目标: • 使客户验收签字 • 系统是否符合事先约定的验收标准 – 时机: • 系统测试完成后,在项目组看来开发和测试工作已经全部完成 ,可以交付使用 – 方法: • 黑盒测试 – 责任: • 产品经理或其他高级经理 • 开发工程师 • 测试工程师 • 用户 8383 测试过程的概念辨析 名称 测试对象 侧重点 参照物 充分性的 评价方法 时机 测试方法 测试执行者 投入工作 量 发现的缺 陷个数 单元测试 软件的最小 单元,如函 数、方法等 逻辑的正 确性 详细设计 、源程序 代码、分 支等覆盖 率 软件中的 基本组成 单位完成 后,边开 发边测试 白盒测试、 动态测试 一般是开发人 员 集成测试 软件的模块 、子系统 接口的正 确性 概要设计 、详细设 计 接口覆盖 率 软件系统 集成过程 中,边集 成,边测 试 黑盒测试 、 功能测试、 白盒测试等 开发人员与测 试人员 系统测试 系统 需求的满 足性 产品需求 用户场景 覆盖率 系统开发 完成后, 交付客户 之前 黑盒测试 、 功能测试、 非功能测试 等 测试人员 验收测试 系统 需求的满 足性 客户需求 需求覆盖 率 交付客户 后,正式 投入使用 之前 黑盒测试 、 功能测试、 非功能测试 等 客户 8484 按角色划分的敏捷测试过程 01/06/10 85 迭代周期中,测试按照角色划分,大部分周期处于并行测试阶段。 实线表示具有连贯性、集中性的测试任务,绿色虚线反之。 箭头指向的方向为时间轴方向,红色竖线表示版本上线时间点。 不同角色的测试工作对比 01/06/10 86 迭代周期中,如果没有上一个版本Hotfix缺陷的理想情况下,不同角 色的测试工作对比如下图所示: 用户测试,分为UAT(User Acceptance Testing)和PAT(Production Acceptance Testing),也对应于Alpha和Beta测试。 恶性循环和良性循环 01/06/10 87 若上一版本质量差,实现新需求的同时,还要修复、复测大量遗留缺 陷,导致工作量急剧上升;亦会导致开发员无充分的时间进行代码级 测试,从而加重后续测试员、用户测试负担,增大项目风险。 反之,若版本质量好,省出的时间还可在迭代中适量增加重构、探索 测试、代码抽查等任务,增强应用程序健壮性,形成良性循环。 单元测试定义 • 单元是被测软件的独立的和最小部分 –一个类 –一个函数 –一个按钮 –一个模块? –多个函数? –一个界面? –一个菜单? • 单元测试是对软件基本组成单元进行的测试。 8888 何时做单元测试? • 工匠一:先拉上一根水平线,砌每一块砖时,都与这根 水平线进行比较,使得每一块砖都保持水平。 工匠二:先将一排砖都砌完,然后拉上一根水平线,看 看哪些砖有问题,再进行调整。 你会选择哪种工作方法呢?你一定会骂工匠二笨 吧!这样多浪费时间呀! 然而你自己想想,你平时在 编写程序的时候又是怎么做的呢?我们就是按工匠二 的方法在干活的呀!甚至有时候比工匠二还笨,是整 面墙都砌完了,直接进行"集成测试",经常让整面的 墙倒塌。看到这里,你还觉得自己的方法高明吗? 8989 测试驱动开发 测试驱动开发(TDD)的前提条件是有良好的、详细的 、通过评审的类设计模型。 测试过程的基本过程为: 1) 明确当前要完成的功能,记录成一个TODO列表。 2) 快速完成针对此功能的测试用例编写。 3) 测试代码编译不通过。 4) 编写对应的功能代码。 5) 测试通过。 6) 对代码进行重构,并保证测试通过。 7) 循环完成所有功能的开发 01/06/10 90 测试驱动开发 优点 可以有效的避免过度设计带来的浪费。但是也有人强调在开发前需要有完整 的设计再实施可以有效的避免重构带来的浪费。 可以让开发者在开发中拥有更全面的视角,避免过度实现带来的浪费。 缺点 开发者可能只完成满足了测试的代码,而忽略了对实际需求的实现。结对编 程或交叉走查以有效避免该问题。 会放慢开发实际代码的速度,特别对于要求开发速度的原型开发造成不利。 这里需要考虑开发速度需要包含功能和品质两个方面。 对于GUI,Web应用而言。构造单元测试比较困难,如果强行构造单元测试, 反而给维护带来额外的工作量。 测试驱动开发会导致单元测试的覆盖度不够,比如可能缺乏边界测试。在实 际的操作中,和非测试驱动开发一样,当代码完成以后还是需要补充单元测 试,提高测试的覆盖度 01/06/10 91 单元测试的基本方法 • 单元测试的基本方法有: –人工静态分析,通常通过代码检查的方式来完成; –自动静态分析,通常借助工具完成; –自动动态测试,通常借助工具完成; –人工动态测试,通常通过打桩、编写驱动来完成; 9292 案例:人工静态分析法 • int getMax(int a[],int n) { int m; int temp=a[0]; for(m=1;m1)&& (B=0) THEN X=X/A;  If (A=2)OR (X>1) THEN X=X+1;  设计测试用例  A = 2,B = 0, X = 3 • 如果将&&错写为|| ,||错写为&& ,则覆盖率同样达到了100%,但是 这个逻辑错误却无法发现 A>1 AND B=0 A=2 OR X>1 X=X+1 X=X/A a b c d e Y N Y N 104104 判断覆盖 • Decision Coverage,执行 足够多的测试用例,使得程 序中的每个分支都得以执行 ; • 判定覆盖又称为分支覆盖;分支覆盖; –优点 –缺点 • 满足判定覆盖的测试用例一 定满足语句覆盖:判定覆盖 比语句覆盖强。但仍是弱的 逻辑覆盖。 A>1 AND B=0 X=X+1 A=2 OR X>1 X=X/A a b c d e YN YN L 1 L 2 105105 判断覆盖  判断覆盖示例  If (A>1)&& (B=0) THEN X=X/A;  If (A=2)OR (X>1) THEN X=X+1;  设计测试用例  A = 2,B = 0, X = 2, 覆盖路径ace  A = 2,B = 1, X = 1, 覆盖路径abd A>1 AND B=0 X=X+1 A=2 OR X>1 X=X/A a b c d e YN YN L 1 L 2 106106 判断覆盖  判断覆盖示例  If (A>1)&& (B=0) THEN X=X/A;  If (A=2)OR (X>1) THEN X=X+1;  设计测试用例  A = 3,B = 0, X = 1, 覆盖路径acd  A = 2,B = 1, X = 3, 覆盖路径abe A>1 AND B=0 X=X+1 A=2 OR X>1 X=X/A a b c d e YN YN L 4 L 3 107107 条件覆盖 • 执行足够的测试用例,使得程序中每 个判断的每个条件的可能取值至少执 行一次; • 程序中有4个条件 –A>1, B=0, A=2, X>1 –为达到“条件覆盖”标准,需要执行 足够的用例使得在a点有: • A>1,A<=1, B=0,B≠0 –需要执行足够的用例使得在b点有 : • A=2, A≠2, X>1,X<=1 条件覆盖不一定包含判定覆盖 判定覆盖也不一定包含条件覆盖! A>1 AND B=0 X=X+1 A=2 OR X>1 X=X/A a b c d e Y N Y N 108108 条件覆盖 • 设计如下两个用例即可满 足条件覆盖的要求;  设计测试用例  A = 2,B = 0, X = 4,覆盖路 径ace  A = 1,B = 1, X = 1,覆盖路 径abd A>1 AND B=0 X=X+1 A=2 OR X>1 X=X/A a b c d e YN YN L 1 L 2 109109 条件判断组合覆盖  判定-条件覆盖就是设计足够的 测试用例,使得判断中每个条件 的所有可能取值至少执行一次, 同时每个判断中的每个条件的可 能取值至少执行一次。  条件判断覆盖并不比条件覆盖更 强  设计测试用例  A = 2,B = 0, X = 4,覆盖 路径ace  A = 1,B = 1, X = 1,覆盖 路径abd A>1 AND B=0 X=X+1 A=2 OR X>1 X=X/A a b c d e YN YN L 1 L 2 110110 条件判断组合覆盖 • 条件组合覆盖就是设计足够 的测试用例,运行被测程序 ,使得每个判断的所有可能 的条件取值组合至少执行一 次。 • 这是一种相当强的覆盖准则 ,可以有效地检查各种可能 的条件取值的组合是否正确 。它不但可覆盖所有条件的 可能取值的组合,还可覆盖 所有判断的可取分支,但可 能有的路径会遗漏掉。 • 满足条件组合覆盖标准的测 试数据,也一定满足判定覆 盖、条件覆盖和判定/条件覆 盖标准。 条件组合如下: ① A>1, B=0 ② A>1, B≠0 ③ A<=1, B=0 ④ A>=1, B≠0 ⑤ A=2, X>1 ⑥ A=2, X>=1 ⑦ A≠2, X>1 ⑧ A≠2, X>=1 111111 条件组合覆盖 • 测试用例(A,B,X) 覆盖组合 •(2, 0, 4), (2, 0, 3) ①, ⑤ •(2, 1, 1), (2, 1, 2) ②, ⑥ •(1, 0, 3), (1, 0, 4) ③, ⑦ •(1, 1, 1), (1, 1, 1) ④, ⑧ 112112 路径覆盖 • 路径测试就是设计足够的测试用例,覆盖程序中所有 可能的路径。 –测试用例 通过路径 –(2, 0, 4), (2, 0, 3) ace(L1) –(1, 1, 1), (1, 1, 1) abd(L2) –(1, 1, 2), (1, 1, 3) abe(L3) –(3, 0, 3), (3, 0, 1) acd(L3) • 这是最强的覆盖! 113113 单元测试的注意事项 • 先根据外部设计描述测试功能正确性 • 再根据内部结构测试逻辑正确性 • 要编写单元测试程序,试单元测试自动化 • 每个单元测试要独立运行,测试用例之间尽可能不相 互依赖 • 从简单的测试开始,一次完成一个测试,不要过度设 计 • 经验数据: –编写被测代码的工作量:编写单元测试的工作量=2:1 • 先写测试代码,再写具体实现 • 每次修改了代码后,都要执行单元测试 • 重构代码,也重构测试 114114 课程安排 • 单元测试基本方法 • 单元测试实践中常见的问题 • 单元测试工具 115115 单元测试实践常见问题 •“传说”中的过程 1. 实例化被测试对象 2. 提供测试数据 3. 调用被测试的方法 4. 验证测试结果 @Test public void addition() { int x = 1; int y = 1; int z = x + y; Assert.assertEquals(2, z); } 116116 实际情况1 • 私有方法,无法从外部调用被测试的方法 @Test public void testSum() { //How to invoke? Assert.assertEquals(2,???); } Public class Calculator{ private int sum (int x,int y){ return x + y ; } } 117117 实际情况2 • 函数没有返回值,不知道如何验证结果 @Test public void addition() { //How to invoke? Calculator myCalculator = new myCalculator(); Assert.assertEquals(???,???); } Public class Calculator{ private int z; public void sum(int x,int y){ this.z = x + y ; } } 118118 实际情况N • 需要容器支持才能运行 • 数据访问层怎么测试 • 和外部系统有交互,怎么办 • 测试耗时太长怎么办 •…… 119119 现实总是很残酷 • 实际的情况 1. 理想是美好的,世界是残酷的 2. 软件由对象的相互协作来实现功能,对象之间充斥着 必不可少的依赖 3. 软件的运行依赖于数据库,网络和文件系统 4. 多数函数的并没有返回值来验证行为 120120 单元测试 • 不经意的转变成集成测试 1. 我们可以将被依赖的类在测试中实例化 2. 被依赖的类肯定也在依赖别的类 3. 一环扣一环,于是我们把整个软件的大部分类都牵扯 到一次测试中 4. 这个单元测试变得笨重 5. 这已经不是单元测试了!!! 121121 解依赖 • 有依赖,就要解依赖 • 在被测试的代码中,依赖是少量的 • 解依赖就是将无法放入测试中的小段代码从整块代码 中分离出来的行为 • 解依赖就是构造接缝的过程 122122 解依赖 • 伪对象(Mocker) 1. 由于虚函数的存在,在测试中的派生类可以改变原来 的行为 2. 在测试中用于伪装成被测试类的合作者的对象,称为 伪对象 3. 伪对象是后面介绍的解依赖技术的根本 123123 解依赖 • 完全没有找到接缝,怎么办? • 没有接缝就创造接缝(重构,改掉代码里的坏味道) • 创建接缝的方法 1. 提取并重写调用 2. 设置并替换 3. 提取并重写获取方法 4. 提取并重写工厂方法 124124 如何开始 • 当前的项目完全没有单元测试 • 动手吧,但不要试图一下子为所有的代码都建立单元 测试 • 蚕食,每次要进行修改,都试试将修改的部分放到测 试下 • 就好像海里不断生长的岛屿,最终会变成大陆 125125 如何开始 • 工具 –X-Unit – CuTest – GoogleTest和GoogleMock – Cmockery – 覆盖率工具 • 更多思考 – 单元测试很好很强大,但不是银弹 – Code review对交流和成长更有帮助 126126 课程安排 • 单元测试基本方法 • 单元测试实践中常见的问题 • 单元测试工具 127127 单元测试需要那些工具 • Framework类的工具 • 覆盖率 • Profiling 128128 Framework • 大名鼎鼎的X-Unit系列工具 • 最早的单元测试框架产生于smalltalk,叫做SUnit,后 来被移植到Java上,被称为JUnit • 自从1999年以来,JUnit已经发展成业界标准的Java测 试工具,获得了广泛的接受,不仅仅在开源的项目中 ,还经常被商业软件公司所使用。 • 后来这种框架被相继移植到30多种语言和环境中。在 这个框架结构后面所表现的一些概念,被抽象成xUnit, 慢慢演化成一些简单的编写测试的规则。 129129 Framework •X-Unit • Google Test • CuTest • TestNG 130130 代码覆盖率 • 代码覆盖率工具的原理 • Rational PureCoverage • Emma • Clover • Clover.Net • Ncover • BullseyeCoverage • VS • XCover 131131 Profiling • Profiling工具的原理 • 什么时候该用Profiling工具? • Rational Quantify • Jprofiler • Google perftools 132132 其他测试工具 • 测试用例管理工具 • GUI自动化测试工具 • 虚拟化技术的在测试中的应用 • 其他测试工具 133 参考更多 http://sourceforge.net/projects/cunit/ http://sourceforge.net/projects/cppunit/ http://code.google.com/p/googlemock/ http://code.google.com/p/googletest/ http://sourceforge.net/apps/mediawiki/cppcheck/index.php?title=Main_Page Google Test心得文章 http://www.cnblogs.com/coderzh/archive/2009/04/06/1426755.html 134 135 测试用例管理工具 • 看似最简单,最没技术含量,实际最难做好! • 测试用例只是给测试人员看的吗? • 测试用例的评审都需要哪些人员参加? • 什么时候开始编写测试用例? • 测试用例和需求的关联 • 测试用例和缺陷的关联 • 测试用例的版本跟踪 • 测试用例执行情况的跟踪 • 测试用例的统计 135 136 常见的几类测试用例管理工具 • 自己开发的 • Excel • Word • Mantis,bugzilla等缺陷管理工具 • TestManager,TD等商业工具 • TestLink等开源工具 136 137 GUI自动化测试工具 • 基于录制回放技术 • 对象识别技术 • 动态验证点 • 数据驱动测试 137 138 常见的GUI自动测试工具 • IBM Rational Robot • IBM Rational Function Tester • Mercury Winrunner • Mercury QTP • Badboy,marathon,Selenium等开源测试工具 138 139 虚拟化工具在测试中的应用 •GUI自动化测试受环境影响大 • 测试环境数量不够,影响测试效率 • 测试环境维护工作量大 • 如何管理虚拟系统? 139 140 其他测试工具 • Findbugs • SoapUI • IBM Rational PurifyPlus • DIY的测试工具,如DBSaver 和 Web tail 140 罗马不是一天建成的 141141 齐心协力才能保证质量 142142 Thank you. Q&A 143143

下载文档,方便阅读与编辑

文档的实际排版效果,会与网站的显示效果略有不同!!

需要 10 金币 [ 分享文档获得金币 ] 0 人已下载

下载文档

相关文档