wake-up-neo.com

Gerätetest ein Android-Fragment

Ich möchte eine Android-Fragment-Klasse testen.

Kann ich einen Test mit AndroidTestCase einrichten oder muss ich ApplicationTestCase verwenden?

Gibt es nützliche Beispiele, wie diese beiden Testfälle verwendet werden können? Die Testbeispiele auf der Entwicklerseite sind minimal und scheinen sich nur auf Testaktivitäten zu konzentrieren.

Alles, was ich an anderer Stelle gefunden habe, sind Beispiele, bei denen die AndroidTestCase-Klasse erweitert ist, aber alles, was getestet wurde, ist das Addieren von zwei Zahlen. Wenn der Kontext verwendet wird, wird nur ein einfacher Abruf durchgeführt, und es wird getestet, dass etwas nicht null ist.

Nach meinem Verständnis muss ein Fragment innerhalb einer Aktivität leben. Könnte ich also eine Scheinaktivität erstellen oder die Anwendung oder den Kontext aufrufen, um eine Aktivität bereitzustellen, in der ich mein Fragment testen kann?

Muss ich meine eigene Aktivität erstellen und dann ActivityUnitTestCase verwenden?

Danke für deine Hilfe.

Trev

36
Trev Sorbie

Ich hatte mit derselben Frage zu kämpfen. Insbesondere, da die meisten Codebeispiele bereits veraltet sind + Android Studio/SDKs verbessert werden, sodass alte Antworten manchmal nicht mehr relevant sind.

Das Wichtigste zuerst: Sie müssen festlegen, ob Sie Instrumental oder einfache JUnit -Tests verwenden möchten.

Der Unterschied zwischen ihnen wurde von S.D. here ; Kurz gesagt: JUnit-Tests sind leichter und erfordern keinen Emulator. Instrumental - gibt Ihnen die größtmögliche Erfahrung mit dem tatsächlichen Gerät (Sensoren, GPS, Interaktion mit anderen Apps usw.). Lesen Sie auch mehr über Testing in Android .

1. JUnit-Test von Fragmenten

Nehmen wir an, Sie brauchen keine schweren instrumentellen Tests und einfache Junit-Tests sind ausreichend .. Ich verwende dazu Nice framework Robolectric .

In gradle hinzufügen:

dependencies {
    .....
    testCompile 'junit:junit:4.12'
    testCompile 'org.robolectric:robolectric:3.0'
    testCompile "org.mockito:mockito-core:1.10.8"
    testCompile ('com.squareup.assertj:assertj-Android:1.0.0') {
        exclude module: 'support-annotations'
    }
    .....
}

Mockito, AsserJ sind optional, aber ich fand sie sehr nützlich, daher empfehle ich dringend, sie auch einzubeziehen.

Dann legen Sie in Build-VariantenUnit-Tests als Test-Artefakt: fest. enter image description here

Nun ist es an der Zeit, einige echte Tests zu schreiben: -) Nehmen wir als Beispiel das Standardprojekt "Leere Aktivität mit Fragment".

Ich habe ein paar Zeilen Code hinzugefügt, um tatsächlich etwas zu testen:

import Android.os.Bundle;
import Android.support.v4.app.Fragment;
import Android.view.LayoutInflater;
import Android.view.View;
import Android.view.ViewGroup;
import Java.util.ArrayList;
import Java.util.List;

public class MainActivityFragment extends Fragment {

    private List<Cow> cows;
    public MainActivityFragment() {}

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {   
        cows = new ArrayList<>();
        cows.add(new Cow("Burka", 10));
        cows.add(new Cow("Zorka", 9));
        cows.add(new Cow("Kruzenshtern", 15));

        return inflater.inflate(R.layout.fragment_main, container, false);
    }

    int calculateYoungCows(int maxAge) {
        if (cows == null) {
            throw new IllegalStateException("onCreateView hasn't been called");
        }

        if (getActivity() == null) {
            throw new IllegalStateException("Activity is null");
        }

        if (getView() == null) {
            throw new IllegalStateException("View is null");
        }

        int result = 0;
        for (Cow cow : cows) {
            if (cow.age <= maxAge) {
                result++;
            }
        }

        return result;
    }
}

Und Klasse Kuh:

public class Cow {
    public String name;
    public int age;

    public Cow(String name, int age) {
        this.name = name;
        this.age = age;
    }
}

Der Testsatz des Robolectic würde ungefähr so ​​aussehen:

import Android.app.Application;
import Android.support.v4.app.Fragment;
import Android.support.v4.app.FragmentManager;
import Android.support.v4.app.FragmentTransaction;
import Android.test.ApplicationTestCase;

import junit.framework.Assert;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.Robolectric;
import org.robolectric.RobolectricGradleTestRunner;
import org.robolectric.annotation.Config;

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

@RunWith(RobolectricGradleTestRunner.class)
@Config(constants = BuildConfig.class, sdk=21)
public class MainActivityFragmentTest extends ApplicationTestCase<Application> {

    public MainActivityFragmentTest() {
        super(Application.class);
    }

    MainActivity mainActivity;
    MainActivityFragment mainActivityFragment;

    @Before
    public void setUp() {
        mainActivity = Robolectric.setupActivity(MainActivity.class);
        mainActivityFragment = new MainActivityFragment();
        startFragment(mainActivityFragment);
    }

    @Test
    public void testMainActivity() {
        Assert.assertNotNull(mainActivity);
    }

    @Test
    public void testCowsCounter() {
        assertThat(mainActivityFragment.calculateYoungCows(10)).isEqualTo(2);
        assertThat(mainActivityFragment.calculateYoungCows(99)).isEqualTo(3);
    }

    private void startFragment( Fragment fragment ) {
        FragmentManager fragmentManager = mainActivity.getSupportFragmentManager();
        FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
        fragmentTransaction.add(fragment, null );
        fragmentTransaction.commit();
    }
}

Das heißt Wir erzeugen Aktivität über Robolectric.setupActivity, ein neues Fragment in setUp () der Testklassen. Optional können Sie das Fragment sofort mit setUp () starten oder direkt aus dem Test heraus. 

NB! Ich habe zu nicht viel Zeit damit verbracht, aber es scheint fast unmöglich, es mit Dagger zusammenzubinden (ich weiß nicht, ob es mit Dagger2 einfacher ist), da Sie es nicht können Benutzerdefinierte Testanwendung mit gespielten Injektionen einstellen.

2. Instrumentelle Prüfung von Fragmenten

Die Komplexität dieses Ansatzes hängt stark davon ab, ob Sie in der App, die Sie testen möchten, Dagger/Dependency-Injektion verwenden.

In Build-Varianten geben Sie Android Instrumental Tests als Test-Artefakt: an. enter image description here

In Gradle füge ich folgende Abhängigkeiten hinzu:

dependencies {
    .....
    androidTestCompile "com.google.dexmaker:dexmaker:1.1"
    androidTestCompile "com.google.dexmaker:dexmaker-mockito:1.1"
    androidTestCompile 'com.squareup.assertj:assertj-Android:1.0.0'
    androidTestCompile "org.mockito:mockito-core:1.10.8"
    }
    .....
}

(wiederum sind fast alle von ihnen optional, aber sie können Ihr Leben so viel einfacher machen)

- Wenn Sie keinen Dolch haben

Dies ist ein glücklicher Weg. Der Unterschied zu Robolectric besteht nur in kleinen Details.

Pre-step 1: Wenn Sie Mockito verwenden, müssen Sie es mit diesem Hack auf den Geräten und Emulatoren ausführen lassen:

public class TestUtils {
    private static final String CACHE_DIRECTORY = "/data/data/" + BuildConfig.APPLICATION_ID + "/cache";
    public static final String DEXMAKER_CACHE_PROPERTY = "dexmaker.dexcache";

    public static void enableMockitoOnDevicesAndEmulators() {
        if (System.getProperty(DEXMAKER_CACHE_PROPERTY) == null || System.getProperty(DEXMAKER_CACHE_PROPERTY).isEmpty()) {
            File file = new File(CACHE_DIRECTORY);
            if (!file.exists()) {
                final boolean success = file.mkdirs();
                if (!success) {
                    fail("Unable to create cache directory required for Mockito");
                }
            }

            System.setProperty(DEXMAKER_CACHE_PROPERTY, file.getPath());
        }
    }
}

Das MainActivityFragment bleibt wie oben. Das Test-Set würde also so aussehen:

package com.klogi.myapplication;

import Android.support.v4.app.Fragment;
import Android.support.v4.app.FragmentManager;
import Android.support.v4.app.FragmentTransaction;
import Android.test.ActivityInstrumentationTestCase2;

import junit.framework.Assert;

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

public class MainActivityFragmentTest extends ActivityInstrumentationTestCase2<MainActivity> {

