2016-03-10 14 views
7

Tôi đang cố gắng tìm ra cách để chạy lại các thử nghiệm không thành công bằng cách sử dụng Espresso. Tôi nghĩ rằng nó phức tạp hơn một chút so với trường hợp thử nghiệm JUnit thông thường khi bạn cần khôi phục trạng thái trong ứng dụng của mình trước khi bắt đầu thử nghiệm.Thử nghiệm chạy lại không thành công trong Espresso như thế nào? - động não

Cách tiếp cận của tôi là tạo ActivityTestRule của riêng mình vì vậy tôi vừa sao chép toàn bộ mã từ lớp này và đặt tên là MyActivityTestRule.

Trong trường hợp quy tắc kiểm tra thiết bị đo đạc cũng cần thông tin về cách chúng tôi muốn bắt đầu hoạt động của mình. Tôi thích tự khởi chạy hơn là có môi trường để làm điều đó cho tôi. Vì vậy, ví dụ:

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

Vì vậy, tôi cũng khởi động hoạt động của tôi trong phương pháp chú thích @Before:

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

Và chắc dọn dẹp trong phương pháp chú thích @After:

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

Những phương pháp - setUp(), tearDown() là điều cần thiết để được gọi trước/sau mỗi lần chạy thử - để đảm bảo trạng thái ứng dụng trong khi bắt đầu thử nghiệm là chính xác.


Bên trong MyActivityTestRule Tôi đã thực hiện một vài sửa đổi cho đến nay. Điều đầu tiên là thay đổi phương pháp áp dụng từ:

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

Đó là một nhưng điều lạ đối với tôi, như ActivityStatement đặt trong ActivityTestRule có phương pháp super.apply vì vậy nó cũng kết thúc tốt đẹp tuyên bố thử nghiệm trong UiThreadStatement:

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(); 
     } 
    } 
} 

Không có mather những gì tôi làm với các bài kiểm tra của tôi Tôi không bao giờ có thể tạo ra trường hợp boolean mRunOnUiThread là đúng sự thật. Nó sẽ là đúng nếu trong các trường hợp thử nghiệm của tôi, các bài kiểm tra với chú thích @UiThreadTest sẽ có mặt - hoặc đó là những gì tôi hiểu từ mã. Nó không bao giờ xảy ra, mặc dù tôi không sử dụng bất cứ điều gì như thế vì vậy tôi đã quyết định bỏ qua UiThreadStatement này và thay đổi MyActivityTestRule tới:

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

Và trường hợp thử nghiệm của tôi chạy mà không có bất kỳ vấn đề. Nhờ đó tất cả những gì đã để lại - mà kết thúc tốt đẹp xung quanh mBase.evaluate() là:

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(); 
     } 
    } 
} 

Trong launchActivity chung sẽ được gọi là chỉ khi tôi đặt trong tham số thứ 3 của ActivityTestRule giá trị nhà xây dựng đúng. Nhưng tôi tự khởi chạy các bài kiểm tra trong setUp() để nó không bao giờ xảy ra.

Từ những gì tôi hiểu mBase.evaluate() chạy mã của tôi bên trong phương thức chú thích @Test. Nó cũng dừng trường hợp thử nghiệm trong khi ném được ném. Điều đó có nghĩa tôi có thể bắt nó và khởi động lại nó - như đề xuất có: How to Re-run failed JUnit tests immediately?

Và rồi tôi đã làm một cái gì đó như thế:

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; 
      } 
     } 
    } 

Vì vậy, những ý kiến ​​trong khối catch là bộ phận không tôi không biết làm thế nào để làm. Tôi đã cố gắng thực hiện launchActivity theo ý định mà tôi đã sử dụng trong setUp() để chạy thử nghiệm lần đầu tiên. Nhưng mBase.evaluate() đã không làm cho nó phản ứng (trường hợp thử nghiệm đã không đi một lần nữa) - không có gì xảy ra + nó sẽ không thực sự giúp tôi có tôi nghĩ. Tôi thiếu một số điểm khởi đầu tôi làm trong @SetUp, nó không được gọi lại.Tôi thực sự muốn tìm một cách làm thế nào để khởi động lại toàn bộ vòng đời thử nghiệm @Before @Test @Sau hơn một lần nữa. Có thể một số cuộc gọi trên Instrumentation hoặc TestRunner từ mã.

Bất kỳ suy nghĩ nào về cách thực hiện?

+0

có giải pháp nào không? –

Trả lời

0

Câu trả lời cực kỳ đơn giản. Chỉ cần đảm bảo bạn nâng cấp các bài kiểm tra espresso lên Junit 4 và sau đó xem this answer

+0

Tôi đã cố gắng đặt 'evaluation()' trong vòng lặp nhưng những gì đã xảy ra -> @Test code block được thực thi lại, nhưng thiết bị không phản ứng. Nó có phù hợp với bạn ON Espresso - không phải các bài kiểm tra Junit phổ biến? (Tôi đang sử dụng Junit ver 4.12) – F1sher

+0

Vâng, tôi đã thực hiện điều này trong các bài kiểm tra Espresso của chúng tôi và nó hoạt động tốt. Nó có lẽ là cách bạn đang thiết lập các bài kiểm tra của bạn đó là vấn đề. Bạn có thể đăng một ý chính của một bài kiểm tra ví dụ mà cũng bao gồm các quy tắc Thử lại như được thực hiện trong câu trả lời tôi liên kết đến? – gorbysbm

+0

Xin cảm ơn rất nhiều vì thông tin đó. Hiện tại tôi thực sự bận rộn với công việc nhưng tôi chắc chắn sẽ kiểm tra nó vì tôi rất quan tâm đến điều đó và tôi sẽ cung cấp cho bạn phản hồi nếu nó hoạt động hoặc cung cấp một số mã để chúng tôi có thể kiểm tra những gì tôi đang làm sai :) – F1sher

Các vấn đề liên quan