2011-10-03 87 views
10

我有一個類是JUnit測試類的JUnit套件。我想在套件上定義規則,以在每個單元測試運行之前和之後對數據庫做些什麼如果該測試方法存在某個註釋。如何在測試套件中定義JUnit方法規則?

我已經能夠在每個和每個(這不夠好)之前這樣做的套件和測試類中創建@ClassRule,並且我已經能夠定義測試規則測試類本身,但這是重複的,看起來不太乾燥。

是否可以在套件中定義每個測試方法規則,還是必須將它們添加到每個測試?爲了澄清,我想聲明一個套件中的代碼,它將在測試類中的測試方法之間運行(即「圍繞」)。

回答

11

這可以完成,但它需要一點工作。您還需要定義自己的套件運行器和您自己的測試運行器,然後在測試運行器中重寫runChild()。使用下面的套房和測試類:

@RunWith(MySuite.class) 
@SuiteClasses({Class1Test.class}) 
public class AllTests { 
} 

public class Class1Test { 
    @Deprecated @Test public void test1() { 
     System.out.println("" + this.getClass().getName() + " test1"); 
    } 

    @Test public void test2() { 
     System.out.println("" + this.getClass().getName() + " test2"); 
    } 
} 

請注意,我註釋test1()@Deprecated。你想,當你有上試@Deprecated註釋做不同的事情,所以我們需要擴展套件使用自定義Runner

public class MySuite extends Suite { 
    // copied from Suite 
    private static Class<?>[] getAnnotatedClasses(Class<?> klass) throws InitializationError { 
     Suite.SuiteClasses annotation = klass.getAnnotation(Suite.SuiteClasses.class); 
     if (annotation == null) { 
      throw new InitializationError(String.format("class '%s' must have a SuiteClasses annotation", klass.getName())); 
     } 
     return annotation.value(); 
    } 

    // copied from Suite 
    public MySuite(Class<?> klass, RunnerBuilder builder) throws InitializationError { 
     super(null, getRunners(getAnnotatedClasses(klass))); 
    } 

    public static List<Runner> getRunners(Class<?>[] classes) throws InitializationError { 
     List<Runner> runners = new LinkedList<Runner>(); 

     for (Class<?> klazz : classes) { 
      runners.add(new MyRunner(klazz)); 
     } 

     return runners; 
    } 
} 

的JUnit會爲每個測試將運行一個Runner。通常情況下,Suite會創建默認的BlockJUnit4ClassRunner,我們這裏所做的全部重寫了Suite的構造函數,它從SuiteClass註釋中讀取類,我們正在創建自己的運行程序MyRunner。這是我們的MyRunner類:

public class MyRunner extends BlockJUnit4ClassRunner { 
    public MyRunner(Class<?> klass) throws InitializationError { 
     super(klass); 
    } 

    @Override 
    protected void runChild(final FrameworkMethod method, RunNotifier notifier) { 
     Description description= describeChild(method); 
     if (method.getAnnotation(Ignore.class) != null) { 
      notifier.fireTestIgnored(description); 
     } else { 
      if (description.getAnnotation(Deprecated.class) != null) { 
       System.out.println("name=" + description.getMethodName() + " annotations=" + description.getAnnotations()); 
      } 
      runLeaf(methodBlock(method), description, notifier); 
     } 
    } 
} 

這其中大部分是從BlockJUnit4ClassRunner複製。我已經添加了位:

if (description.getAnnotation(Deprecated.class) != null) { 
    System.out.println("name=" + description.getMethodName() + " annotations=" + description.getAnnotations()); 
} 

,我們測試了@Deprecated註釋的方法的存在,並做一些事情,如果它的存在。剩下的部分作爲讀者的練習。當我運行上面的套件時,我得到輸出:

name=test1 annotations=[@java.lang.Deprecated(), @org.junit.Test(expected=class org.junit.Test$None, timeout=0)] 
uk.co.farwell.junit.run.Class1Test test1 
uk.co.farwell.junit.run.Class1Test test2 

請注意,Suite有多個構造函數,具體取決於它如何被調用。上述工作適用於Eclipse,但我還沒有測試過運行該套件的其他方式。有關更多信息,請參閱Suite的各種構造函數旁邊的註釋。

-2

您可以用TestNG group tests。你可以配置TestNG來運行一些邏輯@BeforeGroup and @AfterGroup

+0

我不認爲這是我正在尋找。我想要在每個測試之間運行的東西。 – ArtB

+0

但是,如果您有一組測試,應該可以使用BeforeMethod和AfterMethod。 (我猜) – ollins

+2

也許,無論如何,我需要使用JUnit和TestNG不是一個選項。 – ArtB

2

您可以使用添加到套件的RunListener。它不會給你規則可以做的所有事情,但它會爲你提供一個Description類,它應該有可用的註釋。至少,我不認爲JUnit只將它過濾到其理解的註釋中。

JUnit的開發人員剛剛討論了將RunListener添加到套件的機制here

1

就其本身而言,向@RunWith(Suite.class)註解的類添加規則將無濟於事。我認爲這是因爲SuiteParentRunner<Runner>而不是Runner,比如BlockJUnit4ClassRunner,它會試圖在它運行的類上刮取規則。爲了運行它的孩子,它告訴孩子Runners運行。這些Runner可能已經通過對這些類別應用規則來構建他們的測試,但Suite跑步者不會採取任何特殊行動來將自身的規則應用於其子女Runner構建的測試。

+0

那麼目前沒有辦法?說得通。我想知道單個測試會失敗的情況,因爲它推測套件設置的資源。同樣有意義的是,一個套件只會運行單元測試,因爲它們不能將*鉤入*它們的生命週期,同時仍然能夠掛鉤它 – ArtB

+0

儘管如此,我會給@Yishai的建議一個嘗試。 – pholser

0

您是否嘗試過使用「測試類層次結構」?我經常使用抽象測試類來分享測試或夾具。例如,我所有的數據庫測試都在初始化嵌入式數據源。我首先創建一個處理init邏輯的抽象「DbTestCase」類。那麼所有的子類都將有利於測試和固定裝置。

但是,有時我遇到問題,當我的測試用例需要很多測試/夾具邏輯時,我無法將其存儲在單個層次結構中。在這種情況下,只有方面編程才能解決問題。通過特定的註釋/接口標記測試/夾具邏輯,任何必需的類都可以實現。

你可以選擇考慮使用自定義運行器來處理「aspect」,該運行器將根據被測試類的註釋/接口「注入」測試/夾具邏輯。

+0

雖然層次理念是健全的,但方面就像黑魔法或芥末:他們應該謹慎使用,即使只是謹慎使用。 – ArtB