2016-12-14 99 views
1

我需要收集我當前的應用程序的一些數據,以便通過檢查活動啓動期間的平均經過時間來分析性能速度。我想運行一個測試電池,活動開始10,100,1000和5000次。對於每個測試,它應該保持打開至少10秒(收集異步發生的所有數據所需的時間)。我想正是這種行爲,而無需編寫這些方法很多:如何反覆運行單元測試+濃咖啡?

@RunWith(AndroidJUnit4.class) 
@LargeTest 
public class TestStreamLoadingPerformance { 

    private static final long TIME_OUT = 2; 
    private static final long WAITING_TIME = 10000; 

    @Rule 
    public ActivityTestRule mActivityRule = new ActivityTestRule(HomepageActivity.class); 

    private ElapsedTimeIdlingResource mIdleRes = new ElapsedTimeIdlingResource(WAITING_TIME); 


    @Before 
    public void setUp() { 
     IdlingPolicies.setMasterPolicyTimeout(TIME_OUT, TimeUnit.HOURS); 
     IdlingPolicies.setIdlingResourceTimeout(TIME_OUT, TimeUnit.HOURS); 
     Espresso.registerIdlingResources(mIdleRes); 
    } 

    @After 
    public void tearDown() { 
     Espresso.unregisterIdlingResources(mIdleRes); 
    } 

    @Test 
    public void test01() { 
    } 

    @Test 
    public void test02() { 
    } 

    @Test 
    public void test03() { 
    } 

    @Test 
    public void test04() { 
    } 

    @Test 
    public void test05() { 
    } 

    @Test 
    public void test06() { 
    } 

    @Test 
    public void test07() { 
    } 

    @Test 
    public void test08() { 
    } 

    @Test 
    public void test09() { 
    } 
} 
+1

http://stackoverflow.com/q/1492856/4879701包含少數關於如何多次運行相同的junit測試的解決方案。 –

+0

我確實嘗試了其中的大部分,但都失敗了:當它試圖重複測試時,它無法啓動意圖,並因超時而失敗。這是Espresso生命週期的某種方式。 –

+1

啊,這可能是因爲測試規則。只需向launchActivity()提供false布爾值並從測試中手動啓動 –

回答

2

隨着@Be_negative意見,this博客文章和this答案的幫助下,我能夠用下面的代碼來解決這個問題:

@RunWith(AndroidJUnit4.class) 
@LargeTest 
public class TestStreamLoadingPerformance { 

    @Rule 
    public ActivityTestRule mActivityRule = new ActivityTestRule(HomepageActivity.class, false, false); 
    @Rule 
    public RepeatRule mRepeatRule = new RepeatRule(); 


    @After 
    public void tearDown() { 
     closeActivity(); 
    } 

    private void closeActivity() { 
     final int N = 10; 
     try { 
      for (int i = 0; i < N; i++) { 
       Espresso.pressBack(); 
      } 
     } catch (NoActivityResumedException e) { 
      Log.e(TestStreamLoadingPerformance.class.getSimpleName(), "Unable to close activities", e); 
     } 
    } 

    @Test 
    @RepeatRule.Repeat(times = 10) 
    public void collectData() { 
     mActivityRule.launchActivity(null); 
    } 
} 

import org.junit.rules.TestRule; 
import org.junit.runner.Description; 
import org.junit.runners.model.Statement; 

import java.lang.annotation.Retention; 
import java.lang.annotation.RetentionPolicy; 
import java.lang.annotation.Target; 

public class RepeatRule implements TestRule { 
    @Retention(RetentionPolicy.RUNTIME) 
    @Target({ 
      java.lang.annotation.ElementType.METHOD 
    }) 
    public @interface Repeat { 
     public abstract int times(); 
    } 

    private static class RepeatStatement extends Statement { 

     private final int times; 
     private final Statement statement; 

     private RepeatStatement(int times, Statement statement) { 
      this.times = times; 
      this.statement = statement; 
     } 

     @Override 
     public void evaluate() throws Throwable { 
      for (int i = 0; i < times; i++) { 
       statement.evaluate(); 
      } 
     } 
    } 

    @Override 
    public Statement apply(Statement statement, Description description) { 
     Statement result = statement; 
     Repeat repeat = description.getAnnotation(Repeat.class); 
     if (repeat != null) { 
      int times = repeat.times(); 
      result = new RepeatStatement(times, statement); 
     } 
     return result; 
    } 
} 
+0

我想知道,如果不是按回來,你可以做'mActivityRule.getActivity()。finish()' –

+0

不,我測試過了,這不起作用 –

0

要做到這一點,最簡單的方法就是將測試作爲參數化測試運行(用@RunWith(Parameterized.class)註釋並添加一個方法來提供10個空參數)。這樣框架將運行測試10次。

這個測試將需要在類中唯一的測試,或者更好地把所有的測試方法都需要在類中運行10次。

下面是一個例子:

@RunWith(Parameterized.class) 
public class RunTenTimes { 
    @Parameterized.Parameters 
    public static List<Object[]> data() { 
     return Arrays.asList(new Object[10][0]); 
    } 

    public RunTenTimes() { 
    } 

    @Test 
    public void runsTenTimes() { 
     System.out.println("run"); 
    } 
} 

通過以上,有可能即使有一個參數的構造函數做到這一點,但我不知道,如果框架作者意圖,或者如果將在未來打破。

如果你正在實施自己的跑步者,那麼你可以讓跑步者跑10次。如果您使用的是第三方運行程序,那麼使用4.7,您可以使用新的@Rule註釋並實現MethodRule接口,以便它接受語句並在for循環中執行10次。這種方法目前的缺點是@Before和@After只能運行一次。這可能會在下一個版本的JUnit中發生變化(@Before將在@Rule之後運行),但是無論您是在同一個對象實例上操作(事實上參數化運行器都不是這樣)。這假定無論您是否正在運行類的運行程序都正確識別@Rule註釋。只有在委託給JUnit跑步者的情況下才是如此。

如果您正在運行的自定義運行程序不能識別@Rule註釋,那麼您確實需要編寫自己的運行程序,該運行程序正確地委派給該運行程序並運行它10次。

請注意,還有其他方法可能可以解決此問題(如Theories跑步者),但他們都需要跑步者。不幸的是,JUnit目前不支持多層跑步者。這是一個與其他跑步者聯繫在一起的跑步者。