    public MainActivityFragmentTest() {
        super(MainActivity.class);
    }

    MainActivity mainActivity;
    MainActivityFragment mainActivityFragment;

    @Override
    protected void setUp() throws Exception {
        TestUtils.enableMockitoOnDevicesAndEmulators();
        mainActivity = getActivity();
        mainActivityFragment = new MainActivityFragment();
    }

    public void testMainActivity() {
        Assert.assertNotNull(mainActivity);
    }

    public void testCowsCounter() {
        startFragment(mainActivityFragment);
        assertThat(mainActivityFragment.calculateYoungCows(10)).isEqualTo(2);
        assertThat(mainActivityFragment.calculateYoungCows(99)).isEqualTo(3);
    }

    private void startFragment( Fragment fragment ) {
        FragmentManager fragmentManager = mainActivity.getSupportFragmentManager();
        FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
        fragmentTransaction.add(fragment, null);
        fragmentTransaction.commit();

        getActivity().runOnUiThread(new Runnable() {
            @Override
            public void run() {
                getActivity().getSupportFragmentManager().executePendingTransactions();
            }
        });

        getInstrumentation().waitForIdleSync();
    }

}

Wie Sie sehen, ist die Test-Klasse eine Erweiterung der Klasse ActivityInstrumentationTestCase2. Außerdem ist es sehr wichtig, auf die Methode startFragment zu achten, die sich im Vergleich zum JUnit-Beispiel geändert hat: Standardmäßig werden Tests nicht auf dem UI-Thread ausgeführt und wir müssen die ausstehende FragmentManager-Ausführung explizit aufrufen Transaktionen.

- Wenn Sie Dolch haben

Hier wird es ernst :-)

Zunächst werden wir die ActivityInstrumentationTestCase2 zugunsten der ActivityUnitTestCase-Klasse als Basisklasse für alle Testklassen des Fragments los.

Wie üblich ist es nicht so einfach und es gibt mehrere Fallstricke ( das ist eines von Beispielen). Also müssen wir AcitivityUnitTestCase auf ActivityUnitTestCaseOverride pimpen.

Es ist ein bisschen zu lang, um es vollständig hier zu posten, also lade ich die Vollversion davon nach github ;

public abstract class ActivityUnitTestCaseOverride<T extends Activity>
        extends ActivityUnitTestCase<T> {

    ........
    private Class<T> mActivityClass;

    private Context mActivityContext;
    private Application mApplication;
    private MockParent mMockParent;

    private boolean mAttached = false;
    private boolean mCreated = false;

    public ActivityUnitTestCaseOverride(Class<T> activityClass) {
        super(activityClass);
        mActivityClass = activityClass;
    }

    @Override
    public T getActivity() {
        return (T) super.getActivity();
    }

    @Override
    protected void setUp() throws Exception {
        super.setUp();

        // default value for target context, as a default
        mActivityContext = getInstrumentation().getTargetContext();
    }

    /**
     * Start the activity under test, in the same way as if it was started by
     * {@link Android.content.Context#startActivity Context.startActivity()}, providing the
     * arguments it supplied.  When you use this method to start the activity, it will automatically
     * be stopped by {@link #tearDown}.
     * <p/>
     * <p>This method will call onCreate(), but if you wish to further exercise Activity life
     * cycle methods, you must call them yourself from your test case.
     * <p/>
     * <p><i>Do not call from your setUp() method.  You must call this method from each of your
     * test methods.</i>
     *
     * @param intent                       The Intent as if supplied to {@link Android.content.Context#startActivity}.
     * @param savedInstanceState           The instance state, if you are simulating this part of the life
     *                                     cycle.  Typically null.
     * @param lastNonConfigurationInstance This Object will be available to the
     *                                     Activity if it calls {@link Android.app.Activity#getLastNonConfigurationInstance()}.
     *                                     Typically null.
     * @return Returns the Activity that was created
     */
    protected T startActivity(Intent intent, Bundle savedInstanceState,
                              Object lastNonConfigurationInstance) {
        assertFalse("Activity already created", mCreated);

        if (!mAttached) {
            assertNotNull(mActivityClass);
            setActivity(null);
            T newActivity = null;
            try {
                IBinder token = null;
                if (mApplication == null) {
                    setApplication(new MockApplication());
                }
                ComponentName cn = new ComponentName(getInstrumentation().getTargetContext(), mActivityClass.getName());
                intent.setComponent(cn);
                ActivityInfo info = new ActivityInfo();
                CharSequence title = mActivityClass.getName();
                mMockParent = new MockParent();
                String id = null;

                newActivity = (T) getInstrumentation().newActivity(mActivityClass, mActivityContext,
                        token, mApplication, intent, info, title, mMockParent, id,
                        lastNonConfigurationInstance);
            } catch (Exception e) {
                assertNotNull(newActivity);
            }

            assertNotNull(newActivity);
            setActivity(newActivity);

            mAttached = true;
        }

        T result = getActivity();
        if (result != null) {
            getInstrumentation().callActivityOnCreate(getActivity(), savedInstanceState);
            mCreated = true;
        }
        return result;
    }

    protected Class<T> getActivityClass() {
        return mActivityClass;
    }

    @Override
    protected void tearDown() throws Exception {

        setActivity(null);

        // Scrub out members - protects against memory leaks in the case where someone
        // creates a non-static inner class (thus referencing the test case) and gives it to
        // someone else to hold onto
        scrubClass(ActivityInstrumentationTestCase.class);

        super.tearDown();
    }

    /**
     * Set the application for use during the test.  You must call this function before calling
     * {@link #startActivity}.  If your test does not call this method,
     *
     * @param application The Application object that will be injected into the Activity under test.
     */
    public void setApplication(Application application) {
        mApplication = application;
    }
    .......
}

