相信不少道友搞開發的通常都會用到Junit單元測試工具,不知道你們有沒有遇到一個這樣的問題:java
有的單元測試用例有不少@Test方法,甚至有的方法會執行很長時間,只能空等執行。而實際上咱們只須要運行其中的某一些方法就能夠了。而後有人會說不是有ingore註解麼,可ingore須要爲許多的方法添加,當測試方法達到必定數量級的時候,改起來會很煩躁,若是commit到代碼服務器上甚至可能會影響別人工做。己所不欲...git
以前有朋友跟我說過TestNG是支持指定執行哪些方法,本人沒有親自去實驗,由於公司統一使用Junit,因此沒打算在這上面花費學習成本,沒有固定測試框架的朋友不妨本身瞭解一下。下面開始擴展:github
下載
spring
實現思路
服務器
一、在正常運行的狀況下,Junit被觸發會調用org.junit.runners.BlockJUnit4ClassRunner類,加載測試類文件,執行before after childrenInvoker等方法,有興趣的道友能夠本身看下這個類的結構,今天的主角是childrenInvoker方法,這個方法調用了測試類文件的@Test方法並執行,咱們要作的就是重寫這個方法,根據咱們本身的規則選擇執行哪些方法。框架
二、根據上一條咱們要擴展一個R我unner繼承自BlockJUnit4ClassRunner,在這裏進行參數過濾。ide
三、咱們可能但願方法能夠模糊匹配,也可能但願能夠指定某幾個固定的寫法,因此須要引入一種過濾規則,這裏採用正則表達式。過濾規則的傳遞採用註解,由於我以爲簡潔,忘記註解使用的朋友能夠點擊這裏。
工具
四、Junit4開始提供了RunWith註解,以便讓用戶自定義擴展Runner,咱們的實現就是基於它的這個特性。比較有名的應該你們都比較熟悉spring的Junit擴展。oop
代碼實現:
一、定義註解
package com.array7.annotations; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) public @interface FilterMethods { String[] methods(); }
二、定義Runner
package com.array7.runner; import java.util.HashSet; import java.util.Set; import java.util.regex.Pattern; import org.junit.runner.notification.RunNotifier; import org.junit.runners.BlockJUnit4ClassRunner; import org.junit.runners.model.FrameworkMethod; import org.junit.runners.model.InitializationError; import org.junit.runners.model.Statement; import com.array7.annotations.FilterMethods; public class SpecialMethodsRunner extends BlockJUnit4ClassRunner { private FilterMethods filter; public SpecialMethodsRunner(Class<?> clazz) throws InitializationError { super(clazz); filter = clazz.getAnnotation(FilterMethods.class); } /** * EnterPoint */ @Override protected Statement childrenInvoker(final RunNotifier notifier) { if (filter == null) { // keep original runner alone. return super.childrenInvoker(notifier); } return new Statement() { @Override public void evaluate() throws Throwable { runMethodsWithFilter(notifier, filter); } }; } /** * Filter the methods could be run. * @param notifier * @param filterMethods */ private void runMethodsWithFilter(final RunNotifier notifier, final FilterMethods filterMethods) { String[] filters = filterMethods.methods(); if (filters == null || filters.length == 0) { throw new IllegalArgumentException( "Wrong parameters!Please check Annotation FilterMthods parameters..."); } Set<Pattern> patternSet = new HashSet<Pattern>(); for (String filter : filters) { patternSet.add(Pattern.compile(filter)); } for (FrameworkMethod method : getChildren()) { for (Pattern pattern : patternSet) { // loop all patterns if (pattern.matcher(method.getName()).matches()) { // if matches ...break; runChild(method, notifier); break; } } } } }
三、使用實例:
package junit_ext; import org.junit.Test; import org.junit.runner.RunWith; import com.array7.annotations.FilterMethods; import com.array7.runner.SpecialMethodsRunner; @RunWith(SpecialMethodsRunner.class) @FilterMethods(methods = { "^.*2$", "^m.*", "ab21"}) public class DemoTest { @Test public void m1() { System.out.println(123); } @Test public void mmm2() { System.out.println(456); } @Test public void a2() { System.out.println(791); } @Test public void ab21() { System.out.println(7890); } }
四、pom.xml依賴
<dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> </dependency>
五、代碼通過測試,文章亦可隨意轉載,惟請保留出處。