2015-05-05 13 views
5

Sono su Android Studio 1.2, Robolectric 3.0-rc2.alcuni test Robolectric falliscono quando vengono eseguiti tutti insieme ma passano individualmente

Ho due classi di test, una chiamata MotdTest con un metodo di prova che verifica la serializzazione POJO json & deserializzazione. L'altro è chiamato UserInfoTest, che contiene 4 metodi di test che verificano le informazioni utente che ho impostato su SharedPreferences. Se eseguo individualmente lo UserInfoTest, tutti e 4 i metodi di test passano sempre. Tuttavia, se eseguo tutti i test, il test in MotdTest ha esito positivo, ma due metodi di UserInfoTest falliscono sempre. Sto correndo da linea di comando in questo momento chiamando ./gradlew test

Qualcuno sa perché alcuni dei miei test stanno fallendo quando eseguo tutti i test? Nel mio UserInfoTest ho un metodo annotato @After in cui eseguo la pulizia chiamando clear(). Commit() su SharedPreferences.Editor.

UserInfoTest:

testOnSignIn() non riesce a assertThat(6, equalTo(prefs.getAll().size())); perché la dimensione di prefs è 0.

E testIsSignedIn() fallisce a assertThat(UserInfo.isSignedIn(), is(false));

@RunWith(MyRoboRunner.class) 
@Config(constants = BuildConfig.class) 
public class UserInfoTest { 

    private String mExpectedId; 

    private String mExpectedName; 

    private String mExpectedEmail; 

    private String mExpectedToken; 

    private String mExpectedKey; 

    @Before 
    public void setUp() throws Exception { 
     ShadowLog.stream = System.out; 

     mExpectedId = "someiD"; 
     mExpectedName = "johnny boy"; 
     mExpectedEmail = "[email protected]"; 
     mExpectedToken = "Session Token"; 
     mExpectedKey = "Session Key"; 
    } 

    @After 
    public void tearDown() { 
     SharedPreferences prefs = RuntimeEnvironment.application.getSharedPreferences(
       UserInfo.PREFERENCES, Context.MODE_PRIVATE); 
     prefs.edit().clear().commit(); 
     mExpectedId = null; 
     mExpectedName = null; 
     mExpectedEmail = null; 
     mExpectedToken = null; 
     mExpectedKey = null; 
    } 

    @Test 
    public void testOnSignIn() {   
     SharedPreferences prefs = RuntimeEnvironment.application.getSharedPreferences(
       UserInfo.PREFERENCES, Context.MODE_PRIVATE); 

     UserInfo.onSignIn(mExpectedId, mExpectedName, mExpectedEmail, mExpectedKey, mExpectedToken); 
     assertThat(mExpectedKey, equalTo(UserInfo.getSessionKey())); 

     assertThat(mExpectedToken, equalTo(UserInfo.getSessionToken())); 
     assertThat(mExpectedId, equalTo(UserInfo.getUserId())); 
     assertThat(mExpectedEmail, equalTo(UserInfo.getUserEmail())); 
     assertThat(mExpectedName, equalTo(UserInfo.getUserName())); 

     assertThat(6, equalTo(prefs.getAll().size())); 
    } 

    @Test 
    public void testOnSignOut() { 
     UserInfo.onSignIn(mExpectedId, mExpectedName, mExpectedEmail, mExpectedKey, mExpectedToken); 
     // Set Over21 to make sure we unset this value on Signout 
     UserInfo.setIsOver21(true); 

     UserInfo.onSignOut(); 
     SharedPreferences prefs = RuntimeEnvironment.application.getSharedPreferences(
       UserInfo.PREFERENCES, Context.MODE_PRIVATE); 
     assertThat(UserInfo.getSessionKey(), nullValue()); 
     assertThat(UserInfo.getSessionToken(), nullValue()); 
     assertThat(UserInfo.isOver21Set(), is(false)); 
     assertThat(prefs.getAll().size(), equalTo(0)); 
    } 

    @Test 
    public void testIsSignedIn() { 
     assertThat(UserInfo.isSignedIn(), is(false)); 

     UserInfo.onSignIn(mExpectedId, mExpectedName, mExpectedEmail, mExpectedKey, mExpectedToken); 
     assertThat(UserInfo.isSignedIn(), is(true)); 

     UserInfo.onSignOut(); 
     assertThat(UserInfo.isSignedIn(), is(false)); 
    } 

