使用 JUnit 测试 Java 应用程序 课堂笔记(三)

目录

一.测试驱动的开发(TDD)

二.连续集成测试(CI)

三.综合测试

四.课堂补充


一.测试驱动的开发(TDD)

  • 定义:先开发测试用例,再编写应用程序代码,驱动软件设计
  • 步骤:

  1. 创建测试场景,编写测试用例
  2. 编写应用程序代码
  3. 运行测试,若失败则重复②③ / 若成功则④ 
  4. 重构应用程序代码
  • TDD 优点:
  1. 调试时间减少:代码根据测试用例开发
  2. 灵活、可维护和可扩展的代码
  3. 关键分析和设计:设计了测试场景并编写了测试用例时,才开发代码
  4. 可执行文档:测试用例可由其他程序员参考,以了解代码用法及用途
  5. 面向用户的开发:测试用例从用户角度编写
  • 有效测试的准则:
  1. 识别并测试方法的 边界条件,因为方法实际上是在其边界值上生成意外结果
  2. 验证 测试结果,因为还要预料得到不正确的结果
  3. 了解意外问题,借助模拟对象 模拟这些错误 并将它们注入代码
  4. 通过不同策略 交叉检查 测试用例的结果
  5. 应用程序代码应该进行良好 优化 以处理大型复杂值,并且必须始终返回准确结果
  • 有效测试的属性:
  1. 自动: 单元测试应该 自动运行,并且没有任何外部依赖,所有连接配置应该由测试完成
  2. 彻底: 测试用例应该覆盖代码的所有方面并提供 100% 的代码覆盖率
  3. 独立测试用例应该 独立 于其他测试用例
  4. 专业测试应该符合生产 标准 并且代码应该发送给生产服务器
  5. 可重复测试用例应该是 可重复的,并且在执行时生成同样结果
  • 常见编程问题:
  1. 不可忽视中断失败的测试用例
  2. 如果代码处理小数值,那么应该用 浮点数 对它进行测试
  3. 避免测试用例长时间运行
  4. 创建低耦合的测试用例
  5. 测试应该总是生成同样结果,无论在什么机器上执行
  6. 不要将任何类型的生产代码或者配置代码放到 main() 方法中

二.连续集成测试(CI)

1.基本概念

  • CI 测试:应用程序以一定时间间隔彼此集成,验证整体功能和稳定性
  • CI 测试优点:
  1. 提供便捷的单元集成 
  2. 允许自动部署
  3. 提供项目的运行状况报告
  4. 实现独立于平台的开发
  5. 提供项目的更好可视性
  • 实现 CI 连续集成测试的工具(独立平台):
  1. Hudson
  2. Jenkins
  • CI 测试是一种软件开发做法,团队成员 频繁集成 以加速调试过程
  • 连续集成测试方法开发的应用更稳定,因为应用模块 定期集成
  • CI 测试能连续集成应用程序单元并在开发的 早期阶段 识别问题
  • CI 测试能在指定时间后 自动部署模块
  • CI 测试可以生成项目的 运行状况报告
  • CI 测试提供了环境在 不同平台上 集成和测试模块

2.Hudson 简介

  • 简介:Hudson 运行在 Glassfish 或 Apache Tomcat 之类的服务器上,可执行 Ant Maven项目
  • 优点:可轻松安装,通过 基于WEB 的 UI 配置,跟踪 jar文件及其版本
  • 执行构建后操作:
  1. 生成 JUnit 测试报告:.xml 格式保存到指定路径  
  2. 发送电子邮件通知:向开发人员发送电子邮件通知不稳定的工作版本

