如何将Android SingleLaunchActivityTestCase转换为ActivityTestRule?(仪器装置测试)

如何将Android SingleLaunchActivityTestCase转换为ActivityTestRule?(仪器装置测试),android,unit-testing,android-espresso,android-testing,android-instrumentation,Android,Unit Testing,Android Espresso,Android Testing,Android Instrumentation,的文档说明该类现在已被弃用,应替换为ActivityTestRule。但这是如何做到的 SingleLaunchActivityTestCase允许活动启动一次并保持打开状态;然后在此期间可以运行多个测试,然后关闭活动ActivityTestRule似乎没有此功能-它总是为每个@Test方法重新启动活动 那么,是否可以让ActivityTestRule启动一次活动并保持其打开状态,以及如何确保每个@Test函数的上下文(来自ActivityTestRule.getActivity())不为空 示

的文档说明该类现在已被弃用,应替换为
ActivityTestRule
。但这是如何做到的

SingleLaunchActivityTestCase
允许活动启动一次并保持打开状态;然后在此期间可以运行多个测试,然后关闭活动
ActivityTestRule
似乎没有此功能-它总是为每个@Test方法重新启动活动

那么,是否可以让
ActivityTestRule
启动一次活动并保持其打开状态,以及如何确保每个
@Test
函数的
上下文(来自
ActivityTestRule.getActivity()
)不为空

示例代码。

使用(将
launchActivity
参数设置为
false
)。然后在设置中使用,但不要在每个测试方法中使用。这样,您将自己启动一次,但每个测试将在同一实例上运行

您可能还希望在测试类结束时显式完成活动,以进行清理


注意:这通常不是测试的最佳实践,因为测试可能相互依赖(这不是一个好主意),或者根据运行顺序提供不正确的结果,等等。因为在这种情况下,活动状态从一个测试持续到下一个测试。

我使用Jon Adams answer以一个示例详细说明:

@RunWith(AndroidJUnit4.class)
@LargeTest
public class KeepActivityOpenDuringTests {

    @Rule
    public ActivityTestRule<MyActivity> activityTestRule =
            new ActivityTestRule<>(MyActivity.class, true, false);

    /**
     * When running the class as a test suite, setUp() is called repeatedly
     * for each test method. Use setupDone to prevent multiple setups.
     */
    private static boolean setupDone;
    // Static to persist across multiple tests
    private static Context context;
    private static MyActivity activityUnderTest;

    @Before
    public void setUp() throws Exception {
        // Launch the Activity manually, once, to get a real Context object.
        if (!setupDone) {
            activityUnderTest = activityTestRule.launchActivity(null);
            context = (Context) activityUnderTest;
            // continue setup of singletons...
            setupDone = true;
        }
    }

    @Test
    public void test1() {
        // Use context ...
    }

    @Test
    public void test2() {
       // Use activityUnderTest ...
    }

    @AfterClass
    public static void cleanUp() throws Exception {
        if (activityUnderTest != null) {
            activityUnderTest.finish();
            // Prevent any potential memory leaks
            activityUnderTest = null;
            context = null;
            setupDone = false;
        }
    }
}
@RunWith(AndroidJUnit4.class)
@最大的
公共类KeepactivityPenduringTests{
@统治
公共活动测试规则活动测试规则=
新的ActivityTestRule(MyActivity.class,true,false);
/**
*将类作为测试套件运行时,会重复调用setUp()
*对于每种测试方法。使用setupDone可防止多次设置。
*/
私有静态布尔设置完成;
//在多个测试中保持静态
私有静态语境;
私有静态MyActivity活动未测试;
@以前
public void setUp()引发异常{
//手动启动活动一次,以获取真实的上下文对象。
如果(!setupDone){
activityUnderTest=activityTestRule.launchActivity(null);
context=(context)activityUnderTest;
//继续设置单例。。。
setupDone=true;
}
}
@试验
公共void test1(){
//使用上下文。。。
}
@试验
公共无效测试2(){
//使用activityUnderTest。。。
}
@下课
public static void cleanUp()引发异常{
如果(activityUnderTest!=null){
activityUnderTest.finish();
//防止任何潜在的内存泄漏
activityUnderTest=null;
上下文=空;
setupDone=false;
}
}
}

当测试作为一个类或单独运行时,它的工作原理与SingleLaunchActivityTestCase类似。

请注意,只有当测试同步运行而不是并行运行时,这种测试才会工作,或者您可能会得到双重设置和/或不一致的活动状态。要明确的是,此代码确实完成了op的要求,但如上所述,这通常是一个不好的测试实践。在上课前使用
而不是检查非同步静态初始化切换是否更干净?@jondams有用的反馈,谢谢。也许我错了,但这真的被认为是坏习惯吗?它对于测试静态方法很有用,比如数据库访问,它需要在真实的设备/模拟器上使用真实的
上下文。以这种方式运行测试更高效、更快,而不是每次启动和停止
活动。它只是复制了SingleLaunchActivityTestCase的行为。可能不是讨论这个问题的最佳场所,但是,是的,快速版本是,这不是一个好主意,因为它增加了固定测试顺序和同步运行程序等要求,这会减慢速度并限制速度,并将测试相互联系起来,因为一个测试可能会根据它做什么或不做什么来设置(或中断)未来的测试,等等。这会使测试变得脆弱并相互依赖。再说一次,这没有错,只是一个坏习惯。不过,总体而言,集成测试是有效的。我指的是跨测试共享活动及其状态的做法是不好的做法。奇怪的是,我发现
activityUnderTest
test1()之后仍然强制
finish()
。活动在屏幕上不再可见,但
上下文仍处于活动状态。有两种方法尝试在每次测试后完成活动:
MonitoringInstrumentation.ActivityFinisher.run()
ActivityTestRule.finishActivity()
。从2020年9月起,有一个名为
ActivityScenarioRule
的新类,该类将取代
ActivityTestRule
。这可能会使这项技术变得更容易。更多信息: