14

Ho cercato un modo per testare l'interfaccia utente dei miei frammenti separatamente (cioè, indipendentemente da altri frammenti e attività) ma non riesco a trovare un modo per farlo.Android - Strumento di test dell'interfaccia utente indipendente Fragment

In particolare, diciamo che ho Frammento A, Frammento B e Frammento C. L'unico modo (app-saggio) per andare al Frammento C è passare prima attraverso il Frammento A e il Frammento B. Sto cercando un modo per testare Frammento C direttamente (potenzialmente deridendo le dipendenze, se ne esistono), senza dover passare attraverso Frammento A e B.

Strumenti ho studiato finora:

  • scimmia: usata solo per generare eventi pseudo-casuali attraverso la linea di comando. Non quello che voglio.

  • monkeyrunner: può eseguire programmi Python per inviare flussi di eventi alla mia app per Android, ma non può indirizzare un particolare frammento direttamente con quegli script.

  • Espresso: strumento di prova white-box. Questo si avvicina a quello che voglio, ma richiede ancora il passaggio attraverso i frammenti A e B prima di raggiungere Fragment C (cioè, devi avviare la tua app e quindi i test verranno eseguiti da lì).

  • UI Automator: strumento di test black-box. Anche questo si avvicina, ma, di nuovo, richiede di passare attraverso i Frammenti precedenti prima di testare quello che voglio (Frammento C).

Esiste un modo per prova l'interfaccia utente di un Frammentazione t direttamente?

risposta

43

Sto utilizzando un codice personalizzato FragmentTestRule ed Espresso per testare ciascuno dei miei Fragments in isolamento.

Ho un TestActivity dedicato che mostra il test Fragments nella mia app. Nel mio caso lo Activity esiste solo nella variante debug perché i miei test di strumentazione funzionano contro debug.

1. Creare un TestActivity in src/debug/java/your/package/TestActivity.java in vista di contenuti in cui sarà aggiunto il collaudato Fragment a:

@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. Creare un AndroidManifest.xml per la variante debug e dichiarare la TestActivity . È necessario per avviare TestActivity durante il test. Aggiungere questo Manifesto alla variante debug in 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. Creare la FragmentTestRule nella variante androidTest a 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.Quindi è possibile testare Fragments in isolamento:

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

l'unica cosa ** "piccola" ** è che il codice di test è mischiato con il codice produttivo/di runtime (almeno nella build di debug) che può facilmente e molto velocemente diventare disordinato mentre si aggiungono altri test alla suite :(Probabilmente soluzione se la soluzione migliore non esiste è lasciare solo la voce manifest in debug build e mantenere le classi (TestActivity, Rule, ecc.) in AndroidTest – Ewoks

1

È possibile utilizzare Robotium. Questo è per il test dell'interfaccia utente Android.

+1

Ma Robotium ha lo stesso problema di UI Automator ed Espresso. Per testare il frammento C, ho bisogno di passare prima i frammenti A e B. Voglio uno strumento che mi permetta di testare direttamente Frammento C. – Tiago

+0

Poiché utilizzo il robotium, risolve qualsiasi tipo di problema di verifica dell'interfaccia utente. Non conosco i dettagli del tuo requisito, quindi consulta l'API di robotium http://robotium.googlecode.com/svn/doc/com/robotium/solo /Solo.html –

+0

@Tiago Spero che API come waitForFragmentByTag, waitForFragmentById possano aiutarti. In bocca al lupo. –

0

ho sviluppato FragmentTestRule una libreria Andorid utilizzando il @thaussma's idea. Ti permette di testare i tuoi Fragment s in isolamento.

Hai solo bisogno di aggiungere questo:

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

More information here.

Problemi correlati