Android 测试失败后从ActivityTestRule重新启动活动

Android 测试失败后从ActivityTestRule重新启动活动,android,junit,android-testing,android-espresso,Android,Junit,Android Testing,Android Espresso,我已修改ActivityTestRule以重试执行失败的测试用例。每当测试失败时,我需要重新启动活动并重新运行执行。我已尝试调用mActivity.finish(),但当前活动未完成且未重新启动。但是测试重新开始了。我从一开始就采用这种方法 公共类MyActivityTestRule扩展ActivityTestRule{ 私人期末班mActivityClass; 私人活动; 私有静态最终字符串标记=“ActivityInstrumentationRule”; 私有布尔值mInitialTouch

我已修改ActivityTestRule以重试执行失败的测试用例。每当测试失败时,我需要重新启动活动并重新运行执行。我已尝试调用
mActivity.finish()
,但当前活动未完成且未重新启动。但是测试重新开始了。我从一开始就采用这种方法

公共类MyActivityTestRule扩展ActivityTestRule{
私人期末班mActivityClass;
私人活动;
私有静态最终字符串标记=“ActivityInstrumentationRule”;
私有布尔值mInitialTouchMode=false;
私用仪器;
公共MyActivityTestRule(类activityClass、布尔initialTouchMode、布尔启动活动){
超级(activityClass、initialTouchMode、launchActivity);
mActivityClass=活动类;
mInitialTouchMode=初始触摸模式;
mInstrumentation=InstrumentationRegistry.getInstrumentation();
}
@凌驾
公开声明应用(声明库、说明){
最后一个字符串testClassName=description.getClassName();
最终字符串testMethodName=description.getMethodName();
最终上下文=InstrumentationRegistry.getTargetContext();
/*android.support.test.espresso.espresso.setFailureHandler(新的FailureHandler(){
@重写公共无效句柄(可丢弃、可丢弃、匹配器匹配器){
if(AutomationTestCase.mEnableScreenshotOnFailure)
SpoonScreenshotOnFailure.perform(“espresso_断言_失败”,testClassName,testMethodName);
新的DefaultFailureHandler(context).handle(throwable,matcher);
}
});*/
//返回super.apply(基础、说明);
返回语句(基、描述);
}
专用报表(最终报表库、最终说明){
返回新语句(){
@凌驾
public void evaluate()可丢弃{
Throwable caughtThrowable=null;
//重试逻辑
对于(int i=0;i<3;i++){
试一试{
启动AppActivity(getActivityIntent());
base.evaluate();
返回;
}捕获(可丢弃的t){
caughtThrowable=t;
System.err.println(description.getDisplayName()+”:运行“+(i+1)+”失败);
完成活动();
}最后{
完成活动();
}
}
System.err.println(description.getDisplayName()+”:在“+3+”失败后放弃);
可抛可抛;
}
};
}
无效完成活动(){
if(mActivity!=null){
mActivity.finish();
mActivity=null;
}
}
公共T启动活动(@Nullable Intent startinent){
//设置初始触摸模式
Minstrutation.setInTouchMode(迷你触摸模式);
最后一个字符串targetPackage=mInstrumentation.getTargetContext().getPackageName();
//注入自定义意图(如果提供)
if(null==startinent){
startinent=getActivityIntent();
if(null==startinent){
w(标记“getActivityIntent()使用默认值返回null:”+
"意图(意图.行动));;
startIntent=新意图(意图、行动和主要目标);
}
}
setClassName(targetPackage,mActivityClass.getName());
startinent.addFlags(Intent.FLAG\u ACTIVITY\u NEW\u TASK);
Log.d(标记,字符串格式(“启动活动%s”),
mActivityClass.getName());
在活动启动()之前;
//以下强制转换是正确的,因为我们正在创建的活动与
//那个人进来了
mActivity=mActivityClass.cast(minstruement.startActivitySync(startinent));
waitForIdleSync();
启动后活动();
回报率;
}}

如果您的测试以不同于ActivityTestRule初始化为的活动结束,则必须关闭Backbackback中的所有活动。这个例子可能有助于:

public class MyActivityTestRule<T extends Activity> extends ActivityTestRule<T> {

private final Class<T> mActivityClass;
private T mActivity;
private static final String TAG = "ActivityInstrumentationRule";
private boolean mInitialTouchMode = false;
private Instrumentation mInstrumentation;


public MyActivityTestRule(Class<T> activityClass, boolean initialTouchMode, boolean launchActivity) {
    super(activityClass, initialTouchMode, launchActivity);
    mActivityClass = activityClass;
    mInitialTouchMode = initialTouchMode;
    mInstrumentation = InstrumentationRegistry.getInstrumentation();
}

@Override
public Statement apply(Statement base, Description description) {
    final String testClassName = description.getClassName();
    final String testMethodName = description.getMethodName();
    final Context context =  InstrumentationRegistry.getTargetContext();
   /* android.support.test.espresso.Espresso.setFailureHandler(new FailureHandler() {
        @Override public void handle(Throwable throwable, Matcher<View> matcher) {
            if(AutomationTestCase.mEnableScreenshotOnFailure)
            SpoonScreenshotOnFailure.perform("espresso_assertion_failed", testClassName, testMethodName);
            new DefaultFailureHandler(context).handle(throwable, matcher);
        }
    });*/
     // return super.apply(base, description);
     return statement(base, description);
}

private Statement statement(final Statement base, final Description description) {
    return new Statement() {
        @Override
        public void evaluate() throws Throwable {
            Throwable caughtThrowable = null;
            //retry logic
            for (int i = 0; i < 3; i++) {
                try {
                    launchAppActivity(getActivityIntent());
                    base.evaluate();
                    return;
                } catch (Throwable t) {
                    caughtThrowable = t;
                    System.err.println(description.getDisplayName() + ": run " + (i+1) + " failed");
                    finishActivity();
                } finally {
                    finishActivity();
            }
            }
            System.err.println(description.getDisplayName() + ": giving up after " + 3 + " failures");
            throw caughtThrowable;
        }
    };
}

void finishActivity() {
    if (mActivity != null) {
        mActivity.finish();
        mActivity = null;
    }
}

public T launchAppActivity(@Nullable Intent startIntent) {
    // set initial touch mode
    mInstrumentation.setInTouchMode(mInitialTouchMode);

    final String targetPackage = mInstrumentation.getTargetContext().getPackageName();
    // inject custom intent, if provided
    if (null == startIntent) {
        startIntent = getActivityIntent();
        if (null == startIntent) {
            Log.w(TAG, "getActivityIntent() returned null using default: " +
                    "Intent(Intent.ACTION_MAIN)");
            startIntent = new Intent(Intent.ACTION_MAIN);
        }
    }
    startIntent.setClassName(targetPackage, mActivityClass.getName());
    startIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    Log.d(TAG, String.format("Launching activity %s",
            mActivityClass.getName()));

    beforeActivityLaunched();
    // The following cast is correct because the activity we're creating is of the same type as
    // the one passed in
    mActivity = mActivityClass.cast(mInstrumentation.startActivitySync(startIntent));

    mInstrumentation.waitForIdleSync();

    afterActivityLaunched();
    return mActivity;
}}