Junit的扩展

TestListener

用来收集测试结果,并以某种方式输出,比如ResultPrinter,用来打印测试的结果,失败数,成功数

/**
     * @see junit.framework.TestListener#addError(Test, Throwable)
     */
    public void addError(Test test, Throwable e) {
        getWriter().print("E");
    }

    /**
     * @see junit.framework.TestListener#addFailure(Test, AssertionFailedError)
     */
    public void addFailure(Test test, AssertionFailedError t) {
        getWriter().print("F");
    }

然后,在TestResult中会有一组listener和failures

public class TestResult {
    protected List<TestFailure> fFailures;
    protected List<TestFailure> fErrors;
    protected List<TestListener> fListeners;
    protected int fRunTests;
    private boolean fStop;
}

那么为什么要这么设计呢?这是为了可扩展性,不同的Listener各自相互独立,而测试引发的错误,将会分别被发送给不同的Listener,这样我们便可以自己定义Listener,来接收错误信息,并以自己想要的方式来展示结果。

"目前,已有文本界面、图形界面和 Eclipse 集成组件三种监听器,用户完全可以开发符合接口的更强大的监听器。"

其实idea的用法都是点个按钮,就触发对应测试,其实运用Junit也可以通过代码,来自己封装如何进行测试,比如,这种测试,我们自己的灵活性更好

import org.junit.runner.JUnitCore;
import org.junit.runner.Result;
import org.junit.runner.notification.Failure;

public class TestRunner {
   public static void main(String[] args) {
      Result result = JUnitCore.runClasses(TestJunit.class);
      for (Failure failure : result.getFailures()) {
         System.out.println(failure.toString());
      }
      System.out.println(result.wasSuccessful());
   }
}

RunListener

这个也主要是方便我们扩展,用来监听测试过程中出现的各种情况,并按我们想要的方式,给出测试中的各种特征,参考 JUnit源码分析 - 扩展 - 自定义RunListener,不过RunListener需要注册到RunNotifier,所谓注册,其实也就是notifier.add(listener)之类的

import java.util.Date;
 
import org.junit.runner.Description;
import org.junit.runner.Result;
import org.junit.runner.notification.Failure;
import org.junit.runner.notification.RunListener;
 
//自定义Listener类,此处的JUnit用例为单一测试类,所以与Suite相关的测试事件不需要覆写
public class MyListener extends RunListener
{
    private long startTime;
    private long endTime;
 
    @Override
    public void testRunStarted(Description description) throws Exception
    {
        startTime = new Date().getTime();
        System.out.println("Test Run Started!");
        System.out.println("The Test Class is " + description.getClassName() + ". Number of Test Case is " + description.testCount());
        System.out.println("===================================================================================");
    }
 
    @Override
    public void testRunFinished(Result result) throws Exception
    {
        endTime = new Date().getTime();
        System.out.println("Test Run Finished!");
        System.out.println("Number of Test Case Executed is " + result.getRunCount());
        System.out.println("Elipsed Time of this Test Run is " + (endTime - startTime) / 1000);
        System.out.println("===================================================================================");
    }
 
    @Override
    public void testStarted(Description description) throws Exception
    {
        System.out.println("Test Method Named " + description.getMethodName() + " Started!");
    }
 
    @Override
    public void testFinished(Description description) throws Exception
    {
        System.out.println("Test Method Named " + description.getMethodName() + " Ended!");
        System.out.println("===================================================================================");
    }
 
    @Override
    public void testFailure(Failure failure) throws Exception
    {
 
        System.out.println("Test Method Named " + failure.getDescription().getMethodName() + " Failed!");
        System.out.println("Failure Cause is : " + failure.getException());
    }
 
    @Override
    public void testAssumptionFailure(Failure failure)
    {
        System.out.println("Test Method Named " + failure.getDescription().getMethodName() + " Failed for Assumption!");
    }
 
    @Override
    public void testIgnored(Description description) throws Exception
    {
        super.testIgnored(description);
    }
}

最后的结果如下,可以看出testRunStarted其实就是标注了类被调用时的会被调用,testStarted就是@Test方法被调用时会被被调用

Test Run Started!
The Test Class is com.junit.test.CalculateTest. Number of Test Case is 10
===================================================================================
Test Method Named testAdd_Negetive Started!
Test Method Named testAdd_Negetive Ended!
===================================================================================
Test Method Named testAdd_Positive Started!
Test Method Named testAdd_Positive Ended!
===================================================================================
Test Method Named testDivide_Negetive Started!
Test Method Named testDivide_Negetive Ended!
===================================================================================
Test Method Named testDivide_Positive Started!
Test Method Named testDivide_Positive Ended!
===================================================================================
Test Method Named testMinus_Negetive Started!
Test Method Named testMinus_Negetive Ended!
===================================================================================
Test Method Named testMinus_Positive Started!
Test Method Named testMinus_Positive Ended!
===================================================================================
Test Method Named testMultiple_Negetive Started!
Test Method Named testMultiple_Negetive Ended!
===================================================================================
Test Method Named testMultiple_Positive Started!
Test Method Named testMultiple_Positive Ended!
===================================================================================
Test Method Named testTimeout Started!
Test Method Named testTimeout Failed!
Failure Cause is : org.junit.runners.model.TestTimedOutException: test timed out after 200 milliseconds
Test Method Named testTimeout Ended!
===================================================================================
Test Run Finished!
Number of Test Case Executed is 9
Elipsed Time of this Test Run is 0
===================================================================================

TestRule和@Rule

其实@Rule是一个,能够完成所有@Before和@After功能,更加强大的注解,不过好像不能取代@BeforeClass和@AfterClass,具体示例可参考JUnit单元测试6—@Rule注解 - 简书

package junit.mytest;

import org.junit.rules.TestRule;
import org.junit.runner.Description;
import org.junit.runners.model.Statement;

public class LoopRule implements TestRule {
    private int loopCount;

    public LoopRule(int loopCount) {
        this.loopCount = loopCount;
    }

    @Override
    public Statement apply(final Statement base, Description desc) {
        return new Statement() {
            @Override
            public void evaluate() throws Throwable {
                for (int i = 1; i <= loopCount; i++) {
                    System.out.println("Loop " + i + " started");
                    base.evaluate();
                    System.out.println("Loop " + i + " finished\n----------------");
                }
            }
        };
    }
}

以及测试类,用来循环调用@Test方法测试两次

package junit.mytest;
import org.junit.Rule;
import org.junit.Test;

public class HelloWorldTest {
    @Rule
    public LoopRule loopRule = new LoopRule(2);

    @Test
    public void testSayHello() {
        System.out.println("helloWorld");
    }
}

FixMethodOrder

用来表明测试方法的执行先后顺序,比如NAME_ASCENDING,按名字先后排序

总结

从上面的一些扩展来看,注解(比如@Rule, @Before)是消除重复的好办法,否则我们得一个逻辑,在不同测试方法重复写多次(比如@Before里的逻辑),而回调(比如TestRule的apply)是扩展的利器

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值