Как читать тестовый файл в Android unit test
Для моего приложения для Android я пишу модульные тесты, требующие чтения некоторых файлов. Поскольку это тестовые файлы, я не хочу их в своих папках res
, так как я не хочу, чтобы они попали в мой последний файл .apk
.
Я хочу сделать что-то похожее на этот вопрос, но используя недавно добавленный (в Gradle 1.1) unit test поддержка (в отличие от контрольно-измерительного теста).
Моя структура проекта выглядит следующим образом:
/app
/src
/main
/java/my.module/myClass.java
/res/production_resources_go_here
/test
/java/my.module/myClassTest.java
/resources/testFile.txt
Что должен мой тест myClassTest
выглядеть так, чтобы иметь возможность успешно читать testFile.txt
?
Ответы
Ответ 1
В то время, когда этот вопрос задавался, это просто не работало. К счастью, это было исправлено с тех пор.
Вы должны поместить свой текстовый файл в папку app/src/test/resources
, которую пытался выполнить OP. Кроме того, он должен быть в том же пакете, что и ваш тестовый класс. Поэтому, если у вас есть ReadFileTest.java
в пакете com.example.test
в папке app/src/test/java
, тогда ваш тестовый файл должен быть в app/src/test/resources/com/example/test
.
![тестовая структура папок]()
Затем вы можете перейти к текстовому файлу следующим образом:
getClass().getResourceAsStream("testFile.txt")
Это открывает текстовый файл InputStream
. Если вы не знаете, что с ним делать, вот некоторые из его способов: Чтение/преобразование InputStream в строку
Ответ 2
Добавьте это в свой build.gradle:
android {
sourceSets {
test {
resources.srcDirs += ['src/test/resources']
}
androidTest {
resources.srcDirs += ['src/androidTest/resources']
}
}
}
Чтобы ресурсы были доступны для модульных тестов, добавьте свои файлы в: src/test/resources
.
И для контрольных тестов добавьте свои файлы в: src/androidTest/resources
.
Ответ 3
Я работаю над проектом со структурой, подобной той, о которой вы говорили.
Я поместил все ответы своего сервера в файл в папке resources
, например app/src/test/resources/BookingInfo.json
.
Все тестовые файлы java находятся под app/src/test/java/PACKAGE_NAME
, аналогично тому, что вы сказали. У меня есть класс Fixture
под пакетом, который содержит имя ресурсов:
@SuppressWarnings("nls")
public final class Fixtures
{
public static final String GET_ANNOUNCEMENT = "GetAnnouncement.json";
...
}
И, наконец, класс FixtureUtils, который метод этого класса отвечает за чтение файла ресурсов и возврат результата.
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
}
}
И класс AFixture
выглядит следующим образом:
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;
}
}
Примечание: java.nio.file
было удалено из JDK8, если я не ошибаюсь, однако у вас нет проблем, если вы используете JDK7. Если вы используете JDK8, вам просто нужно изменить метод stringFromAsset
таким образом, как FileInputStream (стиль старой моды) или сканер.
Ответ 4
После ответа @Deepansu я объединил тестовые данные в директории {project root}/sampledata
, которая по умолчанию является установкой Android Studio New > Sample Data Directory
.
1. В своем проекте щелкните правой кнопкой мыши и выберите New > Sample Data Directory
. Это создаст каталог sampledata
в app
, который имеет ту же иерархию, что и файлы build.gradle
, src
и build
.
2. В build.gradle
добавьте скрипты, как показано ниже:
android {
sourceSets {
test {
resources.srcDirs += ['sampledata']
}
androidTest {
resources.srcDirs += ['sampledata']
}
}
}
3. Sync
в gradle.
Теперь мы можем поместить тестовые файлы ресурсов в один каталог и использовать их в обеих тестовых средах.
Вы можете прочитать файл, как показано ниже:
// 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();
}
Ответ 5
Примером правильного способа сделать это было бы поместить файл в папку с вашими ресурсами. Однако содержимое папки активов будет добавлено в apk.
InputStream is = resources.getAssets().open("test.txt");
Вы можете обмануть эту систему и перейти к любому другому файлу в вашем проекте. Не забудьте создать каталог ресурсов в местоположении, указанном в файле iml проекта (например, src/main/assets).
InputStream is = resources.getAssets().open("../../test/resources/testFile.txt");
Примером способа получения ресурсов будет:
Resources resources = new Activity().getResources();