问题
I'm not very experienced with Espresso, but I finally succeed to run it.
I have an app that need to be shrink by Proguard in order to be under the 56K methods.
The app starts with a 3 sec animation, so I need to wait until this animation is over in order to continue. This is what I tried to do with the method waitFor(long delay)
I tried to put this method as a standalone class, inner class and even project class = same error.
Here is the Proguard file:
android {
...
compileSdkVersion ANDROID_BUILD_SDK_VERSION
buildToolsVersion ANDROID_BUILD_TOOLS_VERSION
productFlavors {
// Define separate dev and prod product flavors.
dev {
// dev utilizes minSDKVersion = 21 to allow the Android gradle plugin
// to pre-dex each module and produce an APK that can be tested on
// Android Lollipop without time consuming dex merging processes.
minSdkVersion 21
}
prod {
// The actual minSdkVersion for the application.
minSdkVersion ANDROID_BUILD_MIN_SDK_VERSION
}
}
defaultConfig {
applicationId "fr.xs.app.y"
targetSdkVersion ANDROID_BUILD_TARGET_SDK_VERSION
minSdkVersion ANDROID_BUILD_MIN_SDK_VERSION
versionCode ANDROID_BUILD_VERSION_CODE
versionName ANDROID_BUILD_APP_VERSION_NAME
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
// point sur le build de test
testBuildType = "validation"
buildTypes {
release {
debuggable false
ext.enableCrashlytics = true
renderscriptOptimLevel 3
signingConfig android.signingConfigs.release
zipAlignEnabled true
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules-release.pro'
}
debug {
debuggable true
renderscriptOptimLevel 3
applicationIdSuffix ".debug"
versionNameSuffix "debug"
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules-debug.pro', 'proguard-rules-dontobfuscate.pro'
}
validation.initWith(debug)
validation {
debuggable false
renderscriptOptimLevel 3
applicationIdSuffix ".validation"
versionNameSuffix "validation"
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules-debug.pro', 'proguard-rules-dontobfuscate.pro'
testProguardFile('proguard-rules-test.pro')
}
}
...
}
Proguard Configuration
The following in is both Proguard files (debug and test) -keep class fr.xs.app.y.** { *; } -dontobfuscate
I checked that this class is in the mapping.txt (build/output/mapping/androidTest/dev) and not transformed to another string.
Here is the Test Class:
import android.app.Activity;
import android.support.test.espresso.Espresso;
import android.support.test.espresso.IdlingPolicies;
import android.support.test.espresso.IdlingResource;
import android.support.test.espresso.core.deps.guava.collect.Iterables;
import android.support.test.espresso.matcher.ViewMatchers;
import android.support.test.rule.ActivityTestRule;
import android.support.test.runner.AndroidJUnit4;
import android.support.test.runner.lifecycle.ActivityLifecycleMonitorRegistry;
import android.support.test.runner.lifecycle.Stage;
import android.test.suitebuilder.annotation.LargeTest;
import com.squareup.spoon.Spoon;
import org.apache.commons.lang3.StringUtils;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import java.util.concurrent.TimeUnit;
import fr.xs.app.y.Activity.SplashScreenActivity;
import static android.support.test.InstrumentationRegistry.getInstrumentation;
import static android.support.test.espresso.Espresso.onView;
import static android.support.test.espresso.action.ViewActions.click;
import static android.support.test.espresso.assertion.ViewAssertions.matches;
import static android.support.test.espresso.matcher.ViewMatchers.isCompletelyDisplayed;
import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
import static android.support.test.espresso.matcher.ViewMatchers.withEffectiveVisibility;
import static android.support.test.espresso.matcher.ViewMatchers.withId;
import static android.support.test.espresso.matcher.ViewMatchers.withText;
import static org.hamcrest.CoreMatchers.allOf;
@RunWith(AndroidJUnit4.class)
@LargeTest
public class HelloWorldEspressoTest {
@Rule
public ActivityTestRule<SplashScreenActivity> mActivityRule = new ActivityTestRule<>(SplashScreenActivity.class);
@Test
public void seeHomeScreen() throws Throwable {
// SpashScreen
takeScreenShot("Chargement Application");
onView(allOf(withText("Réveille l'amateur qui est en toi"),
withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE)))
.check(matches(isCompletelyDisplayed()));
takeScreenShot("Splash Screen en cours");
waitForDelay(3000);
takeScreenShot("Splash Screen à la fin");
// HomeScree
onView(allOf(withText("Nouvelle Dégustation"),
withEffectiveVisibility(ViewMatchers.Visibility.VISIBLE)))
.check(matches(isCompletelyDisplayed()));
takeScreenShot("Home Screen");
// Preference
onView(withId(R.id.iv_seeParameters)).perform(click());
onView(withId(R.id.content_frame_sign_unsign)).check(matches(isDisplayed()));
takeScreenShot("Preferences Screen");
Activity getCurrentActivity() throws Throwable {
getInstrumentation().waitForIdleSync();
final Activity[] activity = new Activity[1];
getInstrumentation().runOnMainSync(new Runnable() {
@Override
public void run() {
java.util.Collection activites = ActivityLifecycleMonitorRegistry.getInstance().getActivitiesInStage(Stage.RESUMED);
activity[0] = (Activity) Iterables.getOnlyElement(activites);
}
});
return activity[0];
}
private static void waitForDelay(long waitingTime) {
// Make sure Espresso does not time out
IdlingPolicies.setMasterPolicyTimeout(waitingTime * 2, TimeUnit.MILLISECONDS);
IdlingPolicies.setIdlingResourceTimeout(waitingTime * 2, TimeUnit.MILLISECONDS);
// Now we wait
IdlingResource idlingResource = new ElapsedTimeIdlingResource(waitingTime);
Espresso.registerIdlingResources(idlingResource);
// Clean up
Espresso.unregisterIdlingResources(idlingResource);
}
private void takeScreenShot(String title) throws Throwable {
String string = StringUtils.stripAccents(title).replace(" ", "_");
Spoon.screenshot(getCurrentActivity(), string);
}
static class ElapsedTimeIdlingResource implements IdlingResource {
private final long startTime;
private final long waitingTime;
private ResourceCallback resourceCallback;
public ElapsedTimeIdlingResource(long waitingTime) {
this.startTime = System.currentTimeMillis();
this.waitingTime = waitingTime;
}
@Override
public String getName() {
return ElapsedTimeIdlingResource.class.getName() + ":" + waitingTime;
}
@Override
public boolean isIdleNow() {
long elapsed = System.currentTimeMillis() - startTime;
boolean idle = (elapsed >= waitingTime);
if (idle) {
resourceCallback.onTransitionToIdle();
}
return idle;
}
@Override
public void registerIdleTransitionCallback(ResourceCallback resourceCallback) {
this.resourceCallback = resourceCallback;
}
}
}
Here is the log:
04-26 10:15:52.322 ? D/LifecycleMonitor: Lifecycle status change: fr.xs.app.y.Activity.SplashScreenActivity@6f8513d in: PAUSED 04-26 10:15:52.322 ? D/LifecycleMonitor: Lifecycle status change: fr.xs.app.y.Activity.SplashScreenActivity@6f8513d in: RESUMED 04-26 10:15:52.702 ? D/ActivityManager: bindService callerProcessName:fr.xs.app.y.validation, calleePkgName: com.google.android.gms, action: com.google.android.gms.analytics.service.START 04-26 10:15:53.012 ? I/ActivityManager: Displayed fr.xs.app.y.validation/fr.xs.app.y.Activity.SplashScreenActivity: +1s745ms (total +36m45s584ms) 04-26 10:15:53.762 ? I/Timeline: Timeline: Activity_windows_visible id: ActivityRecord{2b3eacb1 u0 fr.xs.app.y.validation/fr.xs.app.y.Activity.SplashScreenActivity t5952} time:259410459 04-26 10:15:54.592 ? I/art: Rejecting re-init on previously-failed class java.lang.Class 04-26 10:15:54.622 ? I/TestRunner: failed: seeHomeScreen(fr.xs.app.y.HelloWorldEspressoTest) 04-26 10:15:54.622 ? I/TestRunner: java.lang.NoClassDefFoundError: fr.xs.app.y.HelloWorldEspressoTest$ElapsedTimeIdlingResource at fr.xs.app.y.HelloWorldEspressoTest.waitForDelay(HelloWorldEspressoTest.java:166) at fr.xs.app.y.HelloWorldEspressoTest.seeHomeScreen(HelloWorldEspressoTest.java:56) at java.lang.reflect.Method.invoke(Native Method) at java.lang.reflect.Method.invoke(Method.java:372) at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50) at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47) at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) at android.support.test.internal.statement.UiThreadStatement.evaluate(UiThreadStatement.java:55) at android.support.test.rule.ActivityTestRule$ActivityStatement.evaluate(ActivityTestRule.java:270) at org.junit.rules.RunRules.evaluate(RunRules.java:20) at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57) at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) at org.junit.runners.ParentRunner.run(ParentRunner.java:363) at org.junit.runners.Suite.runChild(Suite.java:128) at org.junit.runners.Suite.runChild(Suite.java:27) at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) at org.junit.runners.ParentRunner.run(ParentRunner.java:363) at org.junit.runner.JUnitCore.run(JUnitCore.java:137) at org.junit.runner.JUnitCore.run(JUnitCore.java:115) at android.support.test.internal.runner.TestExecutor.execute(TestExecutor.java:59) at android.support.test.runner.AndroidJUnitRunner.onStart(AndroidJUnitRunner.java:262) at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:1873) 04-26 10:15:54.622 ? I/TestRunner: finished: seeHomeScreen(fr.xs.app.y.HelloWorldEspressoTest) 04-26 10:15:54.642 ? D/LifecycleMonitor: Lifecycle status change: fr.xs.app.y.Activity.SplashScreenActivity@6f8513d in: PAUSED 04-26 10:15:54.672 ? I/TestRunner: started: initializationError(fr.xs.app.y.suites.system.LogSupportUser) 04-26 10:15:54.732 ? I/TestRunner: failed: initializationError(fr.xs.app.y.suites.system.LogSupportUser) 04-26 10:15:54.732 ? I/TestRunner: finished: initializationError(fr.xs.app.y.suites.system.LogSupportUser) 04-26 10:15:55.692 ? D/KidsModeInstallReceiver: onReceive intent data = package:fr.xs.app.y.validation.test 04-26 10:15:56.752 ? E/SPPClientService: [PackageInfoChangeReceiver] [handlePkgRemovedEvent] PackageName : fr.xs.app.y.validation.test, true, false 04-26 10:15:56.932 ? D/LifecycleMonitor: Lifecycle status change: fr.xs.app.y.Activity.SplashScreenActivity@6f8513d in: STOPPED 04-26 10:15:56.932 ? D/LifecycleMonitor: Lifecycle status change: fr.xs.app.y.Activity.SplashScreenActivity@6f8513d in: DESTROYED 04-26 10:15:57.302 ? I/ActivityManager: Force stopping fr.xs.app.y.validation appid=10582 user=0: finished inst
no way to run it until now !
来源:https://stackoverflow.com/questions/36859528/java-lang-noclassdeffounderror-with-espresso-and-proguard