2013-07-22 11 views
7

Sto appena iniziando con junit e il primo problema che sto incontrando è, come devo testare i frammenti?Come eseguire i test su un frammento di attività

L'attività sottoposta a test ha un frammento che rappresenta il layout principale.

@Override 
protected void setUp() throws Exception { 
    super.setUp(); 
    Intent intent = new Intent(getInstrumentation().getTargetContext(), 
      ActivityWelcome.class); 
    startActivity(intent, null, null); 

    FragmentManager fragmentManager = getActivity().getSupportFragmentManager(); 
    mFragmentWelcome = (FragmentWelcome) fragmentManager.findFragmentByTag(FragmentWelcome.TAG); 
    if (mFragmentWelcome == null) { 

     mFragmentWelcome= FragmentWelcome.newInstance(); 
     fragmentManager 
       .beginTransaction() 
       .replace(android.R.id.content, mFragmentWelcome, FragmentWelcome.TAG) 
       .commit(); 
    } 
} 

Ho poi andare a testare il layout:

@SmallTest 
public void testLayout() { 

    ImageButton buttonImage = (ImageButton) getActivity().findViewById(my.package.R.id.button_invites); 
    assertNotNull(buttonImage); 
    assertEquals("ImageButton Invite has an invalid drawable" 
      , getActivity().getResources().getDrawable(my.package.R.drawable.light_social_invite) 
      , buttonImage); 
} 

Errore:

java.lang.NullPointerException 
    at my.package.test.ActivityWelcomeUnitTest.testLayout(ActivityWelcomeUnitTest.java:55) 
    at java.lang.reflect.Method.invokeNative(Native Method) 
    at android.test.InstrumentationTestCase.runMethod(InstrumentationTestCase.java:214) 
    at android.test.InstrumentationTestCase.runTest(InstrumentationTestCase.java:199) 
    at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:169) 
    at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:154) 
    at android.test.InstrumentationTestRunner.onStart(InstrumentationTestRunner.java:545) 
    at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:1551) 

fallisce il:

ImageButton buttonImage = (ImageButton) mFragmentWelcome.getView().findViewById(my.package.R.id.button_invites); 

io non sono sicuro perché il il frammento è nullo, ovviamente sto eseguendo questa operazione ectly, qualcuno potrebbe per favore illuminarmi?

+0

Come sei riuscito a eseguire unit test. In Android Studio sto ricevendo l'eccezione del puntatore null a questo Intent intent = new Intent (getInstrumentation(). GetTargetContext(), ActivityWelcome.class) 'Il mio testClass sta estendendo' ActivityUnitTestCase ' –

risposta

9

In realtà è necessario attendere che il thread dell'interfaccia utente componga la vista principale con i frammenti.

Ho avuto gli stessi errori e così ho guardato le fonti di Robotium per vedere come gestiscono ciò. La risposta è che usano alcuni metodi che attendono il tempo richiesto.

Per frammento si può usare qualcosa di simile prima di eseguire le vostre affermazioni:

protected Fragment waitForFragment(String tag, int timeout) { 
     long endTime = SystemClock.uptimeMillis() + timeout; 
     while (SystemClock.uptimeMillis() <= endTime) { 

      Fragment fragment = getActivity().getSupportFragmentManager().findFragmentByTag(tag); 
      if (fragment != null) { 
       return fragment; 
      } 
     } 
     return null; 
    } 

Io uso un timeout di 5000ms, sembra funzionare bene.

Quindi, nel codice è necessario sostituire

mFragmentWelcome = (FragmentWelcome) fragmentManager.findFragmentByTag(FragmentWelcome.TAG); 

da

mFragmentWelcome = (FragmentWelcome) waitForFragment(FragmentWelcome.TAG, 5000); 

EDIT: Questa risposta presuppone che il JUnit estende ActivityInstrumentationTestCase2<T>

+0

Grazie per la risposta. Ha molto senso, tuttavia non ha risolto il puntatore nullo. – HGPB

+0

Sembra che non riesca ad accedere a 'getView()' – HGPB

+0

La junit estende 'ActivityInstrumentationTestCase2 '? Non so se sia d'aiuto ma sul mio 'setup()' chiamo 'setActivityInitialTouchMode (false)' prima di chiamare su 'getActivity()'. Inoltre non ho effettuato chiamate su 'startActivity' ... Finalmente, prova ad aumentare il valore di timeout. – tbruyelle

4

Per un test ActivityUnitTestCase, ho dovuto aggiungere le seguenti righe al metodo waitForFragment:

// haven't really checked if this is necessary 
getInstrumentation().waitForIdleSync(); 
// without this, waitForFragment() failed to find the fragment 
getActivity().getFragmentManager().executePendingTransactions(); 
+0

Grazie per aver chiarito questo. la risposta @tbruyelle non ha funzionato per me. Ho controllato che la chiamata 'waitForIdleSync()' non sia realmente necessaria. – kazbeel

+0

Fare 'mFragment.getView()' non è nullo? –

+0

utilizzando getSUPPORTFragmentManager(). ExecutePendingT ... ha lavorato con ActivityUnitTestCase, perché avevo aggiunto il frammento chiamando getSupportFragmentManager(). Spero che aiuti qualcuno. – flobacca

1

U può utilizzare com.robotium.solo.Solo da 'com.jayway.android.robotium:robotium-solo:5.2.1'

mInstrumentation = InstrumentationRegistry.getInstrumentation(); 
    mSolo = new Solo(mInstrumentation); 
    mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation()); 
    ..... 
    mSolo.waitForFragmentById(); 
Problemi correlati