Espresso - 在 AsyncTask 期间截取屏幕截图
Espresso - Taking screenshot during an AsyncTask
我目前正在使用 Espresso 以编程方式截取 Android 应用程序的屏幕截图。我成功使用
android.support.test.runner.screenshot.Screenshot
问题是,给定以下假设 from official Espresso docs:
- The message queue is empty.
- There are no instances of AsyncTask currently executing a task.
- All developer-defined idling resources are idle.
By performing these checks, Espresso substantially increases the likelihood that only one UI action or assertion can occur at any given time. This capability gives you more reliable and dependable test results.
当 AsyncTask
为 运行 时,我无法执行任何测试。当我的 AsyncTask
为 运行 时,我需要截取一些屏幕截图,但无法理解有关如何执行此类任务的文档。 The most similar SO thread I found好像不行,不知道是不是因为AsyncTask
速度太快,没法截图。
// Start the async task
onView(withId(R.id.start_task_button)).perform(click());
// Then "press" the back button (in the ui thread of the app under test)
mActivityTestRule.runOnUiThread(new Runnable() {
@Override
public void run() {
mScreenshotWatcher.captureScreenshot("screenshot1");
}
});
有什么线索吗?这是正确的方法还是我应该在 AsyncTask
中实施 IdlingResource
?
谢谢
尼古拉
根据我对你问题的理解,你希望在 AsyncTask 正在进行时截取屏幕截图。
我创建了一个最小的 Android 应用程序来验证您的场景,但当使用来自 Espresso 的 click() 时它不起作用。问题在于,一旦 Espresso 执行了它的 click(),它就会在之后调用 loopMainThreadUntilIdle()。由于此时您的 AsyncTask 已经启动,UiControllerImpl#loopMainThreadUntilIdle() 中的循环已经 运行 一遍又一遍,直到 AsyncTask 完成。
克服这个问题的最简单方法是使用自定义 ViewMatcher 进行点击并立即返回。
MainActivity.java
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.test_edit_text).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
v.setVisibility(View.INVISIBLE);
new AsyncTask<Object, Object, Object>() {
@Override
protected Object doInBackground(Object... objects) {
SystemClock.sleep(20000000);
return null;
}
@Override
protected void onPostExecute(Object o) {
findViewById(R.id.test_edit_text)
.setVisibility(View.VISIBLE);
}
}.execute();
}});
}
}
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest package="com.question.Whosebug"
xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
</application>
</manifest>
MainActivityTest.java
@RunWith(AndroidJUnit4.class)
public class ExampleInstrumentedTest {
@Rule
public ActivityTestRule<MainActivity> activityActivityTestRule = new ActivityTestRule<MainActivity>(MainActivity.class);
@Test
public void testTakeScreenshot() throws Exception {
Espresso.onView(withId(R.id.test_edit_text)).check(matches(isDisplayed()));
// use a custom ViewAction here because this call has be non-blocking
Espresso.onView(withId(R.id.test_edit_text)).perform(new ViewAction() {
@Override
public Matcher<View> getConstraints() {
return isDisplayingAtLeast(90);
}
@Override
public String getDescription() {
return "NonBlockingTap";
}
@Override
public void perform(UiController uiController, View view) {
view.performClick();
}
});
ScreenCapture screenCapture = Screenshot.capture();
screenCapture.setFormat(Bitmap.CompressFormat.PNG);
screenCapture.setName("test.png");
screenCapture.process();
Espresso.onView(withId(R.id.test_edit_text)).check(matches(isDisplayed()));
}
}
我目前正在使用 Espresso 以编程方式截取 Android 应用程序的屏幕截图。我成功使用
android.support.test.runner.screenshot.Screenshot
问题是,给定以下假设 from official Espresso docs:
- The message queue is empty.
- There are no instances of AsyncTask currently executing a task.
- All developer-defined idling resources are idle.
By performing these checks, Espresso substantially increases the likelihood that only one UI action or assertion can occur at any given time. This capability gives you more reliable and dependable test results.
当 AsyncTask
为 运行 时,我无法执行任何测试。当我的 AsyncTask
为 运行 时,我需要截取一些屏幕截图,但无法理解有关如何执行此类任务的文档。 The most similar SO thread I found好像不行,不知道是不是因为AsyncTask
速度太快,没法截图。
// Start the async task
onView(withId(R.id.start_task_button)).perform(click());
// Then "press" the back button (in the ui thread of the app under test)
mActivityTestRule.runOnUiThread(new Runnable() {
@Override
public void run() {
mScreenshotWatcher.captureScreenshot("screenshot1");
}
});
有什么线索吗?这是正确的方法还是我应该在 AsyncTask
中实施 IdlingResource
?
谢谢 尼古拉
根据我对你问题的理解,你希望在 AsyncTask 正在进行时截取屏幕截图。
我创建了一个最小的 Android 应用程序来验证您的场景,但当使用来自 Espresso 的 click() 时它不起作用。问题在于,一旦 Espresso 执行了它的 click(),它就会在之后调用 loopMainThreadUntilIdle()。由于此时您的 AsyncTask 已经启动,UiControllerImpl#loopMainThreadUntilIdle() 中的循环已经 运行 一遍又一遍,直到 AsyncTask 完成。
克服这个问题的最简单方法是使用自定义 ViewMatcher 进行点击并立即返回。
MainActivity.java
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.test_edit_text).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
v.setVisibility(View.INVISIBLE);
new AsyncTask<Object, Object, Object>() {
@Override
protected Object doInBackground(Object... objects) {
SystemClock.sleep(20000000);
return null;
}
@Override
protected void onPostExecute(Object o) {
findViewById(R.id.test_edit_text)
.setVisibility(View.VISIBLE);
}
}.execute();
}});
}
}
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest package="com.question.Whosebug"
xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
</application>
</manifest>
MainActivityTest.java
@RunWith(AndroidJUnit4.class)
public class ExampleInstrumentedTest {
@Rule
public ActivityTestRule<MainActivity> activityActivityTestRule = new ActivityTestRule<MainActivity>(MainActivity.class);
@Test
public void testTakeScreenshot() throws Exception {
Espresso.onView(withId(R.id.test_edit_text)).check(matches(isDisplayed()));
// use a custom ViewAction here because this call has be non-blocking
Espresso.onView(withId(R.id.test_edit_text)).perform(new ViewAction() {
@Override
public Matcher<View> getConstraints() {
return isDisplayingAtLeast(90);
}
@Override
public String getDescription() {
return "NonBlockingTap";
}
@Override
public void perform(UiController uiController, View view) {
view.performClick();
}
});
ScreenCapture screenCapture = Screenshot.capture();
screenCapture.setFormat(Bitmap.CompressFormat.PNG);
screenCapture.setName("test.png");
screenCapture.process();
Espresso.onView(withId(R.id.test_edit_text)).check(matches(isDisplayed()));
}
}