3.Jenkins 简介

  • Jenkins 起初作为 Hudson 项目开发,和 Hudson 简介基本相同,但是比 Hudson 有更多的更新和补丁
  • 要启动 Jenkins,需要访问位于端口 8080 localhost 服务器
  • Jenkins 将所有模块组合到中央储存库,并将它们构建在一起
  • 分析工作版本状态图标:
  • 分析工作版本稳定性图标:
  • 注册:
  • 使用 Jenkins 构建目,需要配置 JDK、Ant 和 Maven 路径:
  • Jenkins 上执行 CI 测试,执行以下步骤:
  • 1. 创建新项:
  • 2. 配置该项(见下图构建触发器 Build Triggers
  • 1+2.上面两步创建了项目,显示:
  • 3. 创建工作空间(在 Jenkins 安装文件夹中寻找 workspace)
  • 4. 将文件复制到此工作空间(将 IDE 上的项目源文件复制到 Jenkins 安装处的 workspace)
  • 常用的构建触发器是:
  • 在其他项目构建之后构建 / 定期构建:        
 
  • 不断循环构建,时间设置:
  • 默认情况下, Jenkins 抽取到当前用户的 .jenkins 文件夹。

三.综合测试

Junit 测试总结

 

四.课堂补充

  • STLC(Software Testing Life Cycle),“缺陷修正”和“测试执行”是一个多次往复的过程,如果这个循环一直有,说明软件代码质量很差,如果这个过程几乎没有,测试人员的测试出现了问题,不能有效的发现BUG 
  • 测试级别:从测试颗粒度上来说,从左到右,颗粒度增大
  • 颗粒:可以理解为一个测试点对应的代码量,是整体,不可分割
  • javac -cp,-cp==-classpath:让 java解析器 去查找用户类文件和注释处理程序的位置 

 

  • java -cp .;junit-4.12.jar;hamcrest-core-1.3.jar org.junit.runner.JUnitCore CalculatorTest
  • org.junit.runner.JUnitCore就是我们说的测试运行器(Test Runner) 
  • 要非常清楚5个注解批注的运行时间(什么时候运行),运行次数,对函数的要求(public,void,static) 
  • assertEquals:是Equals,复数 
  • 代码必须抛出特定异常,如果抛出异常,我的测试就“成功”,否则,测试就是“失败” 
  • 这5个异常什么时候会出现,记好异常类型,对分析程序错误非常有效 
  • 为什么现在要求JDK/JRE,真正的生产环境使用64位的?32位的内存空间限制太大(学过操作系统都知道,32位的寻址空间限制,导致32位jdk的内存使用量不能超过4G,真正用于当前Java项目的,就更少)
  • 游戏对战逻辑,就必须要对Timeout进行限制,否则,游戏的可玩性就无从谈起了 
  • 如果直接将jre文件夹放到eclipse.exe同级别目录,即使不配置Java的环境变量(JDK1.5以上,只需要JAVA_HOME和Path),Eclipse 也能正常运行。 所以,即使安装的是32位jdk,要一个64位jre,就可以运行最新版Eclipse
  • Eclipse平台(对,它其实是一个平台),提供选择view的方式,流行的IDE基本都有类似的功能 
  • Ignore,设置以后,不是为了从此不用这个测试方法,往往是“还没有完成”的意思 
  • @Test注解,接受参数时,一般就2个:expected(异常类) 和timeout(毫秒) 
  • 代码出异常了,但是符合测试用例的设计,所以“测试成功,测试通过” 
  • Thead.sleep(),接收的是毫秒数,通过类的静态函数sleep(),控制当前代码所在的进程“休眠” 
  • 有一个小问题,我这样写,对吗? @Test(excepted=ArithmeticException.class,timeout=200) 
  • 比如:assertEquals,而不是Equal,same而不是some,越简单,越觉得不值一看,越容易忽略 

 

  • 核心、逻辑、对象、文本、集合、数字(6大类的匹配器) 
  • hamcrest表达式,在PHP,Ruby,Python等语言上也都适用 
  • hamcrest表达式:assertThat(期望值,匹配器),我们要探讨的就是《匹配器》的使用 
  • Eclipse中,有“workspace”的概念,活用工作空间,对管理本地项目至关重要。
  • 第一行的 Matchers.* :防止每个匹配器都要重新import 
  • 如果不是用 hamcre-all jar包,而是使用 hamcrest-core jar包,很多匹配器将会报错
  • anything(),见名知意,当前匹配器是个“老好人”,只要执行,就会匹配成功 
  • allOf(), 对应逻辑与。所有匹配器为true,最终才是true 
  • anyOf(),对应逻辑或。只要有一个匹配器是true,最终就是true 
  • 逻辑匹配器,是一个可以接受多个匹配器作为参数的匹配器 
  • equalTo(): 判定的是“值”相等,另外,这里是单词的单数,不是复数 
  • equalToIgnoringWhiteSpace 忽略前导和尾部空格 
  • array()匹配器,匹配的规律是:“一一对应” 
  • hasItem()匹配器,内部可以是匹配器 
  • 容忍值的出现是有原因的,浮点数由于存储类型与整型不一样,所以小数点后面的数值会出现不精确的情况,所以,我们比对2个浮点值相等,是这样的:if(  floatA - floatB <   0.000001)  0.000001,就是容忍值,比如:我们要求数值的精度是小数点后面2位,那么我们使用0.0001作为容忍值,就可以保证floatA 和floatB 的相等判断是正确的 
  • 实际的软件开发中,浮点数的使用远远大于整型 
  • eclipse的项目和NetBeans的项目,目录结构很明显,NetBeans的,有nbproject文件夹 

 

  • 【语句覆盖率= 已经执行的语句÷语句总数】 
  • 代码覆盖类型包括:语句覆盖,函数覆盖,条件覆盖,循环覆盖 
  • 5行代码,前4行执行了10此,第五行一次没执行,那么覆盖率仍然是80% 
  • 需要使用 Jacoco的项目,项目路径中不允许出现中文,空格,特殊字符等 
  • 做Java开发,项目放中文路径就是个隐藏在最后的“彩蛋”,你不知道你的代码什么时候会爆发 
  • 另外,NetBeans,Eclipse,包括Idea(大部分java 的IDE),都会默认检测自己所在目录是否有“jre”目录,如果有,则会优先使用此目录下的 jre环境,所以将 jre目录 复制到 Eclipse目录下后,Eclipse就变成了“绿色版” 
  • Eclipse之所以提供一个叫“work-space"的设置,就是为了让开发人员平时将代码放到它里面,然后这种”中文路径“的问题,很多时候就自动避免了 ,另外,这个软件内部内多 http请求,所以会被杀毒软件误杀 

 

  • 如果等到所有的都完成了再测试,后期代码变动带来的风险非常大,所以使用“桩模块“的方式,先略过一些业务,保证常规业务流程的逻辑是”按照我们预期的执行了“ 
  •  “桩模块”的实现,需要“接口机制”的支持。我们依赖的类还没有实现,但是这个类实现自一个接口,那么我们先通过自己实现一个此接口的类,返回我们“要求的固定值”,来解除对此类的依赖 
  • 在你截图的代码中,如果【EasyMock.replay(emailChecker);】没有执行的话,会怎么样?为什么? 
  • 会报错,代码里如果一个接口多次调用,会无法对接口方法进行mock,EasyMock.replay()是将Mock的行为按照mock的步骤重发一遍,在单元测试运行的时候,就能够正确的执行 
  • 缺少了“注册”,那么我们的“设置的期望值”根本不会起作用,也就是说,EasyMock根本没有模拟我们的“期望” 
  • 当boolean result = register.verify(name, email);这句话执行的时候,EasyMock是根据我们EasyMock.expect()设置的期望值来返回结果的,并且在EasyMock.expect中,定义了是设置的verifyEmail()函数的传入参数。所以EasyMock会“模拟”输出,并不是真正的实例化了一个“实现了IEmailChecker”的对象 
  • 没有创建EmailChecker示例,是说没有用New的方式  
  • EasyMock 使用了Java的反射机制,尤其是在expect()函数使用的时候 
  • EasyMock.verify(emailChecker); / / 不是参与的测试用例,而是来验证我们通过Mock创建出来的这个IEmailChecker接口对应的类的模拟实例,是否按照我们expect的条件执行了 

 

  • EJB:将业务逻辑从客户端软件中抽取出来,封装在一个组件中。这个组件运行在一个独立的服务器上,客户端软件通过网络调用组件提供的服务以实现业务逻辑,而客户端软件的功能只负责发送调用请求和显示处理结果。 
  • 默认的glassfish的安装目录是:【C:\Program Files (x86)\glassfish-4.1.1\glassfish\lib\embedded】
  • Derby:Apache Derby是一个完全用 java编写的数据库,核心部分derby.jar只有2M,所以既可以做为单独的数据库服务器使用,也可以内嵌在应用程序中使用
  • Java还属于Sun的时候,Derby被开发出来,作为Java内置轻量级数据库,可是没想到让 Sqlite给暗度陈仓了。不得不说,Android是一个很大的推手
  • Jenkins的功能: 自动获取代码,并编译
  • EasyMock需要expect和replay,Mockito需要when().thenReturn()  
  • createMock:创建常规模拟对象
  • createNiceMock:可以创建随意的模拟对象(创建的不符合规范也不报错)
  • createStrictMock:最严格的,创建的稍有不规范,mock失败 
  • 逗号分隔符:简称csv,Comma separator,value 
  • csv可以用 excel打开,csv实际是文本文件,除了csv,还有tsv:tab  separator value 
  • DELETE,只删除数据集里面有的
  • DELETE_ALL,数据集对应的表中的数据,都删除 
  • 响应代码:200(成功),404(找不到),500(服务器内部错误),403(没有权限)
  • 响应消息:success,not found, error, access deny URL:你请求的链接 
  • 比如: 
    int a=1,b=2; 
    if(a=b){ 
    print("hello"); 
  • 在编程中,往往是:非0即为真,就因为这种错误,据说:当时的阿波罗航天飞机爆炸,跟这个有关系 
  • 程序员确实干过很多高风险的事儿,比如前段时间:XX删库事件 rm -rf * 
  • 在信息安全等级比较高的公司,一般人没有 rm权限 
  • 如果将来你们当老总,一定记得,不要相信你的员工会帮你考虑所有隐患
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Lyrelion

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值