2011-08-08 10 views
26

テストケースでテストの失敗またはエラーが発生した場合、@After注釈付きメソッド内でJUnitで検出する方法はありますか? 1は、テストコードでは「インフラ」(withoutFailureフラグ)の世話をする必要があるので、これは醜いです@AfterメソッドでJunitテストの失敗またはエラーを検出する

boolean withoutFailure = false; 

@Test 
void test() { 
    ... 
    asserts... 
    withoutFailure = true; 
} 

@After 
public void tearDown() { 
    if(!withoutFailuere) { 
     this.dontReuseTestenvironmentForNextTest(); 
    } 
} 

一つ醜いソリューションは、そのようなものになるだろう。

@Afterメソッドでテストステータスを取得できる場所があることを願っています。

+0

があなたの 'Before'方法@環境は、すべてのテストのために正しく設定されていることを保証するの世話をしていませんか? –

+0

@Vineet Reynolds:はい、いいえ:Selemium2/Webdriverでテストしていますが、ドライバを再利用したいと思います。しかし、前のテストでもエラーがなければ、再利用したいだけです。 – Ralph

+0

ああ、私の現在の問題。私はこの旗を避けようとしている。他の答えを見ることを願っています。私は合理的な解決策に遭遇した場合、私は投稿します。 –

答えて

8

あなたがJUnit 4.9以降を使用するには十分な運がよければ、TestWatcherはあなたの望むものとまったく同じです。

共有して楽しんでください!

+5

この記事のTestWatchmanは廃止予定です。TestWatcherは新しいクラスです。 – jconlin

+0

リンクは現在停止しています。 –

+3

これはJUnit 4.12とArquillian 1.1.10では動作しません。なぜなら、TestWatcherは '@ After'メソッドの実行後に遅すぎることが通知されるからです。 –

2

あなたがしたいことは、RunListenerをJUnitコアに追加することだと思います。 testFailureメソッドをオーバーライドしてwithoutFailureフラグを1か所に設定すると、@After注釈付きメソッドで確認できます。

さらに、以前のバージョンのJUnitを使用している場合のこのアプローチに関するいくつかの問題については、this blog postを参照してください。

1

TestRuleは、テストメソッドの実行とアフターメソッドの実行の間にあるコードを実行できないという問題を解決するためにdsaffの答えを拡張しています。だから簡単なMethodRule@After注釈付きメソッドで使用されている成功フラグを提供するために、このルールを使用することはできません。

私の考えはハックです!とにかく、TestRule(extend TestWatcher)を使用します。 TestRuleは、テストの失敗または成功についての知識を得るでしょう。私のTestRuleは、新しいAfterHack注釈で注釈が付けられたすべてのメソッドのクラスをスキャンし、そのメソッドを成功フラグとともに呼び出します。


AfterHack注釈

import static java.lang.annotation.ElementType.METHOD; 
import static java.lang.annotation.RetentionPolicy.RUNTIME;  
import java.lang.annotation.Retention; 
import java.lang.annotation.Target; 

@Retention(RUNTIME) 
@Target(METHOD) 
public @interface AfterHack {} 

AfterHackRule

import java.lang.reflect.InvocationTargetException; 
import java.lang.reflect.Method; 
import java.util.ArrayList; 
import java.util.List; 

import org.junit.rules.TestWatcher; 
import org.junit.runner.Description; 

public class AfterHackRule extends TestWatcher { 

    private Object testClassInstance; 
    public AfterHackRule(final Object testClassInstance) { 
     this.testClassInstance = testClassInstance; 
    } 

    protected void succeeded(Description description) { 
     invokeAfterHackMethods(true); 
    } 

    protected void failed(Throwable e, Description description) { 
     invokeAfterHackMethods(false); 
    } 

    public void invokeAfterHackMethods(boolean successFlag) { 
     for (Method afterHackMethod : 
        this.getAfterHackMethods(this.testClassInstance.getClass())) { 
      try { 
       afterHackMethod.invoke(this.testClassInstance, successFlag); 
      } catch (IllegalAccessException | IllegalArgumentException 
        | InvocationTargetException e) { 
       throw new RuntimeException("error while invoking afterHackMethod " 
          + afterHackMethod); 
      } 
     } 
    } 

    private List<Method> getAfterHackMethods(Class<?> testClass) { 
     List<Method> results = new ArrayList<>();    
     for (Method method : testClass.getMethods()) { 
      if (method.isAnnotationPresent(AfterHack.class)) { 
       results.add(method); 
      } 
     } 
     return results; 
    } 
} 

使用:

public class DemoTest { 

    @Rule 
    public AfterHackRule afterHackRule = new AfterHackRule(this); 

    @AfterHack 
    public void after(boolean success) { 
     System.out.println("afterHack:" + success); 
    } 

    @Test 
    public void demofails() { 
     Assert.fail(); 
    } 

    @Test 
    public void demoSucceeds() {} 
} 
BTW

  • 1)うまくいけばJunit5
  • 2のよりよい解決策がある)より良い方法は全く代わり@Beforeと@After方法TestWatcherルールを使用することである(つまり私はdsaffの答えを読む方法)

@see

1

私は@After方法でJUnitテストの障害を検出するための任意の簡単なまたはエレガントな方法を知りません。

@Afterメソッドの代わりにTestRuleを使用することができれば、TestWatcherを内部ルールとして使用して、2つの連鎖したTestRulesを使用することができます。

例:

package org.example; 

    import static org.junit.Assert.fail; 

    import org.junit.Rule; 
    import org.junit.Test; 
    import org.junit.rules.ExternalResource; 
    import org.junit.rules.RuleChain; 
    import org.junit.rules.TestRule; 
    import org.junit.rules.TestWatcher; 
    import org.junit.runner.Description; 

    public class ExampleTest { 

     private String name = ""; 
     private boolean failed; 

     @Rule 
     public TestRule afterWithFailedInformation = RuleChain 
     .outerRule(new ExternalResource(){ 
      @Override 
      protected void after() { 
      System.out.println("Test "+name+" "+(failed?"failed":"finished")+"."); 
      }  
     }) 
     .around(new TestWatcher(){ 
      @Override 
      protected void finished(Description description) { 
      name = description.getDisplayName(); 
      } 
      @Override 
      protected void failed(Throwable e, Description description) { 
      failed = true; 
      }  
     }) 
     ; 

     @Test 
     public void testSomething(){ 
     fail(); 
     } 

     @Test 
     public void testSomethingElse(){ 
     } 

    } 
+0

しかし、私は@Afterの代わりにTestRuleを使用することができます私はTestRuleを使うことができ、 'RuleChain'を必要としません - あるいは何か逃しましたか? – Ralph

+0

RuleChain ...パートは、2つのルール(TestWatcherとExternalResource)を「連結」することによって、新しいTestRuleを構築します。これらのルールは独立して指定できますが、after()メソッドがfailed()より前に実行される可能性があります。 System.out.println()の部分は、対応する@Afterメソッドの中に入れます。 – Gustave

+0

私が理解できないことは、テストの後に実行される 'TestWatcher'を単に使用せず、' succeeded'メソッドと 'failed'メソッドを持っている理由は何ですか? – Ralph

関連する問題