Erstellen Sie einen abstrakten AbstractFragmentTest für alle Ihre Fragmenttests:

import Android.app.Activity;
import Android.content.Intent;
import Android.content.pm.ActivityInfo;
import Android.content.res.Configuration;
import Android.support.v4.app.Fragment;
import Android.support.v4.app.FragmentManager;
import Android.support.v4.app.FragmentTransaction;

/**
 * Common base class for {@link Fragment} tests.
 */
public abstract class AbstractFragmentTest<TFragment extends Fragment, TActivity extends FragmentActivity> extends ActivityUnitTestCaseOverride<TActivity> {

    private TFragment fragment;
    protected MockInjectionRegistration mocks;

    protected AbstractFragmentTest(TFragment fragment, Class<TActivity> activityType) {
        super(activityType);
        this.fragment = parameterIsNotNull(fragment);
    }

    @Override
    protected void setActivity(Activity testActivity) {
        if (testActivity != null) {
            testActivity.setTheme(R.style.AppCompatTheme);
        }

        super.setActivity(testActivity);
    }

    /**
     * Get the {@link Fragment} under test.
     */
    protected TFragment getFragment() {
        return fragment;
    }

    protected void setUpActivityAndFragment() {
        createMockApplication();

        final Intent intent = new Intent(getInstrumentation().getTargetContext(),
                getActivityClass());
        startActivity(intent, null, null);
        startFragment(getFragment());

        getInstrumentation().callActivityOnStart(getActivity());
        getInstrumentation().callActivityOnResume(getActivity());
    }

    private void createMockApplication() {
        TestUtils.enableMockitoOnDevicesAndEmulators();

        mocks = new MockInjectionRegistration();
        TestApplication testApplication = new TestApplication(getInstrumentation().getTargetContext());
        testApplication.setModules(mocks);
        testApplication.onCreate();
        setApplication(testApplication);
    }

    private void startFragment(Fragment fragment) {
        FragmentManager fragmentManager = getActivity().getSupportFragmentManager();
        FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
        fragmentTransaction.add(fragment, null);
        fragmentTransaction.commit();
    }
}

Hier sind einige wichtige Dinge.

1) Wir setzen die Methode setActivity ()} außer Kraft, um das AppCompact-Design auf die Aktivität festzulegen. Ohne das wird der Testanzug abstürzen.

2) setUpActivityAndFragment () - Methode:

I. erstellt Aktivität (=> getActivity () beginnt, in Tests und in der zu testenden App einen Wert ungleich Null zurückzugeben) 1) onCreate () der aufgerufenen Aktivität;

2) onStart () der aufgerufenen Aktivität;

3) onResume () der aufgerufenen Aktivität;

II. Hängt an und beginnt mit der Aktivität zu fragmentieren

1) onAttach () des Fragments aufgerufen;

2) onCreateView () des Fragments aufgerufen;

3) onStart () des Fragments aufgerufen;

4) onResume () des Fragments aufgerufen;

3) createMockApplication () -Methode: Wie in der Nicht-Dolch-Version aktivieren wir in Vor-Schritt 1 das Mocking auf den Geräten und auf den Emulatoren.

Dann ersetzen wir die normale Anwendung durch ihre Injektionen durch unsere benutzerdefinierte TestApplication!

MockInjectionRegistration sieht folgendermaßen aus:

....
import javax.inject.Singleton;

import dagger.Module;
import dagger.Provides;
import de.greenrobot.event.EventBus;

import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

@Module(
        injects = {

                ....
                MainActivity.class,
                MyWorkFragment.class,
                HomeFragment.class,
                ProfileFragment.class,
                ....
        },
        addsTo = DelveMobileInjectionRegistration.class,
        overrides = true
)
public final class MockInjectionRegistration {

    .....
    public DataSource dataSource;
    public EventBus eventBus;
    public MixpanelAPI mixpanel;
    .....

    public MockInjectionRegistration() {
        .....
        dataSource = mock(DataSource.class);
        eventBus = mock(EventBus.class);
        mixpanel = mock(MixpanelAPI.class);
        MixpanelAPI.People mixpanelPeople = mock(MixpanelAPI.People.class);
        when(mixpanel.getPeople()).thenReturn(mixpanelPeople);
        .....
    }
...........
    @Provides
    @Singleton
    @SuppressWarnings("unused")
        // invoked by Dagger
    DataSource provideDataSource() {
        Guard.valueIsNotNull(dataSource);
        return dataSource;
    }

    @Provides
    @Singleton
    @SuppressWarnings("unused")
        // invoked by Dagger
    EventBus provideEventBus() {
        Guard.valueIsNotNull(eventBus);
        return eventBus;
    }

    @Provides
    @Singleton
    @SuppressWarnings("unused")
        // invoked by Dagger
    MixpanelAPI provideMixpanelAPI() {
        Guard.valueIsNotNull(mixpanel);
        return mixpanel;
    }
.........
}

Das heißt Anstelle von echten Klassen stellen wir den Fragmenten ihre verspotteten Versionen zur Verfügung. (Das ist leicht nachvollziehbar, ermöglicht das Konfigurieren von Ergebnissen von Methodenaufrufen usw.).

Und die TestApplication ist nur Ihre benutzerdefinierte Erweiterung von Application, die das Setzen von Modulen unterstützen und die ObjectGraph initialisieren sollte.

Dies waren die ersten Schritte zum Schreiben der Tests :) Nun der einfache Teil, die eigentlichen Tests:

public class SearchFragmentTest extends AbstractFragmentTest<SearchFragment, MainActivity> {

    public SearchFragmentTest() {
        super(new SearchFragment(), MainActivity.class);
    }

    @UiThreadTest
    public void testOnCreateView() throws Exception {
        setUpActivityAndFragment();

        SearchFragment searchFragment = getFragment();
        assertNotNull(searchFragment.adapter);
        assertNotNull(SearchFragment.getSearchAdapter());
        assertNotNull(SearchFragment.getSearchSignalLogger());
    }

    @UiThreadTest
    public void testOnPause() throws Exception {
        setUpActivityAndFragment();

        SearchFragment searchFragment = getFragment();
        assertTrue(Strings.isNullOrEmpty(SharedPreferencesTools.getString(getActivity(), SearchFragment.SEARCH_STATE_BUNDLE_ARGUMENT)));

        searchFragment.searchBoxRef.setCurrentConstraint("abs");
        searchFragment.onPause();

        assertEquals(searchFragment.searchBoxRef.getCurrentConstraint(), SharedPreferencesTools.getString(getActivity(), SearchFragment.SEARCH_STATE_BUNDLE_ARGUMENT));
    }

    @UiThreadTest
    public void testOnQueryTextChange() throws Exception {
        setUpActivityAndFragment();
        reset(mocks.eventBus);

        getFragment().onQueryTextChange("Donald");
        Thread.sleep(300);

        // Should be one cached, one uncached event
        verify(mocks.eventBus, times(2)).post(isA(SearchRequest.class));
        verify(mocks.eventBus).post(isA(SearchLoadingIndicatorEvent.class));
    }

    @UiThreadTest
    public void testOnQueryUpdateEventWithDifferentConstraint() throws Exception {
        setUpActivityAndFragment();

        reset(mocks.eventBus);

        getFragment().onEventMainThread(new SearchResponse(new ArrayList<>(), "Donald", false));

        verifyNoMoreInteractions(mocks.eventBus);
    }
    ....
}

