410 likes | 663 Views
Junit , CodeCover & CFG. 刘子 聪 lzc10@software.nju.edu.cn. 内容. 单元测试 Junit 静态控制流图模型 CFG Generator 覆盖率报告 CodeCover 作业说明. JUnit. JUnit 测试是程序员测试,即所谓白盒 测试 继承 TestCase 类即可利用 JUnit 测试. JUnit. 需要 知道程序结构以及逻辑 设计不同的测试输入以及输出预言 尽可能覆盖多的语句以及分支. Junit 安装及配置. 要安装和使用 JUnit 是很容易的,只需三个步骤:
E N D
Junit, CodeCover & CFG 刘子聪 lzc10@software.nju.edu.cn
内容 • 单元测试 Junit • 静态控制流图模型 CFG Generator • 覆盖率报告 CodeCover • 作业说明
JUnit • JUnit测试是程序员测试,即所谓白盒测试 • 继承TestCase类即可利用JUnit测试
JUnit • 需要知道程序结构以及逻辑 • 设计不同的测试输入以及输出预言 • 尽可能覆盖多的语句以及分支
Junit安装及配置 • 要安装和使用JUnit是很容易的,只需三个步骤: • (1)下载JUnit软件; • (2)将JUnit包解开,放到文件系统中; • (3)运行JUnit测试时,将JUnit中的所有*.jar文件放到类路径里。
Junit安装及配置 • http://sourceforge.net/projects/junit/?source=navbar • http://www.junit.org(重定向到Github)
Assert 断言 断言是单元测试最基本的组成部分。Junit程序库提供了如下不同形式的多种断言。 • assertEquals([String message],expected,actual);-是否相等 • Excpected-是你期望得到的值;actual-是被测试代码实际产生的值; • assertNull([String message],Object object);-是否为空
Assert 断言 4. assertNotNull([String message],Object object);-是否不为空 5. assertTrue([String message],boolean condition);-是否为真 6. Fail(String message); 此断言会使测试立即失效,其中message参数是可选的。这种断言通常用于标记某个不应该到达的分支。(例如:在一个预期异常发生的时侯)
Assert断言 • 当一个断言失败了,加上一个简短的消息来通知这个失败的一些属性甚至是失败的原因,可能会带来比较好的效果。 • JUnit框架里,一个断言的方法的第一个参数作为可选项,接受一个“String”类型的参数,包含一些消息,在断言失败的时候显示出来。对于assertTrue( )有2种形式:
对于异常的处理 • 对于测试而言,下面两种异常是我们可能会感兴趣的: • 从测试代码抛出的可预测异常 • 由于某个模块发生严重错误,而抛出的不可预测异常 • 对于Junit而言异常彻头彻尾是一个好东西-它能明确告诉 我们什么地方出错了。例如:有一个名为sortMyList()的方法,如果传入的参数是一个null list,那么我们希望方法能抛出一个异常。在Junit中我们可以显式地针对这一点进行测试。
对于异常的处理 Public class TestException extends TestCase{ Public void testForException(){ try{ sortMyList(null); //特意传入null,看测试结果 Fail(“需要抛出一个异常!”); }catch(RuntimeException e){ assertTrue(true) //如果有异常抛出则应到执行此语句 } } }
测试的技巧 • 大量测试数据 • 典型错误类型 • 强制产生错误条件
大量测试数据 对于有大量的测试数据的测试,可以通过数据文件来存储这些测试数据,然后让单元测试读取该文件,从而提高测试的完整性和效率。
典型错误类型 注:找边界条件是做单元测试最有价值的工作之一,因为bug一般就 出现在边界上。 常见的边界条件有如下一些: • 完全伪造一个不一致的输入数据,例如:“!·#¥%……—……*%—”; • 格式错误的数据,例如没有顶层域名的电子邮件地址,象abc@yahoo; • 空值或者不完整的值(如0,0.00,””和null); • 一些与意料中的合理值相去甚远的数值。例如一个人岁数1000岁; • 如果要求是一个不允许出现重复数值的list,但是传入的是一个存在重复数值的list; • 事情到达的次序是错误的,或者碰巧和期望的次序不一致。例如:在未登录系统之前,就尝试打印文件;
强制产生错误 在真实世界,错误总是会发生:磁盘会满,网络连接会断开,电子邮件会多得会塞满整个邮箱,而程序是会崩溃的。所以我们应当能够通过强制引发错误,来测试代码中是如何处理所有这些真实世界中的问题的。 我们常用的手段可以通过提供一些无效的参数来进行模拟错误,但是对于象网络连接断开这类型错误,我们可能需要借鉴一些其它手段或工具(如Mock对象等)
JUnit简单例子 源程序:
JUnit简单例子 测试程序:
JUnit简单例子 启动JUnit:
JUnit简单例子 测试结果:
CFG Generator 观察结构 • CFG —— Control Flow Graph • 观察程序的控制流走向 • 我们的目的就是尽量走遍每一条路线
CFG Generator • 安装地址 • http://eclipsefcg.sourceforge.net • “Help”->”Install New Software…”->输入地址
CFG Generator • 例子:
CFG Generator • 控制流图
CodeCover • 用来统计测试覆盖率,支持多种覆盖(包括语句覆盖、分支覆盖、MCDC覆盖等)
使用CodeCover统计覆盖率 • http://update.codecover.org/ • 使用上面这个地址安装eclipse插件
使用CodeCover统计覆盖率 • 查看结果
作业要提交的内容 • 每个程序一个Eclipse项目包 • 其中包含可以使用Junit运行的测试用例 • 所有的测试用例写在一个.java文件之中
作业要提交的内容 • 每个测试用例需要加上注释,说明其作用,比如加上注释后,使用Javadoc产生接口文档,提交之。
Java Doc生成 • 右击项目,选择Export • 选择Javadoc
Java Doc生成 • Javadoc command: • 选择jdk的bin/javadoc.exe • 生成的doc在工程目录下doc文件夹下
评分标准 • 覆盖率 • 语句覆盖、分支覆盖、条件覆盖。。。 • 测试用例说明
附:JUnit3、4对照 • 在网上的教程好多是基于JUnit3的(比如继承TestCase类),JUnit3与4的区别都有哪些?
JUnit4 • 取消用反射机制来命名定位测试,而采用JDK的注释机制。方法命名更加多样! @Test public void additionTest() { int z = x + y; assertEquals(2, z); }
JUnit4 • 不需要继承TestCase类,只需要使用JDK中的static import。 import static org.junit.Assert.assertEquals; … @Test public void addition() { int z = x + y; assertEquals(2, z); }
JUnit4 • 新的setUp()和tearDown()。 • 在Junit4中不再使用setUp()和 tearDown()来完成测试前后的准备和清除工作,而是采用: • @Before,@After:标识需要在每个测试方法前后需要进行的操作。 • @BeforeClass,@AfterClass:标识需要在测试类前后进行的操作。
JUnit4 • 异常测试 Junit4 @Test(expected=ArithmeticException.class) public void divideByZero() { int n = 2 / 0; } • 如果该异常没有抛出(或者抛出了一个不同的异常),那么测试就将失败。 • 异常测试 old Junit try { int n = 2 / 0; fail("Divided by zero!"); } catch (ArithmeticException success){ assertNotNull(success.getMessage()); }
JUnit4 • 如果需要忽略某个测试的时候,可以采用这个标识@Ignore,当使用文本界面时,会输出一个“I”(代表 ignore)。 • 标识@Test(timeout=500)可以帮助解决单元测试的一些性能问题。 • Assert判断方法精简,并添加了: public static void assertEquals(Object[] expected, Object[] actual) public static void assertEquals(String message, Object[] expected, Object[] actual) • 为数组的比较提供了方便。