2015-03-08 12 views
11

Dla mojej aplikacji na Androida piszę testy jednostkowe, które wymagają odczytania niektórych plików. Ponieważ są to pliki tylko do testów, nie chcę ich w moich folderach res, ponieważ nie chcę, aby skończyły się w moim ostatnim pliku .apk.Jak odczytać plik testowy tylko w teście urządzenia z Androidem

Chcę zrobić coś podobnego do this question, ale używając nowo dodanego (w Gradle 1.1) unit test support (w przeciwieństwie do testu oprzyrządowania).

Moja struktura projektu jest następujący:

/app 
    /src 
     /main 
     /java/my.module/myClass.java 
     /res/production_resources_go_here 
     /test 
     /java/my.module/myClassTest.java 
     /resources/testFile.txt 

co powinno moja próba myClassTest wyglądać, aby móc skutecznie odczytać testFile.txt?

+0

Myślę, że potrzebowalibyśmy więcej kodu dla myClass.java, aby to skomentować. Chcesz przetestować przekazanie pliku testFile.txt do dowolnej metody przetwarzającej pliki tekstowe w myClass, a następnie sprawdź (assert with AssertJ), czy wynik wraca zgodnie z oczekiwaniami. Zaglądanie do Robolectric i Mockito może dać ci kilka pomysłów. – TTransmit

+0

'myClass.java' nie ma znaczenia. Załóżmy, że ma metodę, która zużywa 'InputStream' i chcę, aby strumień zawierał zawartość pliku w moim teście. Czy to ma sens? –

+0

