Espresso-core2.2.2とRunner/Rules 0.5が公開されていたのでコードを見る

espresso 2.2.2と、Runner/Rules 0.5が公開されていた。Silent releaseぽい。

https://google.github.io/android-testing-support-library/downloads/release-notes/index.html

更新情報の中で気になったところをメモ。sampleとかも書かれていないので、コードを直接追ってみました。コードまで追ってみた結果としては、 withResourceName だけ気にしていれば良いかなという感じ。

New feature

  • Added checks for enabled animations and transitions
  • New ViewMatcher API: withResourceName

notable change

  • ActivityTestRule, UiThreadTestRule, IntentsTestRule and ServiceTestRule are out of beta.

dive into code

withResourceName

コードを見た感じだと以下。 withResourceName は resource idではなく、name属性から要素を特定できるっぽい。

  • android/support/test/espresso/matcher/ViewMatchers.java


// android/support/test/espresso/matcher/ViewMatchers.java
/**
* Returns a matcher that matches {@link View}s based on resource id names,
* (for instance, channel_avatar).
*
* @param name the resource id name
*/
public static Matcher<View> withResourceName(String name) {
return withResourceName(is(name));
}
/**
* Returns a matcher that matches {@link View}s based on resource id names,
* (for instance, channel_avatar).
*
* @param stringMatcher a Matcher for resource id names
*/
public static Matcher<View> withResourceName(final Matcher<String> stringMatcher) {
checkNotNull(stringMatcher);
return new TypeSafeMatcher<View>() {
@Override
public void describeTo(Description description) {
description.appendText("with res-name that ");
stringMatcher.describeTo(description);
}
@Override
public boolean matchesSafely(View view) {
if (view.getId() == -1 || view.getResources() == null) {
return false;
}
try {
return stringMatcher.matches(view.getResources().getResourceEntryName(view.getId()));
} catch (Resources.NotFoundException ignore) {
return false;
}
}
};
}

animation

Added checks for enabled animations and transitions に関しては、テストがアニメーションの設定が起因で失敗した時には

"Animations or transitions are enabled on the target device.\n"
+ "For more info check: http://goo.gl/qVu1yV\n\n");

の失敗が表示されるらしい。ここは、以下のHandlerメソッドに内包されている。

http://developer.android.com/reference/android/support/test/espresso/base/DefaultFailureHandler.html

ちなみに、http://goo.gl/qVu1yV のリンク先には以下があるので、結局は端末のアニメーションをOFFにしてね、という表示をするだけぽい。

On your device, under Settings->Developer options disable the following 3 settings:
– Window animation scale
– Transition animation scale
– Animator duration scale

この判定箇所のprivateコードが眠っている箇所は以下。

  • android/support/test/espresso/base/DefaultFailureHandler.java


// android/support/test/espresso/base/DefaultFailureHandler.java
….
@Override
public void handle(Throwable error, Matcher<View> viewMatcher) {
if (error instanceof EspressoException || error instanceof AssertionFailedError
|| error instanceof AssertionError) {
throw propagate(getUserFriendlyError(error, viewMatcher));
} else {
throw propagate(error);
}
}
/**
* When the error is coming from espresso, it is more user friendly to:
* 1. propagate assertions as assertions
* 2. swap the stack trace of the error to that of current thread (which will show
* directly where the actual problem is)
*/
private Throwable getUserFriendlyError(Throwable error, Matcher<View> viewMatcher) {
if (error instanceof PerformException) {
StringBuilder sb = new StringBuilder();
if (!isAnimationAndTransitionDisabled(appContext)) {
sb.append(
"Animations or transitions are enabled on the target device.\n"
+ "For more info check: http://goo.gl/qVu1yV\n\n");
}
sb.append(viewMatcher.toString());
// Re-throw the exception with the viewMatcher (used to locate the view) as the view
// description (makes the error more readable). The reason we do this here: not all creators
// of PerformException have access to the viewMatcher.
throw new PerformException.Builder()
.from((PerformException) error)
.withViewDescription(sb.toString())
.build();
}
if (error instanceof AssertionError) {
// reports Failure instead of Error.
// assertThat(…) throws an AssertionFailedError.
error = new AssertionFailedWithCauseError(error.getMessage(), error);
}
error.setStackTrace(Thread.currentThread().getStackTrace());
return error;
}
….
/**
* Checks whether animations and transitions are disabled on the current device.
*
* @param context The target's context.
*
* @return <code>true</code> if animations or transitions are disabled, else <code>false</code>.
*
*/
private static boolean isAnimationAndTransitionDisabled(Context context) {
ContentResolver resolver = context.getContentResolver();
boolean isTransitionAnimationDisabled = isEqualToZero(getTransitionAnimationScale(resolver));
boolean isWindowAnimationDisabled = isEqualToZero(getWindowAnimationScale(resolver));
boolean isAnimatorDisabled = isEqualToZero(getAnimatorDurationScale(resolver));
return isTransitionAnimationDisabled && isWindowAnimationDisabled && isAnimatorDisabled;
}
private static boolean isEqualToZero(float value) {
return Float.compare(Math.abs(value), 0.0f) == 0;
}
private static float getTransitionAnimationScale(ContentResolver resolver) {
return getSetting(resolver, Settings.Global.TRANSITION_ANIMATION_SCALE,
Settings.System.TRANSITION_ANIMATION_SCALE);
}
private static float getWindowAnimationScale(ContentResolver resolver) {
return getSetting(resolver, Settings.Global.WINDOW_ANIMATION_SCALE,
Settings.System.WINDOW_ANIMATION_SCALE);
}
private static float getAnimatorDurationScale(ContentResolver resolver) {
if (isJellyBeanMR1OrHigher()) {
return getSetting(resolver, Settings.Global.ANIMATOR_DURATION_SCALE,
Settings.System.ANIMATOR_DURATION_SCALE);
}
return 0f;
}
/**
* Compatibility wrapper for obtaining animation related settings.
*
* Gets an animation specific setting regardless of the API level the tests are running on.
*
* @param resolver The content resolver to use.
* @param current The setting name to use on {@link JELLY_BEAN_MR1} and above.
@see #getGlobalSetting(ContentResolver, String)
* @param deprecated The setting name to use up to {@link JELLY_BEAN_MR1}.
@see #getSystemSetting(ContentResolver, String)
*/
private static float getSetting(ContentResolver resolver, String current, String deprecated) {
if (isJellyBeanMR1OrHigher()) {
return getGlobalSetting(resolver, current);
} else {
return getSystemSetting(resolver, deprecated);
}
}

結局は、アニメーションをEspressoのsetupとかでOFFにはできないのですね。まだadbコマンドだけか。

Leave a Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.