Android - Independent Fragment UI测试工具

问题描述 投票:16回答:4

我一直在寻找一种方法来分别测试我的碎片的UI(即独立于其他碎片和活动),但我找不到办法。

特别是,假设我有片段A,片段B和片段C.进入片段C的唯一方法(应用方式)是首先通过片段A和片段B.我正在寻找一种直接测试Fragment C的方法(可能通过模拟它的依赖关系,如果存在的话),而不必通过Fragment A和B.

到目前为止我调查的工具:

  • monkey:仅用于通过命令行生成伪随机事件。不是我想要的。
  • monkeyrunner:它可以运行Python程序将事件流发送到我的Android应用程序,但它不能直接使用这些脚本定位特定的Fragment。
  • Espresso:白盒测试工具。这接近我想要的,但它仍然需要在到达片段C之前通过片段A和B(即,您需要启动您的应用程序,然后测试将从那里运行)。
  • UI Automator:黑盒测试工具。这也很接近,但同样,它需要在测试我想要的之前通过先前的片段(片段C)。

有没有办法直接测试片段的UI?

android android-testing android-espresso uiautomator android-uiautomator
4个回答
53
投票

我正在使用定制的FragmentTestRule和Espresso来隔离测试我的每个Fragments

我有一个专门的TestActivity,在我的应用程序中显示测试的Fragments。在我的情况下,Activity仅存在于debug变体中,因为我的仪器测试针对debug

TL; DR使用FragmentTestRule的真棒@brais-gabin库。

1.在TestActivity中创建一个src/debug/java/your/package/TestActivity.java,其内容视图将测试的Fragment添加到:

@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。这是测试时启动TestActivity所必需的。将此清单添加到debug中的src/debug/AndroidManifest.xml变体中:

<?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>

3.在FragmentTestRuleandroidTest变体中创建src/androidTest/java/your/test/package/FragmentTestRule.java

public class FragmentTestRule<F extends Fragment> extends ActivityTestRule<TestActivity> {

    private final Class<F> mFragmentClass;
    private F mFragment;

    public FragmentTestRule(final Class<F> fragmentClass) {
        super(TestActivity.class, true, false);
        mFragmentClass = fragmentClass;
    }

    @Override
    protected void afterActivityLaunched() {
        super.afterActivityLaunched();

        getActivity().runOnUiThread(() -> {
            try {
                //Instantiate and insert the fragment into the container layout
                FragmentManager manager = getActivity().getSupportFragmentManager();
                FragmentTransaction transaction = manager.beginTransaction();
                mFragment = mFragmentClass.newInstance();
                transaction.replace(R.id.container, mFragment);
                transaction.commit();
            } catch (InstantiationException | IllegalAccessException e) {
                Assert.fail(String.format("%s: Could not insert %s into TestActivity: %s",
                        getClass().getSimpleName(),
                        mFragmentClass.getSimpleName(),
                        e.getMessage()));
            }
        });
    }
    public F getFragment(){
        return mFragment;
    }
}

然后你可以孤立地测试Fragments

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()));
    }
}

3
投票

我使用qazxsw poi开发了qazxsw poi一个Android库。它允许您孤立地测试您的FragmentTestRules。

你只需要添加这个:

@thaussma's idea

Fragment


2
投票

你可以使用@Rule public FragmentTestRule<?, FragmentWithoutActivityDependency> fragmentTestRule = FragmentTestRule.create(FragmentWithoutActivityDependency.class); 。这是用于Android UI测试。


1
投票

如果您正在使用导航架构组件并且在应用程序中使用单个活动体系结构,则可以在测试开始时通过深度链接到目标片段(使用适当的参数)快速测试每个片段。

例如:

More information here

destinationId是导航图中的片段目标ID。以下是一旦您准备好启动片段就会执行的调用示例:

Robotium

这样做会直接启动片段。如果你的测试有效,那么证明你的应用程序在片段深层链接时不会崩溃。如果进程被系统杀死并且它尝试重建堆栈并重新启动片段,它还可以确保应用程序稳定。

© www.soinside.com 2019 - 2024. All rights reserved.