JUnit学习笔记(一):基本用法

时间:2022-06-30 05:07:19
JUnit学习笔记(一):基本用法



    JUnit是Java的单元测试框架。JUnit提倡“先测试后编码”的理念,强调建立测试数据的代码,可以先测试,再应用。
框架的特点
    JUnit是
开放的资源框架,用于编写和运行测试;
    提供注释来识别测试的方法;
    提供断言来测试预期结果;
    提供测试运行来运行测试;

单元测试用例的特点
    预期输入和预期输出。预期输入需要有测试的前置条件,预期输出需要有测试的后置条件;
    每一项需求至少需要两个单元测试用例:一个正向验证(是否做了该做的事),一个负向验证(是否做了不该做的事)。
    若一个需求有子需求,每一个子需求必须至少有正向验证和负向验证两个测试用例。负向用例可以有多个;
API     官网API地址:http://junit.org/junit4/javadoc/latest/index.html     核心包junit.frameworkjunit.runner。Framework包-->整个测试对象的构架,Runner-->测试驱动;
    JUnit的四个核心类:TestCaseTestSuiteTestRunnerTestResult
TestResult: 测试结果。收集TestCase所执行的结果,将结果分为两类,可预测的Failure和没有预测的Error。同时将测试结果                      转发到TestListener(该接口由TestRunner继承)处理;
TestRunner: 测试运行器。对象调用的起始点,对整个测试流程的跟踪。能显示返回的测试结果,并且报告测试的进度;
TestSuite: 测试集合。包装和运行所有的TestCase;
TestCase: 测试用例。测试类所要继承的类,测试时对被测试类进行初始化,及测试方法调用;


重要的接口:Test和TestListener     Test的主要方法:run()和countTestCases();
    TestListener的主要方法:addError()、addFailure()、startTest()和endTest();

基本的测试过程         TestClass.class(被测试类)-->TestCase(测试用例)-->TestSuite(测试用例集合)-->TestRunner(测试运行器)-->TestResult(测试结果)
例子:
public class Message { //被测试类

private String message = null;
public boolean isPrint = false;

public Message(String message) {
this.message = message;
}

public String printMessage() { // method1-->case1
System.out.println(message);
this.isPrint = true;
System.out.println(this.isPrint + "...");
return this.message;
}

public String changeMessage(String str) { // method2-->case2
this.message += str;
return this.message;
}

public String handleMessage(String str){ // method3-->case3
int a = str.length();
if(a>=5){
this.message = str.substring(0, 5);
}

return this.message;
}
}


public class MessageTestCase1 { //测试用例1

String info = "new String";
Message m = new Message(info);

@Test
public void test1() {
m.printMessage();
assertEquals(true, m.isPrint);
}

@Test
public void test2() {
m.printMessage();
assertEquals(false, m.isPrint);
}
}


public class MessageTestCase2 { //测试用例2

String s = "aa";
Message m = new Message(s);

@Test
public void test1(){
String str = "aazz";
assertEquals(str,m.changeMessage("zz"));
}

@Test
public void test2(){
String str = "asdf";
assertEquals(str,m.changeMessage(str));
}
}


public class MessageTestCase3 { //测试用例3

String str = "abcdefgh";
Message m = new Message("a");

@Test
public void test1(){
assertEquals(5,m.handleMessage(str).length());
}

@Test
public void test2(){
assertEquals(4,m.handleMessage(str).length());
}

@Test
public void test3(){
assertEquals(6,m.handleMessage(str).length());
}
}


@RunWith(Suite.class)
@Suite.SuiteClasses({ MessageTestCase1.class, MessageTestCase2.class,
MessageTestCase3.class })

public class MessageTestSuite { //测试用例集

//public static void main(String[] args) {
//
//TestSuite suite = new TestSuite(MessageTestCase1.class,
//MessageTestCase2.class,MessageTestCase3.class);
//
//TestResult result = new TestResult();
//suite.run(result);
//
//}
}


public class MessageTestRunner { //测试执行器

public static void main(String[] args) {

Result result = JUnitCore.runClasses(MessageTestSuite.class);
for (Failure failure : result.getFailures()) {
System.out.println(failure.toString());
}
System.out.println("TestResult:" + result.wasSuccessful());
}
}




Ignoring Tests     含有@Ignore注释的测试方法将不会被执行;
    用@Ignore注释的测试类,它的测试方法将不会执行;

例子:
@Ignore("冗余测试用例")
@Test
public void test3(){
assertEquals(6,m.handleMessage(str).length());
}


Timeout for Tests
   设置超时时间,对用例执行时间进行控制。    第一种用法:
@Test(timeout=10000)
public void test2(){
assertEquals(4,m.handleMessage(str).length());
}

    第二种用法(设置超时规则。写在测试类中,测试类中的所有测试方法均遵守此规则):
@Rule
public Timeout globalTimeout = Timeout.seconds(10);


Exception Testing
    测试代码是否抛出预想的异常。 例子:
Class.forName("jdbc.mysql.Driver");

@Test(expected = ClassNotFoundException.class)
public void test1() {
Class.forName("jdbc.mysql.Driver");
}


Parameterized Tests

    参数化测试允许使用不同的值反复运行同一个测试。可以按照以下步骤来创建参数化测试:
用 @RunWith(Parameterized.class) 来注释 test 类;
创建一个由 @Parameters 注释的公共的静态方法,它返回一个对象的集合(数组)来作为测试数据集合; 创建一个公共的构造函数,它接受和一行测试数据相等同的东西; 为每一列测试数据创建一个实例变量;
用实例变量作为测试数据的来源来创建你的测试用例;


例子:
public class Test123 { //被测试类

private Integer a;
private Integer b;

public int add(int a, int b) { //
return a + b;
}
}

@RunWith(Parameterized.class)
public class TestCase { //使用参数化的 测试用例

private Integer input1;
private Integer input2;
private Integer result;

public TestCase(Integer a, Integer b, Integer c) {
this.input1 = a;
this.input2 = b;
this.result = c;
}

@Parameters
public static Collection addNumbers() {
return Arrays.asList(new Object[][] { { 1, 2, 3 }, { -6, -3, -9 },
{ 1, -6, -5 }, { 2, 0, 6 }, { 99, 9, 108 } });
}

@Test
public void test1() {

Test123 t =new Test123();
assertEquals(result.intValue(), t.add(input1, input2));
}
}




Rules
@ClassRule
public static Service service = Service.getInstance(); //必须是静态的

@Rule
public Service tmp = service;

@ClassRule:set up the external resource in your example.
@Rule:resetting the resource in that example.













     参考:           http://wiki.jikexueyuan.com/project/junit/           http://junit.org/junit4/           http://*.com/questions/20767486/combining-classrule-and-rule-in-junit-4-11
注: