1.Junit安装
Placethe JUnit jar file where accessible: (examples)
Linux:/opt/java/lib/ or /usr/java/latest/lib/
MS/Windows:C:\Java\lib\ or C:\Program Files\Java\jdk1.6.0_26\lib\
2.导入Junit包:
选中java工程,点击鼠标右键--->选择properties---->在窗口中选JavaBuildPath---->在右侧点击Add Library---->在弹出的窗口列表中选中Junit---->下一步----->Junit4(我用的是Junit 4)---->finish
这样Junit 4包就导完了。
3.创建Junit测试类:(IBM的介绍很详细 https://www.ibm.com/developerworks/cn/java/j-lo-springunitest/)
右键要测试的文件--->New--->Others-->JUnit Test Case-->填写文件名称,勾选Setup()等-->Next-->勾选文件中要测试的类-->Finsh
@Before | 每个测试方法执行之前调用 |
@After | 每个方法执行之后调用 |
@Test 参数一:timeout 参数二:expected | 测试方法声明 毫秒,超时时间@Test(timeout = 1000 ) NullPointerException.class |
@Ignore | 测试跳过的方法 |
@BeforeClass | 只在测试用例初始化时候执行 |
@AfterClass | 所有测试执行完毕后 |
expected | 期望抛出异常 @Test(expected = ArithmeticException. class ) |
@RunWith | 设置运行代码方式 @RunWith(TestClassRunner. class ) |
@Parameters | 设置参数 |
@Rule | 允许灵活添加或重新定义测试类中的每个测试方法的行为 |
@FixMethodOrder | 指定测试方法的执行顺序 |
@Transaction | 每个测试类都要有这个,回滚测试用例,不用担心测试会改变数据库之类的 |
@Repeat | 设置重复次数,很有用的,不用自己写for循环, @Repeat(3) |
@ActiveProfiles("test") | 加载bean中的test实例 |
4.Assert:确保自己使用的第一个参数为String类型的签名,这个参数让你可以在断言失败的时候提供一个有意义的文本描述。
assertArrayEquals(expecteds, actuals) | 查看两个数组是否相等。 |
assertEquals(expected, actual) | 查看两个对象是否相等。类似于字符串比较使用的equals()方法 |
assertNotEquals(first, second) | 查看两个对象是否不相等。 |
assertNull(object) | 查看对象是否为空。 |
assertNotNull(object) | 查看对象是否不为空。 |
assertSame(expected, actual) | 查看两个对象的引用是否相等。类似于使用“==”比较两个对象 |
assertNotSame(unexpected, actual) | 查看两个对象的引用是否不相等。类似于使用“!=”比较两个对象 |
assertTrue(condition) | 查看运行结果是否为true。 |
assertFalse(condition) | 查看运行结果是否为false。 |
assertThat(actual, matcher) | 查看实际值是否满足指定的条件 |
fail() | 让测试失败 |
@RunWith | value=org.junit.internal.runners.JUnit38ClassRunner.class |
运行器 | 目的 |
org.junit.internal.runners.JUnit38ClassRunner | 这个运行器包含在当前的JUnit版本中,仅仅是为了向后兼容,它将测试用例作为Junit3.8的测试用例来启动 |
org.junit.runners.JUnit4 | 这个运行器将测试用例作为Junit4的测试用例来启动 |
org.junit.runners.Parameterized | 这个运测试运行器可以使用不同的参数来运行相同的测试集 |
@RunWith(value=org.junit.runners.Suite.calss) @suiteClasses(value={FolderConfigurationTest.class,FileConfigurationTest.class}) public class FileSystemConfigurationTestSuite{} | 将测试类组合为一个suite |
5.controller组件:
接受请求;
根据请求执行任意常用计算;
选择一个合适的请求处理器;
路由请求,以便处理可以执行相关的业务逻辑;
可能提供一个顶层处理器来处理错误和异常;
四个对象:Request、Response、RequestHandler和Controller。
解决组件的基本要求:
需求 | 解决方法 |
接受请求 | public Response processRequest(Request request) |
选择处理器 | this.requestHandlers.get(request.getName()) |
路由请求 | response = getRequestHandler(request).process(request); |
错误处理 | 子类化ErrorResponse |
领域对象(Domain Object) | 对比和比较用于应用程序中的对象与用来测试应用程序的对象 |
测试对象(Test Object) | 用来与被测对象交互的 |
诊断测试(diagnostic test) | 监测应用程序 |
6.重构:改善已有代码的设计
7.Hamcrest简化断言:(http://code.google.com/p/hamcrest/)
import staticorg.hamcrest.CoreMatchers.anyof;
importstatic org.hamcrest.CoreMatchers.equalTo;
@Test
publicvoid testWithHamcrest(){
assertThat(values,hasItem(anyOf(equalTo("one"),equalTo("two"),equalTo("three"))));
}
8.一些常用的Hamcrest匹配器 |
|
核心 | 逻辑 |
anything | 绝对匹配 |
is | 仅用于改善语句的可读性 |
allOf | 检查是否与所有包含的匹配器匹配(&&) |
anyOf | 检查是否与任一包含的匹配器匹配(||||) |
not | 与包含的匹配器意思相反 |
instanceOf、isCompatibleType | 匹配对象是否是兼容类型(是另一个对象的实例) |
sameInstance | 测试对象标识 |
notNullValue、nullValue | 测试null值和非null值 |
hasProperty | 测试JavaBean是否具有某种属性 |
hasEntry、hasKey、hasValue | 测试给定的Map是否含有某个给定的实体、键或者值 |
hasItem、hasItems | 测试给定的集合包含了一个或者多个元素 |
closeTo、greaterThan、greaterThanOrEqual、lessThan、lessThanOrEqual | 测试给定的数字是否接近于,大于、大于等于、小于、小于等于某个给定的值 |
equalToIgnoringCase | 通过忽略大小写,测试给定的字符串是否与另一个字符串相同 |
equalToIgnoringWhiteSpance | 通过忽略空格,测试给定的字符串是否与另一个字符串相同 |
containsString、endsWith、startWith | 测试给定的字符串是否包含了某个字符串,是否以某个字符串结尾或者开始 |
9.三种单元测试
测试类型 | 描述 |
逻辑单元测试 | 针对一个单独的方法来检查代码,你可以通过mock objects或者stub来控制某个特定的测试方法的边界 |
集成单元测试 | 用来测试在这是环境中的不同组件之间的相互作用 |
功能单元测试 | 确认一个刺激响应 |
10.Cobertura:可以与Ant和Maven集成,通过命令行调用
可以生成HTML或者XML格式的报告,生成覆盖率的百分比
11.stub:粗粒度,相当于集成测试
下面是一些具体的编写测试代码的技巧或较好的实践方法:
1. 不要用TestCase的构造函数初始化Fixture,而要用setUp()和tearDown()方法。
2.不要依赖或假定测试运行的顺序,因为JUnit利用Vector保存测试方法。所以不同的平台会按不同的顺序从Vector中取出测试方法。
3.避免编写有副作用的TestCase。例如:如果随后的测试依赖于某些特定的交易数据,就不要提交交易数据。简单的回滚就可以了。
4.当继承一个测试类时,记得调用父类的setUp()和tearDown()方法。
5.将测试代码和工作代码放在一起,一边同步编译和更新。(使用Ant中有支持junit的task.)
6.测试类和测试方法应该有一致的命名方案。如在工作类名前加上test从而形成测试类名。
7.确保测试与时间无关,不要依赖使用过期的数据进行测试。导致在随后的维护过程中很难重现测试。
8.如果你编写的软件面向国际市场,编写测试时要考虑国际化的因素。不要仅用母语的Locale进行测试。
9.尽可能地利用JUnit提供地assert/fail方法以及异常处理的方法,可以使代码更为简洁。
10.测试要尽可能地小,执行速度快。
11.不要硬性规定数据文件的路径。
12.利用Junit的自动异常处理书写简洁的测试代码
事实上在Junit中使用try-catch 来捕获异常是没有必要的,Junit 会自动捕获异常。那些没有被捕获的异常就被当成错误处理。
13. 充分利用Junit的assert/fail 方法
assertSame()用来测试两个引用是否指向同一个对象
assertEquals()用来测试两个对象是否相等
14. 确保测试代码与时间无关
15. 使用文档生成器做测试文档。
JUnit和ant结合
ant 提供了两个 target :junit 和 junitreport 运行所有测试用例,并生成html 格式的报表
具体操作如下:
1.将 junit.jar 放在ANT_HOMElib 目录下
2.修改 build.xml ,加入如下内容:
-------------- Oneor more tests failed, check the report for detail...-----------------------------
运行 这个 target ,ant会运行每个 TestCase,在 report 目录下就有了 很多 TEST*.xml 和 一些网页打开 report 目录下的 index.html就可以看到很直观的测试运行报告,一目了然。
在Eclipse中开发、运行JUnit测试相当简单。因为Eclipse本身集成了JUnit相关组件,并对JUnit的运行提供了无缝的支持。
示例1:参数化
@RunWith(Parameterized.class)
public class FibonacciTest {
@Parameters(name = "{index}:fib({0})={1}")
public static Iterable<Object[]>data() {
return Arrays.asList(new Object[][]{ { 0, 0 }, { 1, 1 }, { 2, 1 },
{ 3, 2 }, { 4, 3 }, { 5, 5}, { 6, 8 } });
}
private int input;
private int expected;
public FibonacciTest(int input, intexpected) {
this.input = input;
this.expected = expected;
}
示例2:打包测试
方法一:
package test;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
import org.junit.runners.Suite.SuiteClasses;
@RunWith(Suite.class)
@Suite.SuiteClasses({ AssertTests.class, FibonacciTest.class, JDemoTest.class })
public class AllCaseTest {
}
方法二:
import junit.framework.JUnit4TestAdapter;
import junit.framework.Test;
import junit.framework.TestSuite;
public static Test suite() {
TestSuite suite = new TestSuite();
suite.addTest(new JUnit4TestAdapter(LoginControllerTest.class));
return suite;
}
示例3:异常测试
@Rule public ExpectedException thrown = ExpectedException.none();
@Test
public void shouldTestExceptionMessage() throws IndexOutOfBoundsException {
List<Object> list = new ArrayList<Object>();
thrown.expect(IndexOutOfBoundsException.class);
thrown.expectMessage("Index: 0, Size: 0");
list.get(0);
Assert.assertEquals(1, list.get(0));
}
示例4:限时测试
@Rule
public Timeout globalTimeout = new Timeout(10000); // 10 seconds max per method tested
@Test
public void testInfiniteLoop1() {
log += "ran1";
for (;;) {
}
}