Rules允許非常靈活地新增或重新定義一個測試類中每個測試方法的行為。測試人員可以重複使用或擴充套件下面提供的Rules之一,或編寫自己的Rules。
TestName Rule使當前的測試名稱在測試方法中可用。用於在測試執行過程中獲取測試方法名稱。在starting()中記錄測試方法名,在getMethodName()中返回
例如:
import static org.junit.Assert.*;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TestName;
public class NameRuleTest {
@Rule
public final TestName name = new TestName();
@Test
public void testA() {
assertEquals("testA", name.getMethodName());
}
@Test
public void testB() {
assertEquals("testB", name.getMethodName());
}
}
TemporaryFolder Rule允許建立檔案和資料夾,這些檔案和資料夾在測試方法結束時被刪除(無論通過還是失敗)。預設情況下,如果資源不能被刪除,則不會丟擲異常。
import java.io.*;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
public class HasTempFolder {
@Rule
public TemporaryFolder folder= new TemporaryFolder();
@Test
public void testUsingTempFolder() throws IOException {
File createdFile = folder.newFile("myfile.txt");
File createdFolder = folder.newFolder("subfolder");
// ...
}
}
ExternalResource是一個規則(如TemporaryFolder)的基礎類別,它在測試前設定了一個外部資源(一個檔案、通訊端、伺服器、資料庫連線等),並保證在測試後將其拆除。
可以設定測試前後需要做的事情(比如:檔案、socket、服務、資料庫的連線與關閉)。
public static class UsesExternalResource {
Server myServer = new Server();
@Rule
public ExternalResource resource = new ExternalResource() {
@Override
protected void before() throws Throwable {
myServer.connect();
};
@Override
protected void after() {
myServer.disconnect();
};
};
@Test
public void testFoo() {
new Client().run(myServer);
}
}
ErrorCollector這個Rule,在出現一個錯誤後,還可以讓測試繼續進行下去。
他提供三個方法:
前面兩個是用來處理斷言的,最後一個是新增錯誤至錯誤列表中。
看下面例子:
package mytest;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
import java.util.concurrent.Callable;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ErrorCollector;
public class JUnitCoreErrorControllerRuleTest {
private final int multiplesOf2[] = { 0, 2, 4, 7, 8, 11, 12 };
@Rule
public ErrorCollector errorCollector = new ErrorCollector();
/*
* 下面這個測試,會報告兩個failures。這一點和下面的checkSucceeds測試不同
*/
@Test
public void testMultiplesOf2() {
int multiple = 0;
for (int multipleOf2 : multiplesOf2) {
// Will count the number of issues in this list
// - 3*2 = 6 not 7, 5*2 = 10 not 11 : 2 Failures
errorCollector.checkThat(2 * multiple, is(multipleOf2));
multiple++;
}
}
/*
* 下面程式碼中有兩個斷言會失敗,但每次執行JUnit框架只會報告一個。這一點和上面的checkThat測試不同,可以對比一下。
*/
@Test
public void testCallableMultiples() {
errorCollector.checkSucceeds(new Callable<Object>() {
public Object call() throws Exception {
assertThat(2 * 2, is(5));
assertThat(2 * 3, is(6));
assertThat(2 * 4, is(8));
assertThat(2 * 5, is(9));
return null;
}
});
}
/*
* 下面執行時,會報告2個錯誤
*/
@Test
public void testAddingAnError() {
assertThat(2 * 2, is(4));
errorCollector.addError(new Throwable("Error Collector added an error"));
assertThat(2 * 3, is(6));
errorCollector.addError(new Throwable(
"Error Collector added a second error"));
}
}
執行結果:
Failed tests:
testCallableMultiples(mytest.JUnitCoreErrorControllerRuleTest):
Expected: is <5>
but: was <4>
testMultiplesOf2(mytest.JUnitCoreErrorControllerRuleTest):
Expected: is <7>
but: was <6>
testMultiplesOf2(mytest.JUnitCoreErrorControllerRuleTest):
Expected: is <11>
but: was <10>
Tests in error:
testAddingAnError(tangzhi.mytest.JUnitCoreErrorControllerRuleTest): Error Collector added an error
testAddingAnError(tangzhi.mytest.JUnitCoreErrorControllerRuleTest): Error Collector added a second error
從這個例子,可以看出:
如果,你想在每個測試之後,甚至是在@After之後,想檢查些什麼,就可以使用Verifier這個Rule.
看例子:
private static String sequence;
public static class UsesVerifier {
@Rule
public Verifier collector = new Verifier() {
@Override
protected void verify() {
sequence += " verify ";
}
};
@Test
public void example() {
sequence += "test";
}
@Test
public void example2() {
sequence += "test2";
}
@After
public void after() {
sequence += " after";
}
}
@Test
public void verifierRunsAfterTest() {
sequence = "";
assertThat(testResult(UsesVerifier.class), isSuccessful());
assertEquals("test after verify test2 after verify ", sequence);
}
從上面例子可以看出:Verifier#verify針對每個測試都會執行一次,並且執行在@After步驟之後。
需要說明:如果某測試出現失敗(fail),那麼這個測試之後就不會做verify,這一點,可以結合下面的例子看出
對測試的每個步驟進行監控。
看例子:
package tangzhi.mytest;
import static org.junit.Assert.*;
import static org.hamcrest.CoreMatchers.*;
import org.junit.After;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TestRule;
import org.junit.rules.TestWatcher;
import org.junit.rules.Verifier;
import org.junit.runner.Description;
import org.junit.runners.model.Statement;
public class WatchmanTest {
private static String watchedLog;
@Rule
public TestRule watchman = new TestWatcher() {
@Override
public Statement apply(Statement base, Description description) {
Statement s = super.apply(base, description);
watchedLog="";
System.out.println("watch apply.");
return s;
}
@Override
protected void succeeded(Description description) {
watchedLog += description.getDisplayName() + " " + "success!";
System.out.println("watch succeed:"+watchedLog);
}
@Override
protected void failed(Throwable e, Description description) {
watchedLog += description.getDisplayName() + " " + e.getClass().getSimpleName();
System.out.println("watch failed:"+watchedLog);
}
@Override
protected void starting(Description description) {
super.starting(description);
System.out.println("watch starting.");
}
@Override
protected void finished(Description description) {
super.finished(description);
System.out.println("watch finished.");
}
};
@Rule
public Verifier collector = new Verifier() {
@Override
protected void verify() {
System.out.println("@Verify:"+watchedLog);
}
};
@Test
public void fails() {
System.out.println("in fails");
assertThat("ssss", is("sss"));
}
@Test
public void succeeds() {
System.out.println("in succeeds");
}
@After
public void after() {
System.out.println("@After");
}
}
對於新增了TimeoutRule 的測試類,當測試類中的測試方法執行超過TimeoutRule 設定的時間時,測試方法執行就會被標記為失敗
public class TimeoutRuleTest {
@Rule
public Timeout globalTimeout = Timeout.seconds(5);
@Test
public void timeout() throws InterruptedException {
TimeUnit.SECONDS.sleep(10);
}
@Test
public void onTime() throws InterruptedException {
TimeUnit.SECONDS.sleep(2);
}
}
執行上面測試用例,onTime方法執行通過,timeout()方法則丟擲TestTimedOutException:
org.junit.runners.model.TestTimedOutException: test timed out after 5 seconds
還有很多Rule就不一一介紹了