2017-02-27 14 views
8

アクティビティを再作成するテストを作成したいと思います。ローテーションの実行はオプションです。インストルメンテーションとJUnit4を使用してAndroidのアクティビティを再作成することをテストしてください

Googleが「祝福した」テストフレームワークの最新バージョンにテストを書きたいと思っています。私はテストを書くのが初めてであるので、私は基本的な、メインストリーム、よくサポートされているツールを学びたいと思う。私が基礎を掴むと、第三者のテストフレームワークはうまくいくでしょう。基本的な、頻繁に発生するシナリオをテストしたいので、基本的なツールで十分でしょうか?

最小限のテストコード:

public class MainActivity extends AppCompatActivity { 

    static int creationCounter = 0; 
    Integer instanceId; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 

     ++creationCounter; 
     instanceId = new Integer(creationCounter); 
     Log.d("TEST", "creating activity " + this + ", has id " + instanceId); 
    } 
} 

とテストクラス:コードの上

@RunWith(AndroidJUnit4.class) 
public class ExampleInstrumentedTest { 

    @Rule 
    public ActivityTestRule<MainActivity> mActivityTestRule = new ActivityTestRule<>(MainActivity.class); 

    @Test 
    public void useAppContext() throws Exception { 

     MainActivity activity1 = mActivityTestRule.getActivity(); 
     int act1 = activity1.instanceId.intValue(); 
     int counter1 = MainActivity.creationCounter; 
     assertEquals(1, counter1); 
     assertEquals(1, act1); 


     Log.d("TEST", "requesting rotation"); 
     // method 1 
     activity1.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); 
     // method 2 //https://gist.github.com/nbarraille/03e8910dc1d415ed9740#file-orientationchangeaction-java 
     // onView(isRoot()).perform(orientationLandscape()); 

     getInstrumentation().waitForIdleSync(); // I thought this should suffice 
     // How to do this? 
     //somehowRefreshActivityInstanceInsideTestRule(); 

     MainActivity activity2 = mActivityTestRule.getActivity(); 
     int act2 = activity2.instanceId.intValue(); 
     int counter2 = MainActivity.creationCounter; 
     Log.d("TEST", "newly acquired activity " + activity2 + " has id " + act2 + "/" + counter2); 

     assertEquals(2, counter2); 
     assertEquals(2, act2); 
    } 
} 

(法1または2のいずれか)logcatを与える:

D/ActivityTestRule: Launching activity example.com.rotationtest.MainActivity 
D/TEST: creating activity [email protected], has id 1 
D/TEST: requesting rotation 
D/TEST: creating activity [email protected], has id 2 
D/TEST: newly acquired activity [email protected] has id 1/2 
I/TestRunner: failed: useAppContext(example.com.rotationtest.ExampleInstrumentedTest) 
I/TestRunner: ----- begin exception ----- 
I/TestRunner: java.lang.AssertionError: expected:<2> but was:<1> 

私の診断、なら、私を修正私は間違っている:

  1. activity1.setRequestedOrientationにより、他のスレッドで新しいアクティビティが作成されます。私はそれが適切なバンドルを受け取ることを願っています。
  2. getInstrumentation()。waitForIdleSync();新しいアクティビティが作成されるまでテストを待機させます。
  3. mActivityTestRule.getActivity();古いアクティビティインスタンスを返します。
  4. 私は、テストルール内で保持されているアクティビティインスタンスをリフレッシュするために何らかの方法が必要です。

私はテストフレームワークの古いバージョンで答えを見つけました:Instrumentation test for Android - How to receive new Activity after orientation change?

mActivity.setRequestedOrientation(
    ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); 
mActivity.finish(); 
setActivity(null); 
mActivity = getActivity(); 
getInstrumentation().waitForIdleSync(); 

しかし、私は新しいバージョンにそれを変換する方法を知りません。

EDIT:破壊された状態で離脱活性上記の方法の

両方:(。mActivityTestRule.getActivity()isDestroyed())assertFalse。失敗する。

私はアクティビティインスタンスを再作成する別の方法(Destroy and restart Activity with Testing Support Library)を見つけましたが、私は最終的にここに働いて解決策を見つけたonSaveInstanceState

+0

ActivityTestRule.getActivityはちょうどあなた –

+0

ヨニを同じインスタンスを取得し、新しいアクティビティを作成しません、私は、これは動作しません知っています。どのように動作させるかを知りたい、ActivityTestRuleを必ずしも使用する必要はない – MateuszL

答えて

0

を通じてその状態を維持しません:私のニーズのコードに適応した後Get Current Activity in Espresso android

は次のようになります。

public class CurrentActivityTestRule<T extends Activity> extends ActivityTestRule<T> { 
    public CurrentActivityTestRule(Class<T> activityClass) { 
     super(activityClass, false); 
    } 

    public CurrentActivityTestRule(Class<T> activityClass, boolean initialTouchMode) { 
     super(activityClass, initialTouchMode, true); 
    } 

    public CurrentActivityTestRule(Class<T> activityClass, boolean initialTouchMode, boolean launchActivity) { 
     super(activityClass, initialTouchMode, launchActivity); 
    } 

    public T getCurrentActivity() { 
     getInstrumentation().waitForIdleSync(); 
     final Activity[] activity = new Activity[1]; 
     getInstrumentation().runOnMainSync(new Runnable() { 
      @Override 
      public void run() { 
       java.util.Collection<Activity> activities = ActivityLifecycleMonitorRegistry.getInstance().getActivitiesInStage(Stage.RESUMED); 
       activity[0] = Iterables.getOnlyElement(activities); 
      }}); 
     T current = (T) activity[0]; 
     return current; 
    } 
} 

と、このように使用されます。

onView(isRoot()).perform(orientationLandscape()); 
Activity oldActivityInstance = mActivityTestRule.getActivity(); 
Activity currentActivityInstance = mActivityTestRule.getCurrentActivity(); 
私はこのライブラリのバージョンで作業している

androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { 
    exclude group: 'com.android.support', module: 'support-annotations' 
}) 
androidTestCompile('com.android.support.test:runner:0.5', { 
    exclude group: 'com.android.support', module: 'support-annotations' 
}) 
関連する問題