2016-03-10 8 views
7

私は、エスプレッソの使用で失敗したテストを再実行する方法を理解しようとしています。テスト開始前からアプリのステータスを復元する必要があるため、一般的なJUnitのテストケースからは少し複雑です。エスプレッソで再試験に失敗した方法は? - ブレーンストーミング

自分のActivityTestRuleを作成して、このクラスのコード全体をコピーしてMyActivityTestRuleという名前を付けました。

インストルメンテーションテストの場合、ルールにはアクティビティの開始方法に関する情報も必要です。私は自分のためにそれを行うための環境を持っているのではなく、自分でそれを起動する方が好きです。だから、例えば:

@Rule 
    public MyActivityTestRule<ActivityToStartWith> activityRule = new MyActivityTestRule<>(
      ActivityToStartWith.class, true, false 
    ); 

だから私も@Before注釈方法で私の活動を起動します。

@Before 
    public void setUp() throws Exception { 
     activityRule.launchActivity(new Intent()); 
    } 

そして@After注釈方法でクリーンアップを行います。

@After 
    public void tearDown() throws Exception { 
     cleanUpDataBaseAfterTest(); 
     returnToStartingActivity(activityRule); 
    } 

これらの方法を - setUp()、tearDown()は、各テストの実行の前/後に呼び出すことが必須です。テスト開始時のアプリの状態が正しいことを保証するためです。


これまでの変更はほとんどありませんでした。それはまたUiThreadStatementのテスト文を包むようsuper.apply方法を持っているActivityStatementがActivityTestRuleに配置されたとしてそれは、私にとっては未知のことだ

@Override 
    public Statement apply(final Statement base, Description description) { 
     return new ActivityStatement(super.apply(base, description)); 
    } 

public class UiThreadStatement extends Statement { 
    private final Statement mBase; 
    private final boolean mRunOnUiThread; 

    public UiThreadStatement(Statement base, boolean runOnUiThread) { 
     mBase = base; 
     mRunOnUiThread = runOnUiThread; 
    } 

    @Override 
    public void evaluate() throws Throwable { 
     if (mRunOnUiThread) { 
      final AtomicReference<Throwable> exceptionRef = new AtomicReference<>(); 
      getInstrumentation().runOnMainSync(new Runnable() { 
       public void run() { 
        try { 
         mBase.evaluate(); 
        } catch (Throwable throwable) { 
         exceptionRef.set(throwable); 
        } 
       } 
      }); 
      Throwable throwable = exceptionRef.get(); 
      if (throwable != null) { 
       throw throwable; 
      } 
     } else { 
      mBase.evaluate(); 
     } 
    } 
} 

まず最初はからの適用方法の変更あり私は自分のテストで何をしているのかわからない。私は決してmRunOnUiThreadブール値をtrueにすることはできない。私のテストケースの中で、@UiThreadTestアノテーションが付いたテストが存在するか、それがコードから理解したものであれば真です。

@Override 
    public Statement apply(final Statement base, Description description) { 
     return new ActivityStatement(base); 
    } 

そして、私のテストケースが問題なく実行します。しかし、私は、私はこのUiThreadStatementを無視してまでMyActivityTestRuleを変更することを決めたようなものを使用していないが起こることはありません。そのすべて私が残っているのおかげで - mBase.evaluate(包む)である:私は本当のActivityTestRuleコンストラクタ値の3番目のパラメータで設定した場合にのみ、一般launchActivityに

private class ActivityStatement extends Statement { 

    private final Statement mBase; 

    public ActivityStatement(Statement base) { 
     mBase = base; 
    } 

    @Override 
    public void evaluate() throws Throwable { 
     try { 
      if (mLaunchActivity) { 
       mActivity = launchActivity(getActivityIntent()); 
      } 
      mBase.evaluate(); 
     } finally { 
      finishActivity(); 
      afterActivityFinished(); 
     } 
    } 
} 

が呼び出されます。しかし、私はsetUp()で自分でテストを起動します。私はmBase.evaluateを理解し何から

は()@Testアノテーションのメソッド内の私のコードを実行します。また、スローされたスローされている間テストケースを停止します。それは私がそれをキャッチし、それを再起動することができることを意味 - のようなものが提案: How to Re-run failed JUnit tests immediately?

そして、大丈夫、私はそのような何かをした:

public class ActivityRetryStatement extends Statement { 

     private final Statement mBase; 
     private final int MAX_RUNS = 2; 

     public ActivityRetryStatement(Statement base) { 
      mBase = base; 
     } 

     @Override 
     public void evaluate() throws Throwable { 

      Throwable throwable = null; 

      for (int i = 0; i < MAX_RUNS; i++) { 

       try { 
        mBase.evaluate(); 
        // if you reach this lane that means evaluate passed 
        // and you don't need to do the next run 
        break; 
       } catch (Throwable t) { 

        // save first throwable if occurred 
        if (throwable == null) { 
         throwable = t; 
        } 

        // my try that didn't work 
        launchActivity(testInitialIntent); 
        // I've returned test to starting screen but 
        // mBase.envaluate() didn't make it run again 

        // it would be cool now to: 
        // - invoke @After 
        // - finish current activity 
        // - invoke @Before again and start activity 
        // - mBase.evaluate() should restart @Test on activity started again by @Before 
       } 
      } 

      finishActivity(); 
      afterActivityFinished(); 

      // if 1st try fail but 2nd passes inform me still that there was error 
      if (throwable != null) { 
       throw throwable; 
      } 
     } 
    } 

だから、catchブロックでそれらのコメントは、私がどのように知っていない部分であり、行う。私は最初にテストを実行するためにsetUp()で使用したインテントでlaunchActivityを実行しようとしました。しかしmBase.evaluateは、()(テストケースを再度行っていない)、それが反応しなかった - 何もそれが本当にそこに私が思うに、私を保存しないでしょう+起こりませんでした。私は@SetUpで、それが再び呼び出されていなかったんいくつかのイニシエーションを欠いていました。私は実際にテストライフサイクル全体を@Before @Test @After Againに再起動する方法を見つけたいと思っています。コードからInstrumentationまたはTestRunnerを呼び出すことがあります。

どうすればいいですか?

+0

のいずれかの解決方法を確認してください。 –

答えて

0

答えは簡単です。あなたのエスプレッソテストをJunit 4にアップグレードしてから、this answer

+0

私は 'evaluate()'をループに入れようとしましたが、何が起こったのですか - > @Testコードブロックは再び実行されましたが、デバイスは反応しませんでした。それはあなたのためにエスプレッソで動作しました - 一般的なJunitテストではありませんか? (私はJunit ver 4.12を使用しています) – F1sher

+0

うん、私はエスプレッソのテストでこれを実装しましたが、うまくいきました。おそらくあなたがテストを設定していることが問題です。リンク先の回答に実装されているRetryルールも含むテストの要点を投稿できますか? – gorbysbm

+0

どうもありがとうございました。現在、私は仕事に忙しかったですが、私は非常に興味を持っているので、必ず確認しています。もし私が間違っていることを確認できるように働いていればフィードバックをお寄せください:) – F1sher

関連する問題