2012-08-22 10 views
15

私は@Afterでシステムからログアウトし、ブラウザを閉じるのは@AfterClassです。私は@Ruleを使用して、すべてのテストメソッドでSeleniumを使用して失敗したテストスクリーンショットを取得しようとしています。私は手動で@Ruleがすべて@Beforeの前に実行されていることを確認しましたが、@Testの後で@Afterの前に設定します。私は簡単な解決策を見つけることができませんでした。どんな助けもありがとう。JUnitで '@Test'の後に '@After'の後に '@Rule'を入力してください

public class MorgatgeCalculatorTest { 

@Before 
public void before(){ 
    System.out.println("I am before"); 
} 
@BeforeClass 
public static void beforeclass(){ 
    System.out.println("I am beforeclass"); 
} 
@Test 
    public void test(){ 
     System.out.println("I am Test"); 
    } 
@Test 
public void test2(){ 
    System.out.println("I am Test2"); 
} 
@After 
    public void after(){ 
     System.out.println("I am after"); 
    } 
@AfterClass 
     public static void afterclass(){ 
      System.out.println("I am afterclass"); 

} 
@Rule 
ExpensiveExternalResource ExpensiveExternalResource = new ExpensiveExternalResource(); 

static class ExpensiveExternalResource implements MethodRule { 
    public ExpensiveExternalResource(){ 
     System.out.println("I am rule"); 
    } 

    @Override 
    public Statement apply(Statement arg0, FrameworkMethod arg1, Object arg2) { 
     // TODO Auto-generated method stub 
     return null; 
    }  
}    

私は取得しています出力は

I am beforeclass 
I am rule 
I am before 
I am Test 
I am after 
I am rule 
I am before 
I am Test2 
I am after 
I am afterclass 
+0

私は、テストが失敗した場合にのみスクリーンショットを撮りたいと述べました。すべてのテストではありません:D –

+0

面白いです。私は注文だけに興味があったので、実際にあなたの質問は私の答えでした:) –

+0

@GáborLipták:)私はうれしいです! –

答えて

19

ルールが設定されているため、@ beforeまたは@afterの後に来るルールを設定することはできません。あなたはテストメソッドに置いたシェルのようなルールを考えることができます。最初のシェルは@ before/@ afterです。その後、@rulesが適用されます。

あなたがしたいことをすばやく行うには、@Afterを避けることです。メソッドが失敗した場合にスクリーンショットを取得し、コードの後に​​コードを実行するようにルールを作成できます。 @Afterほどきれいではありませんが、動作します。 (また、私はMethodRuleが償却されているので、TestRuleを実装しました)。

public class MortgageCalculatorTest { 
    @Before 
    public void before(){ 
     System.out.println("I am before"); 
    } 

    @BeforeClass 
    public static void beforeclass(){ 
     System.out.println("I am beforeclass"); 
    } 

    @Test 
    public void test(){ 
     System.out.println("I am a Test"); 
    } 

    @Test 
    public void test2(){ 
     System.out.println("I am a Failed Test"); 
     fail(); 
    } 

    @AfterClass 
      public static void afterclass(){ 
       System.out.println("I am afterclass"); 

    } 

    @Rule 
    public ExpensiveExternalResource ExpensiveExternalResource = new ExpensiveExternalResource(); 

    public static class ExpensiveExternalResource implements TestRule { 


     // public ExpensiveExternalResource(){} 


     public class ExpansiveExternalResourceStatement extends Statement{ 

      private Statement baseStatement; 

      public ExpansiveExternalResourceStatement(Statement b){ 
       baseStatement = b; 
      } 

      @Override 
      public void evaluate() throws Throwable { 
       try{ 
        baseStatement.evaluate(); 
       }catch(Error e){ 
        System.out.println("I take a Screenshot"); 
        throw e; 
       }finally{ 
        after(); 
       } 
      } 

      //Put your after code in this method! 
      public void after(){ 
       System.out.println("I am after"); 
      } 
     } 

     public Statement apply(Statement base, Description description) { 
      return new ExpansiveExternalResourceStatement(base); 

     } 


    } 
} 

すべての作業はステートメントで行われます。 org.junit.runners.model.Statementは、コードの束を表すクラスです。だからここでメソッドを適用すると、あなたはシェルを置いているコードの束を受け取ります。 Applyは、与えられたコードの束を実行する文を返し、try/catch文で囲んでメソッドの失敗を捕捉します。

このメソッドの出力は次のとおりです。

I am beforeclass 
I am before 
I am a Test 
I am after 
I am before 
I am a Failed Test 
I take a Screenshot 
I am after 
I am afterclass 

は、この情報がお役に立てば幸い!

+0

トロイ、ご意見ありがとうございます。あなたの解決策のヒントを得ました。 –

+0

'@ After'メソッドを出力に追加して、それが表示されるようにします。つまり、baseStatement.evaluate()は実際に' @ Before'を実行し、次にメソッドをテストし、 '@ After'を実行します。 – dhblah

1

ExternalResourceルールを使用する方法についてですか?
必要なものに十分な柔軟性を与えることができるようです。
これが必要なものでない場合は、source codeの外部リソースをご覧ください。
ルールを実装する方法をかなり理解できます。たとえば、テスト呼び出しの後にのみ動作するルールです。

4
public class ScreenshotTestRule implements MethodRule { 
    public Statement apply(final Statement statement, final FrameworkMethod frameworkMethod, final Object o) { 
     return new Statement() { 
      @Override 
      public void evaluate() throws Throwable { 
       try { 
        statement.evaluate(); 

       } catch (Throwable t) { 
        captureScreenshot(frameworkMethod.getName()); 
        throw t; // rethrow to allow the failure to be reported to JUnit      
       } finally { 
        tearDown(); 
       } 
      } 

      public void tearDown() { 
       //logout to the system; 
      } 


      public void captureScreenshot(String fileName) { 
       try { 
        new File("target/surefire-reports/screenshot").mkdirs(); // Insure directory is there 
        FileOutputStream out = new FileOutputStream("target/surefire-reports/screenshot/screenshot-" + fileName + ".png"); 
        out.write(((TakesScreenshot) driver).getScreenshotAs(OutputType.BYTES)); 
        out.close(); 
       } catch (Exception e) { 
        // No need to crash the tests if the screenshot fails 
       } 
      } 
     }; 
    } 
} 
関連する問題