    @Test 
    public void testIsOver21Set() { 
     assertThat(UserInfo.isOver21Set(), is(false)); 
     UserInfo.setIsOver21(false); 
     assertThat(UserInfo.isOver21Set(), is(true)); 
    } 
} 

UserInfo:

App è un un Application sottoclasse d App.getInstance() è un singleton.

private static final SharedPreferences PREFS = App.getInstance() 
     .getSharedPreferences(PREFERENCES, Context.MODE_PRIVATE); 

public static void onSignIn(String userId, String fullName, String email, String sessionKey, 
     String sessionToken) { 
    SharedPreferences.Editor editor = PREFS.edit(); 
    editor.putString(PROPERTY_USER_ID, userId); 
    editor.putString(PROPERTY_USER_NAME, fullName); 
    editor.putString(PROPERTY_USER_EMAIL, email); 
    editor.putString(PROPERTY_SESSION_KEY, sessionKey); 
    editor.putString(PROPERTY_SESSION_TOKEN, sessionToken); 
    editor.putStringSet(PROPERTY_PENDING_SCANS, new HashSet<String>()); 

    editor.commit(); 
} 
public static boolean isSignedIn() { 
    return getSessionToken() != null; 
} 

MyRoboRunner: Una versione modificata di this perché sono su Mac, e anche perché ho scelto come target API 22 nel mio progetto, ma robolectric non supporta fino a che ancora, quindi ho eseguito i miei test contro API 21.

public class MyRoboRunner extends RobolectricGradleTestRunner { 

    public MyRoboRunner(Class<?> klass) throws InitializationError { 
     super(klass); 
    } 

    protected AndroidManifest getAppManifest(Config config) { 
     AndroidManifest appManifest = super.getAppManifest(config); 
     String moduleRoot = getModuleRootPath(config); 

     //can use this line instead dynamic path resolution when AS bug is fix, or use @Config 
     //FsFile androidManifestFile = appManifest.getAndroidManifestFile(); 
     FsFile androidManifestFile = FileFsFile.from(moduleRoot, 
       appManifest.getAndroidManifestFile().getPath() 
         .replace("bundles", "manifests/full")); 
     FsFile resDirectory = FileFsFile.from(moduleRoot, appManifest.getResDirectory().getPath()); 
     FsFile assetsDirectory = FileFsFile 
       .from(moduleRoot, appManifest.getAssetsDirectory().getPath()); 
     return new AndroidManifest(androidManifestFile, resDirectory, assetsDirectory) { 
      @Override 
      public int getTargetSdkVersion() { 
       //lollipop bc it's highest that robolectric 3.0 supports 
       return Build.VERSION_CODES.LOLLIPOP; 
      } 

      @Override 
      public int getMinSdkVersion() { 
       return Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1; 
      } 
     }; 
    } 

    private String getModuleRootPath(Config config) { 
     String moduleRoot = config.constants().getResource("").toString().replace("file:", ""); 
     return moduleRoot.substring(0, moduleRoot.indexOf("/build")); 
    } 
} 
+0

Che tipo di errore vedi? Potresti condividere il codice per i test? –

+0

@EugenMartynov Ho incluso parte del codice che uso per i test. – waynesford

risposta

0

Utilizzando la robolectric gradle plugin e l'impostazione di questa proprietà ha tutti i miei esami di passaggio:

robolectric { 
    // Specify max number of processes (default is 1) 
    maxParallelForks = 2 
} 

Ma, io ancora non so perché questo potrebbe influenzare la mia t ests se eseguito individualmente vs tutti insieme. Inoltre, sembra che il plug-in gradle robolectric non sia più necessario da quando sono su Android Studio 1.2, ma non sono riuscito a capire come farlo funzionare senza di esso e impostare manualmente la proprietà maxParallelForks.

+1

Questa è una soluzione alternativa ma non corretta –

1

Mantenere i riferimenti statici a SharedPreferences nello PREFS. Penso che i tuoi test verranno risolti non appena lo resetti nel tuo metodo tearDown o rimuovi i riferimenti statici. Se si rimuove il riferimento statico, il file SharedPreferences verrà cancellato dallo stesso Robolectric - non è necessario cancellarlo nuovamente in tearDown.

Un altro punto da menzionare - sto anche utilizzando Mac e non ho alcun problema con RobolectricGradleTestRunnner. A volte devo eseguire clean prima di eseguire i test ma nient'altro.

E un'altra cosa che hai citato robobolectric-gradle-plugin. Non ne hai bisogno con Android Studio v1.1 + e Android gradle plugin v1.1 +