jeśli chcesz coś z tym zrobić, przeczytaj [Mój wpis] (http://stackoverflow.com/questions/28206507/getting-list-of-subfolders-name-and-files-name-in-android- pakiet źródłowy). możesz otworzyć apk w swoim telefonie komórkowym, a następnie odczytać go jako strumień. –

Odpowiedz

17

W czasie, gdy zadawano to pytanie, po prostu nie działało. Na szczęście od tego czasu zostało to naprawione.

Musisz umieścić swój plik tekstowy pod folderem app/src/test/resources, tak jak próbował OP. Dodatkowo musi być w tym samym pakiecie co twoja klasa testowa. Więc jeśli masz ReadFileTest.java w paczce com.example.test w folderze app/src/test/java, twój plik testowy powinien być w app/src/test/resources/com/example/test.

test folder structure

Następnie można dostać się do pliku tekstowego tak:

getClass().getResourceAsStream("testFile.txt") 

To otwiera InputStream do pliku tekstowego. Jeśli nie jesteś pewien, co z nim zrobić, oto niektóre z wielu sposobów, można go używać: Read/convert an InputStream to a String

+0

FWIW Myślę, że to teraz działa bez problemu. Jeśli są jakieś zainteresowania, mogę dwukrotnie sprawdzić i edytować odpowiedź, aby pokazać, w jaki sposób można załadować plik. –

+0

Tak, mam zainteresowanie, proszę zademonstrować. –

+0

Załatwiłbym to 100 razy, gdybym mógł. Kluczem naprawdę jest uzyskanie właściwych ścieżek. Dziękuję dziękuję! : D –

0

Przykład prawidłowego wykonania tej czynności polegałby na umieszczeniu pliku w folderze zasobów. Jednak zawartość folderu aktywów zostanie dodana do pliku APK.

InputStream is = resources.getAssets().open("test.txt"); 

Możesz oszukać ten system i przejść do dowolnego innego pliku w projekcie. Pamiętaj, aby utworzyć katalog zasobów w lokalizacji określonej w pliku iml projektu (np. Src/main/assets).

InputStream is = resources.getAssets().open("../../test/resources/testFile.txt"); 

Przykładem sposób, aby uzyskać środki byłyby:

Resources resources = new Activity().getResources(); 
1

pracuję projekt o strukturze podobnej do tego, co pan wspomniał. Umieściłem wszystkie moje odpowiedzi serwera w pliku pod folderem resources, takim jak app/src/test/resources/BookingInfo.json.

Wszystkie pliki testowe java są pod app/src/test/java/PACKAGE_NAME podobne do tego, co powiedziałeś. Mam klasy Fixture w ramach pakietu, który zawiera nazwę zasobów:

@SuppressWarnings("nls") 
public final class Fixtures 
{ 
    public static final String GET_ANNOUNCEMENT = "GetAnnouncement.json"; 
... 
} 

i wreszcie klasę FixtureUtils że metoda tej klasy jest odpowiedzialny, aby przeczytać plik zasobów i powrócić wynik.

import java.nio.file.Files; 
import java.nio.file.Paths; 

public class FixtureUtils 
    { 
     public static final AFixture fixtureFromName(final String fixtureName) 
     { 
      final String fixtureString = FixtureUtils.stringFromAsset(fixtureName); 

      if (StringUtils.isEmpty(fixtureString)) 
      { 
       return null; 
      } 

      final Gson gson = new Gson(); 
      final AFixture aFixture = gson.fromJson(fixtureString, AFixture.class); 
      return aFixture; 
     } 

     private static final String stringFromAsset(final String filename) 
     { 
      try 
      { 
       final URL resourceURL = ClassLoader.getSystemResource(filename); 
       if (resourceURL == null) 
       { 
        return null; 
       } 

       final String result = new String(Files.readAllBytes(Paths.get(resourceURL.toURI())), 
           Charset.forName("UTF-8")); //$NON-NLS-1$ 
       return result; 
      } 
      catch (final Exception e) 
      { 
       e.printStackTrace(); 
      } 

      return null; 
     } 

     private FixtureUtils() 
     { 
      // Ensure Singleton 
     } 
    } 

I AFixture klasy wygląda następująco:

public class AFixture 
{ 
    public List<JsonElement> validItems; 
    public List<JsonElement> invalidItems; 

    public AFixture() 
    { 
     super(); 
    } 

    public List<JsonElement> getInvalidItems() 
    { 
     return this.invalidItems; 
    } 

    public List<JsonElement> getValidItems() 
    { 
     return this.validItems; 
    } 

    public void setInvalidItems(final List<JsonElement> invalidItems) 
    { 
     this.invalidItems = invalidItems; 
    } 

    public void setValidItems(final List<JsonElement> validItems) 
    { 
     this.validItems = validItems; 
    } 

} 

Uwaga: java.nio.file została usunięta z JDK8 jeśli się nie mylę jednak nie masz problemu, jeśli używasz JDK7. Jeśli używasz JDK8, po prostu musisz zmienić metodę stringFromAsset w taki sposób, jak FileInputStream (stary styl mody) lub Scanner.

5

Dodaj to do swojej build.gradle:

android { 
    sourceSets { 
     test { 
      resources.srcDirs += ['src/test/resources'] 
     } 
     androidTest { 
      resources.srcDirs += ['src/androidTest/resources'] 
     } 
    } 
} 

przypadku zasobów, aby były dostępne przez jednostkę testy, dodaj pliki w: src/test/resources. W przypadku testów oprzyrządowania należy dodać pliki do: src/androidTest/resources.

1

Po odpowiedzi @ Deepansu, ujednoliciłem dane testowe w katalogu {project root}/sampledata, który jest domyślną lokalizacją polecenia Android Studio New > Sample Data Directory.

1. W projekcie kliknij prawym przyciskiem myszy i kliknij New > Sample Data Directory. Spowoduje to utworzenie katalogu sampledata w app, który ma tę samą hierarchię co katalogi build.gradle, src i build.

2. W build.gradle dodaj skrypty jak poniżej;

android { 
    sourceSets { 
     test { 
      resources.srcDirs += ['sampledata'] 
     } 
     androidTest { 
      resources.srcDirs += ['sampledata'] 
     } 
    } 
} 

3.Sync w Gradle.

Teraz możemy umieścić pliki zasobów testowych w jednym katalogu i używać ich w obu środowiskach testowych.

Możesz odczytać plik jak poniżej;

// use somewhere at test logic. Note that slash symbol is required (or not). 
jsonObject = new JSONObject(readFromFile("/testFile.json")); 

// a method to read text file. 
public String readFromFile(String filename) throws IOException { 
    InputStream is = getClass().getResourceAsStream(filename); 
    StringBuilder stringBuilder = new StringBuilder(); 
    int i; 
    byte[] b = new byte[4096]; 
    while ((i = is.read(b)) != -1) { 
     stringBuilder.append(new String(b, 0, i)); 
    } 
    return stringBuilder.toString(); 
} 
Powiązane problemy