2014-01-30 4 views
11

Weitere Informationen:konsekutiv Android JUnit-Tests spiegeln nicht die realen Daten in der zugrunde liegenden Datenbank

Um zu klären, nutzt die App im Test ein ContentProvider auf die Datenbank zuzugreifen.

Edit:

Wenn jemand bereit und in der Lage ist, mir diese debuggen zu helfen. Das vollständige Projekt ist verfügbar here. In der issue107-contentprovider Niederlassung, BaseballCardListAddCardsTest.

Frage:

Als ich zwei meiner Android JUnit-Tests laufen getrennt, gehen sie einfach gut. Wenn ich sie jedoch zusammen laufen lasse, geht der erste über und der zweite scheitert. Das Problem scheint zu sein, dass der erste Testlauf eine Zeile zur zugrunde liegenden Datenbank hinzufügt. tearDown() löscht die Datenbank korrekt, aber der zweite Test beginnt immer noch mit den schmutzigen Daten, die in ListView angezeigt werden, obwohl die Datenbank die zusätzliche Zeile nicht enthält. (Ich bestätigte dies unter Verwendung adb shell.) Hat jemand irgendwelche Ideen, wie ich dieses Problem beheben kann?

Die zu testende Aktivitätsklasse kann here gefunden werden.

Hier ist mein Testcode:

/** 
* Tests for the {@link BaseballCardList} activity when the database contains 
* data. 
*/ 
public class BaseballCardListWithDataTest extends 
     ActivityInstrumentationTestCase2<BaseballCardList> { 

    /** 
    * Create instrumented test cases for {@link BaseballCardList}. 
    */ 
    public BaseballCardListWithDataTest() { 
     super(BaseballCardList.class); 
    } 

    /** 
    * Set up test fixture. This consists of an instance of the 
    * {@link BaseballCardList} activity, its {@link ListView}, and a populated 
    * database. 
    * 
    * @throws Exception 
    *    If an error occurs while chaining to the super class. 
    */ 
    @Override 
    public void setUp() throws Exception { 
     super.setUp(); 

     this.inst = this.getInstrumentation(); 

     // Create the database and populate table with test data 
     InputStream cardInputStream = this.inst.getContext().getAssets() 
       .open(BBCTTestUtil.CARD_DATA); 
     BaseballCardCsvFileReader cardInput = new BaseballCardCsvFileReader(
       cardInputStream, true); 
     this.allCards = cardInput.getAllBaseballCards(); 
     cardInput.close(); 

     this.dbUtil = new DatabaseUtil(this.inst.getTargetContext()); 
     this.dbUtil.populateTable(this.allCards); 

     // Start Activity 
     this.activity = this.getActivity(); 
     this.listView = (ListView) this.activity 
       .findViewById(android.R.id.list); 
     this.newCard = new BaseballCard("Code Guru Apps", 1993, 1, 50000, 1, 
       "Code Guru", "Code Guru Devs", "Catcher"); 
    } 

    /** 
    * Tear down the test fixture by calling {@link Activity#finish()} and 
    * deleting the database. 
    * 
    * @throws Exception 
    *    If an error occurs while chaining to the super class. 
    */ 
    @Override 
    public void tearDown() throws Exception { 
     this.dbUtil.deleteDatabase(); 

     super.tearDown(); 
    } 

    /** 
    * Check preconditions which must hold to guarantee the validity of all 
    * other tests. Assert that the {@link Activity} to test and its 
    * {@link ListView} are not <code>null</code>, that the {@link ListView} 
    * contains the expected data, and that the database was created with the 
    * correct table and populated with the correct data. 
    */ 
    public void testPreConditions() { 
     Assert.assertNotNull(this.activity); 

     BBCTTestUtil.assertDatabaseCreated(this.inst.getTargetContext()); 
     Assert.assertTrue(this.dbUtil.containsAllBaseballCards(this.allCards)); 

     Assert.assertNotNull(this.listView); 
     BBCTTestUtil.assertListViewContainsItems(this.inst, this.allCards, 
       this.listView); 
    } 

    /** 
    * Test that the {@link ListView} is updated when the user adds a new card 
    * which matches the current filter. 
    * 
    * @throws Throwable 
    *    If an error occurs while the portion of the test on the UI 
    *    thread runs. 
    */ 
    public void testAddCardMatchingCurrentFilter() throws Throwable { 
     this.testYearFilter(); 

     Activity cardDetails = BBCTTestUtil.testMenuItem(this.inst, 
       this.activity, R.id.add_menu, BaseballCardDetails.class); 
     BBCTTestUtil.addCard(this, cardDetails, this.newCard); 
     BBCTTestUtil.clickCardDetailsDone(this, cardDetails); 

     this.expectedCards.add(this.newCard); 
     BBCTTestUtil.assertListViewContainsItems(this.inst, this.expectedCards, 
       this.listView); 
    } 

    /** 
    * Test that the {@link ListView} is updated when the user adds a new card 
    * after an active filter was cleared. 
    * 
    * @throws Throwable 
    *    If an error occurs while the portion of the test on the UI 
    *    thread runs. 
    */ 
    public void testAddCardAfterClearFilter() throws Throwable { 
     this.testClearFilter(); 
     Activity cardDetails = BBCTTestUtil.testMenuItem(this.inst, 
       this.activity, R.id.add_menu, BaseballCardDetails.class); 
     BBCTTestUtil.addCard(this, cardDetails, this.newCard); 
     BBCTTestUtil.clickCardDetailsDone(this, cardDetails); 

     this.allCards.add(this.newCard); 
     BBCTTestUtil.assertListViewContainsItems(this.inst, this.allCards, 
       this.listView); 
    } 

    private List<BaseballCard> allCards; 
    private List<BaseballCard> expectedCards; 
    private Instrumentation inst = null; 
    private Activity activity = null; 
    private DatabaseUtil dbUtil = null; 
    private ListView listView = null; 
    private BaseballCard newCard = null; 
    private static final int TIME_OUT = 5 * 1000; // 5 seconds 
    private static final String TAG = BaseballCardListWithDataTest.class 
      .getName(); 
} 

Antwort

0

Es scheint, dass ein ContentProvider ‚s Lebenszyklus der ein Application gebunden ist nicht der Activity, dass es acesses. Von dem, was ich sagen kann, erstellt ActivityInstrumentationTestCase2 eine einzige Application für alle Tests; Nur der Activity wird für jeden Test zerstört und neu gestartet. Dies bedeutet, dass die einzelnen Tests die gleichen ContentProvider teilen. Dies bedeutet, dass die Datenbankdatei beim ersten Zugriff von der ContentProvider geöffnet und erst geschlossen wird, nachdem alle Testmethoden in ActivityInstrumentationTestCase2 beendet sind. Da die Datenbankdatei zwischen Testfällen offen bleibt, kann auf die Daten auch zugegriffen werden, nachdem die Datei aus dem zugrunde liegenden Dateisystem gelöscht wurde. Meine Lösung bestand darin, die Zeilen der Datenbank einzeln zu löschen, anstatt die gesamte Datenbank zu löschen.

Verwandte Themen