Das ist es! Jetzt haben Sie für Ihre Fragmente Instrumental/JUnit-Tests aktiviert.

Ich hoffe aufrichtig, dass dieser Beitrag jemandem hilft.

32

Angenommen, Sie haben eine FragmentActivity-Klasse mit dem Namen 'MyFragmentActivity', in der eine öffentliche Fragment-Klasse mit dem Namen 'MyFragment' mit FragmentTransaction hinzugefügt wird. Erstellen Sie einfach eine Klasse 'JUnit Test Case', die ActivityInstrumentationTestCase2 in Ihrem Testprojekt erweitert. Rufen Sie dann einfach getActivity () auf und greifen Sie auf das MyFragment-Objekt und seine öffentlichen Member zu, um Testfälle zu schreiben.

Verweisen Sie auf den Code-Ausschnitt unten:

// TARGET CLASS
public class MyFragmentActivity extends FragmentActivity {
    public MyFragment myFragment;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
        myFragment = new MyFragment();
        fragmentTransaction.add(R.id.mainFragmentContainer, myFragment);
        fragmentTransaction.commit();
    }
}

// TEST CLASS
public class MyFragmentActivityTest extends Android.test.ActivityInstrumentationTestCase2<MyFragmentActivity> {
    MyFragmentActivity myFragmentActivity;
    MyFragment myFragment;

    public MyFragmentActivityTest() {
        super(MyFragmentActivity.class);
    }

    @Override
    protected void setUp() throws Exception {
        super.setUp();
        myFragmentActivity = (MyFragmentActivity) getActivity();
        myFragment = myFragmentActivity.myFragment;
    }

    public void testPreConditions() {
        assertNotNull(myFragmentActivity);
        assertNotNull(myFragment);
    }

    public void testAnythingFromMyFragment() {
        // access any public members of myFragment to test
    }
}

Ich hoffe das hilft. Akzeptieren Sie meine Antwort, wenn Sie dies nützlich finden. Vielen Dank.

17
abhijit.mitkar

Ich bin mir ziemlich sicher, dass Sie tun können, was Sie sagen, eine Scheinaktivität erstellen und das Fragment von dort aus testen. Sie müssen nur die Kompatibilitätsbibliothek im Hauptprojekt exportieren, und Sie können auf die Fragmente des Testprojekts zugreifen. Ich werde ein Beispielprojekt erstellen und den Code hier testen und werde meine Antwort basierend auf dem, was ich herausfinde, aktualisieren.

Weitere Informationen zum Export der Kompatibilitätsbibliothek finden Sie unter hier .

0
DallaRosa

Hinzufügen zu @ abhijit.mitkars Antwort.

In einem bestimmten Szenario ist Ihr Fragment kein öffentliches Mitglied in der zu testenden Aktivität.

protected void setUp() {
   mActivity = getActivity();
   mFragment = new TheTargetFragment();

   FragmentTransaction transaction = mActivity.getSupportFragmentManager().beginTransaction();
   transaction.add(R.id.fragment_container, mFragment, "FRAGMENT_TAG");
   transaction.commit();
}

Der Zweck des obigen Codes besteht darin, das Fragment durch ein neues Fragmentobjekt zu ersetzen, auf das wir Zugriff haben.

Mit dem folgenden Code erhalten Sie Zugriff auf die Mitglieder der Fragment-Benutzeroberfläche.

TextView randomTextView= (TextView) mFragment.getView().findViewById(R.id.textViewRandom);

Wenn Sie die Benutzeroberfläche aus der Aktivität wird nichtabrufen, erhalten Sie das erwartete Ergebnis.

TextView randomTextView= (TextView) mActivity.findViewById(R.id.textViewRandom);

Schließlich, wenn Sie Änderungen an der Benutzeroberfläche vornehmen möchten. Wie ein guter Android-Entwickler tun Sie es im Haupt-Thread.

mActivity.runOnUiThread(new Runnable() {
    @Override
    public void run() {
        // set text view's value
    }
});

Hinweis: Möglicherweise möchten Sie ihm jedes Mal ein Thread.sleep () geben, wenn ein Test endet. Um ein Blockieren zu vermeiden, muss die getInstrumentation (). WaitForIdleSync (); scheint nicht immer zu funktionieren.

Ich habe ActivityInstrumentationTestCase2 verwendet, seit ich Funktionstests durchführte.

0