用Rules来控制JUnit的执行

本文主要依据以下几篇介绍及个人理解所整理,转载请注明,发现错误请指出,谢谢。

JUnit Rules: http://wiki.alfresco.com/wiki/JUnit_Rules

Using Rules to Influence JUnit Test Execution:http://cwd.dhemery.com/2010/12/junit-rules/


JUnit Rule目的

JUnit Rules是最新加入到JUnit库中的,是setUp() tearDown()方法及最新的@Before、@After标记的演化产品。它能够实现@Before、@After标记所能实现的所有功能,并且还有所扩展。总结起来,Rules主要用以以下目的:

  1. 在运行测试之前,能够得到测试名以做一些需要的处理
  2. 指导Swing来运行测试
  3. 对测试失败的case加入额外信息作为参考,尤其对于selenium有作用,如抓屏

认识JUnit Rule

JUnit Rule主要包含三要素,运行测试的语句、选择需要运行哪些语句的规则以及@Rule标记。

在加入了@Rule后JUnit按如下流程运行测试:

  1. 创建默认语句运行测试
  2. 找出测试类中所有的标记了@Rule的public的成员规则
  3. 调用Rule中的apply()方法并告诉该方法所要运行的测试类和测试方法以及JUnit所收集到的语句。apply()方法决定怎么来运行测试,选择或者创建语句来运行测试并返回相应的语句传给JUnit。然后JUnit把语句传给下一个rule的apply方法,如此循环直到最后一条规则。
  4. 调用最后一条Rule返回的语句的evaluate()来运行测试

如何写JUnit Rule

JUnit比较之前的版本用的主要是MethodRule,后面改用TestRule,下面以实际例子来展现如何撰写TestRule并加入到Test类中。

class DemoTestRule implements TestRule{
    public Statement apply(final Statement base,
                           final org.junit.runner.Description description) {
        return new Statement(){
            @Override
            public void evaluate() throws Throwable{
                try{
                    base.evaluate();
                }
                catch(Throwable t){
                    System.out.println("Test rule suggest that "+description.getMethodName()+" failed");
                    throw t;
                }
            }
        };
    }
}
上面已经定义了一样例TestRule,那么它如何用在Test类中呢,下面的代码可以很好的解释:

public class MathTest {
	
	@Rule
	public TestRule testRule = new DemoTestRule();
	
	public MathTest(){
		System.out.println("Create MathTest instance ...");
	}

	@BeforeClass
	public static void setUpBeforeClass() throws Exception {
		System.out.println("Call @BeforeClass");
	}
	
	@AfterClass
	public static void tearDownAfterClass() throws Exception {
		System.out.println("Call @AfterClass");
	}
	
	@Before
	public void setUp() throws Exception {
		System.out.println("Call @Before before a test case!");
	}

	@After
	public void tearDown() throws Exception {
		System.out.println("Call @After after a test case!");
	}

	@Test
	public void testAbs() {
		Math math = new Math();
        assertEquals(200, math.abs(200));
        assertEquals(100, math.abs(-100));
        assertEquals(0, math.abs(0));
	}

	@Test
	public void testDiv() {
		Math math = new Math();
		assertEquals(2,math.div(9, 4));
		assertEquals(5,math.div(100, 20));
	}

	@Test
	public void testExp() {
		 Math math = new Math();
		 assertEquals(32f, math.exp(2, 5), 0.001f);
	     assertEquals(1f, math.exp(2, 0), 0.001f);
	     assertEquals(0.5f, math.exp(2, (-1)), 0.001f);   
	}
	
	@Ignore("Not for the test class")
	@Test(timeout=1)
	public void testTimeLimitedExceeded() {
		double d = 0;
		for(int i = 0;i < 10000000; i ++)
			d += i;
	}
	
	@Test(expected=ArithmeticException.class)
	public void testDivByZero() {
		System.out.println("Started test divided by 0...");
		new Math().div(1, 0);
	}
	
	public static void main(String args[]){
		JUnitCore junitCore = new JUnitCore();
		junitCore.addListener(new RunListener() {
			public void testStarted(Description description) throws Exception {
				System.out.println(description.getDisplayName() + "...started");
			}
			public void testIgnored(Description description) throws Exception {
				System.out.println(description.getDisplayName() + "...failed");
			}
			});
		Result result = junitCore.runClasses(MathTest.class);
		for(Failure failure : result.getFailures())
			System.out.println(failure.getTestHeader()+":"+failure.getMessage());
	}

}

我们可以看到,只需要在Test类的开始用annotation @Rule来标记一个TestRule的声明及初始化即完成了。在运行过程中,我们明显能够发现当测试失败的时候DemoTestRule中的提示信息就会输出。


附Math.java文件

public class Math {
	public int abs(int a){
		if(a >= 0)return a;
		else return -a;
	}
	public int div(int a,int b){
		return a/b;
	}
	public float exp(int a,int b){
		float r = 1;
		for(int i = 0;i < b;i ++)
			r *= a;
		return r;
	}
}

利用JUnit Rule和Selenium抓截屏

在进行网页UI测试时候,往往我们没有时间去跟踪测试过程。在自动化测试过程中,什么地方出错了,错误是什么样子对于我们来分析是产品问题还是代码问题很有帮助。可是往往光靠提示的日志信息往往不足以让我们得到分析结果。于是我们就可以利用selenium的captureScreenShot来抓屏,而且结合TestRule,设置规则当failure后触发该动作。

class ScreenshotTestRule implements TestRule{
   
    protected Selenium selenium;
    protected String filePath="/home/user";
    public ScreenshtTestTule(Selenium selenium){
    	this.selenium = selenium;
    }
    public ScreenshtTestTule(Selenium selenium,String path){
    	this.selenium = selenium;
    	this.filePath = path;
    }
    public Statement apply(final Statement base,
                           final org.junit.runner.Description description) {
        return new Statement(){
            @Override
            public void evaluate() throws Throwable{
                try{
                    base.evaluate();
                }
                catch(Throwable t){
                    selenium.captureScreenshot(filePath+description.getMethodName()+".png");
                    System.out.println("Test rule suggest that "+description.getMethodName()+" failed");
                    throw t;
                }
            }
        };
    }
}




  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值