独立于Android的片段UI测试工具
我一直在寻找一种方法来分别测试我的片段的UI(即,独立于其他片段和活动),但我找不到一种方法 特别是,假设我有片段A、片段B和片段C。进入片段C的唯一方法(应用程序方面)是首先通过片段A和片段B。我正在寻找一种直接测试片段C的方法(可能通过模拟其依赖关系,如果存在的话),而不必通过片段a和B 到目前为止,我调查的工具包括:独立于Android的片段UI测试工具,android,android-testing,android-espresso,android-uiautomator,Android,Android Testing,Android Espresso,Android Uiautomator,我一直在寻找一种方法来分别测试我的片段的UI(即,独立于其他片段和活动),但我找不到一种方法 特别是,假设我有片段A、片段B和片段C。进入片段C的唯一方法(应用程序方面)是首先通过片段A和片段B。我正在寻找一种直接测试片段C的方法(可能通过模拟其依赖关系,如果存在的话),而不必通过片段a和B 到目前为止,我调查的工具包括: monkey:仅用于通过命令行生成伪随机事件。不是我想要的 monkeyrunner:它可以运行Python程序将事件流发送到我的Android应用程序,但它不能直接用这些
- monkey:仅用于通过命令行生成伪随机事件。不是我想要的
- monkeyrunner:它可以运行Python程序将事件流发送到我的Android应用程序,但它不能直接用这些脚本将特定片段作为目标
- 浓缩咖啡:白盒测试工具。这接近于我想要的,但它仍然需要在到达片段C之前通过片段A和B(即,您需要启动应用程序,然后从那里运行测试)
- UI自动机:黑盒测试工具。这也很接近,但同样,它需要在测试我想要的片段(片段C)之前通过前面的片段
有什么方法可以直接测试Fragmen的UI吗?您可以使用。这是用于android UI测试的。我正在使用自定义的
FragmentTestRule
和浓缩咖啡来单独测试我的片段
我有一个专用的测试活动
,显示我的应用程序中测试的片段。在我的情况下,活动
只存在于调试
变量中,因为我的检测测试是针对调试
运行的
TL;博士使用令人敬畏的图书馆
1。在src/debug/java/your/package/TestActivity.java
中创建一个TestActivity
,并在内容视图中添加测试的片段
:
@VisibleForTesting
public class TestActivity extends AppCompatActivity {
@Override
protected void onCreate(@Nullable final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
FrameLayout frameLayout = new FrameLayout(this);
frameLayout.setId(R.id.container);
setContentView(frameLayout);
}
}
2。为debug
变量创建一个AndroidManifest.xml,并声明TestActivity
。测试时,需要启动测试活动
。将此清单添加到src/debug/AndroidManifest.xml
中的debug
变量:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<application>
<activity android:name="your.package.TestActivity"/>
</application>
</manifest>
4。然后您可以单独测试片段
:
public class MyFragmentTest {
@Rule
public FragmentTestRule<MyFragment> mFragmentTestRule = new FragmentTestRule<>(MyFragment.class);
@Test
public void fragment_can_be_instantiated() {
// Launch the activity to make the fragment visible
mFragmentTestRule.launchActivity(null);
// Then use Espresso to test the Fragment
onView(withId(R.id.an_id_in_the_fragment)).check(matches(isDisplayed()));
}
}
公共类MyFragmentTest{
@统治
公共FragmentTestRule MFFragmentTestRule=新的FragmentTestRule(MyFragment.class);
@试验
公共无效片段\u可以\u实例化(){
//启动活动以使片段可见
MFFragmentTestRule.launchActivity(null);
//然后用浓缩咖啡测试碎片
onView(使用id(R.id.an_id_在_片段中)).check(匹配项(isDisplayed());
}
}
我使用开发了一个android库。它允许您单独测试片段
您只需添加以下内容:
@Rule
public FragmentTestRule<?, FragmentWithoutActivityDependency> fragmentTestRule =
FragmentTestRule.create(FragmentWithoutActivityDependency.class);
@规则
public FragmentTestRule如果您正在使用导航架构组件,并且在应用程序中使用单个活动架构,则可以在测试开始时通过深入链接到目标片段(带有适当参数)来快速测试每个片段。
例如:
@Rule
@JvmField
var activityRule = ActivityTestRule(MainActivity::class.java)
protected fun launchFragment(destinationId: Int,
argBundle: Bundle? = null) {
val launchFragmentIntent = buildLaunchFragmentIntent(destinationId, argBundle)
activityRule.launchActivity(launchFragmentIntent)
}
private fun buildLaunchFragmentIntent(destinationId: Int, argBundle: Bundle?): Intent =
NavDeepLinkBuilder(InstrumentationRegistry.getInstrumentation().targetContext)
.setGraph(R.navigation.navigation)
.setComponentName(MainActivity::class.java)
.setDestination(destinationId)
.setArguments(argBundle)
.createTaskStackBuilder().intents[0]
destinationId是导航图中的片段目标id。下面是一个调用示例,一旦您准备好启动片段,就会执行该调用:
launchFragment(R.id.target_fragment, targetBundle())
private fun targetBundle(): Bundle? {
val bundle = Bundle()
bundle.putString(ARGUMENT_ID, "Argument needed by fragment")
return bundle
}
这样做将直接启动碎片。如果你的测试有效,那么这证明了当碎片深度链接到你的应用程序时,你的应用程序不会崩溃。它还可以确保应用程序在进程被系统终止时保持稳定,并尝试重建堆栈和重新启动片段。但是Robotium与UI Automator和Espresso存在相同的问题。为了测试片段C,我需要先通过片段A和B。我想要一个可以让我直接测试片段C的工具。因为我一直在使用robotium,它可以解决任何类型的UI测试问题。我不知道您需求的详细信息,所以请检查robotium API@Tiago。我希望waitForFragmentByTag、waitForFragmentById等API可以帮助您。祝你好运。唯一的“小”问题是,你的测试代码与生产性/运行时代码混合在一起(至少在调试版本中),当你向套件中添加更多测试时,这些代码很容易很快就会变得混乱:(如果没有更好的解决方案,可能的解决办法是在调试版本中只保留清单条目,并保留类(测试活动性、规则等)在里面androidTest@thaussma谢谢,这个解决方案也解决了我的问题。我只是想知道,在项目中添加测试活动
只是为了测试目的,这是一个好的做法吗?@Kavita\p:通常,您希望避免在生产代码中有任何仅测试的依赖项。将测试活动
添加到生产代码中会破坏这一点规则。我认为在这种情况下,好处大于(小)风险。它简单明了。我认为@Ewoks的评论夸大了一项活动的影响,然后暗示这可能会导致在生产中添加许多其他测试依赖项。这总是一个坏主意。。。
launchFragment(R.id.target_fragment, targetBundle())
private fun targetBundle(): Bundle? {
val bundle = Bundle()
bundle.putString(ARGUMENT_ID, "Argument needed by fragment")
return bundle
}