Android - независимый инструмент тестирования пользовательского интерфейса Fragment

Я искал способ протестировать пользовательский интерфейс моих фрагментов отдельно (т.е. независимо от других фрагментов и действий), но я не могу найти способ сделать это.

В частности, допустим, что у меня есть фрагмент A, фрагмент B и фрагмент C. Единственный способ (по-видимому) перейти к фрагменту C - сначала пропустить фрагмент A и фрагмент B. Я ищу способ непосредственно проверить фрагмент C (возможно, издеваясь над его зависимостями, если таковой существует), без необходимости проходить через фрагменты A и B.

Инструменты, которые я исследовал до сих пор:

  • monkey: используется только для генерации псевдослучайных событий через командную строку. Не то, что я хочу.

  • monkeyrunner: он может запускать программы Python для отправки потоков событий в мое приложение для Android, но он не может напрямую нацеливаться на определенный фрагмент с этими сценариями.

  • Эспрессо: инструмент для тестирования белого ящика. Это приближается к тому, что я хочу, но по-прежнему требуется пройти через фрагменты A и B до достижения фрагмента C (т.е. Вам нужно запустить приложение, а затем тесты будут выполняться оттуда).

  • Пользовательский автомат: инструмент тестирования черного ящика. Это также близко, но опять же, оно требует прохождения через предыдущие фрагменты перед тестированием того, что я хочу (фрагмент C).

Есть ли способ напрямую проверить интерфейс Fragmen t?

Ответы

Ответ 1

Я использую пользовательские FragmentTestRule и эспрессо, чтобы изолировать каждый из моих Fragments.

У меня есть выделенный TestActivity, который показывает тестируемое Fragments в моем приложении. В моем случае Activity существует только в варианте debug, потому что мои контрольные тесты работают с debug.

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. Создайте AndroidManifest.xml для варианта debug и объявите 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. Создайте FragmentTestRule в варианте androidTest в 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;
    }
}

4. Затем вы можете протестировать 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()));
    }
}

Ответ 2

Вы можете использовать Robotium. Это для тестирования пользовательского интерфейса Android.

Ответ 3

Я разработал FragmentTestRule библиотеку Andorid, используя идею @thaussma, Это позволяет вам изолировать Fragment.

Вам просто нужно добавить это:

@Rule
public FragmentTestRule<?, FragmentWithoutActivityDependency> fragmentTestRule =
    FragmentTestRule.create(FragmentWithoutActivityDependency.class);

Дополнительная информация здесь.