我想为重新创建活动编写测试.执行旋转是可选的. 我希望测试能够被谷歌“祝福”的测试框架的最新版本编写.我是编写测试的新手,所以我想学习基本的,主流的,支持良好的工具.当我掌
我希望测试能够被谷歌“祝福”的测试框架的最新版本编写.我是编写测试的新手,所以我想学习基本的,主流的,支持良好的工具.当我掌握基础知识时,任何第三方测试框架都会没问题.而且由于我想测试非常基本的,经常出现的场景,基本工具应该足够了,对吧?
最小测试代码:
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 example.com.rotationtest.MainActivity@47404a3, has id 1 D/TEST: requesting rotation D/TEST: creating activity example.com.rotationtest.MainActivity@169887e, has id 2 D/TEST: newly acquired activity example.com.rotationtest.MainActivity@47404a3 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>
我的诊断,如果我错了,请纠正我:
> activity1.setRequestedOrientation导致在其他线程中创建新活动.我希望它会得到适当的捆绑
> getInstrumentation().waitForIdleSync();导致test等待,直到创建新活动
> mActivityTestRule.getActivity();仍然返回旧的活动实例.
>我需要一些方法来刷新测试规则中保存的活动实例,释放之前保存的实例.
我找到了旧版测试框架的答案: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();
但我不知道如何将其翻译成新版本.
编辑:
上述两种方法都将活动保留在销毁状态:assertFalse(mActivityTestRule.getActivity().isDestroyed());失败.
我找到了另一种方法(Destroy and restart Activity with Testing Support Library),它重新创建活动实例,但不通过onSaveInstanceState保持其状态
我终于找到了工作解决方案: 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' })