About
Recently, I am writing test cases for my android project. At some point, I need to load (or installed) some data files to run my tests. Documentations in this area scatter everywhere. So, I tried to summarize them here.
NOTE: Assume you are running android’s test cases with Espresso.
Files will be used on Local unit test or instrumented test?
Please read the official document here if you are not familiar with either or both of the terms
Local unit test
and Instrumented test
. In short, the former one runs tests without a need for android simulator while the later one does.With Local unit test
Although I have not coded such kind of test cases yet, I believe answer here shows where to put the fixtures which is package under
app/src/test/resources/
.
Then, you can load the fixture via
getClass().getResourceAsStream("testFile.txt")
as illustrated in the link.With Instrumented test
Put files under
app/src/androidTest/assets
. For example, I have 2 PDF files one.pdf
and two.pdf
.PROJECT/app/src/androidTest/assets/one.pdf
PROJECT/app/src/androidTest/assets/two.pdf
Getting a file stream, for example
one.pdf
, first.InputStream input =
InstrumentationRegistry.getContext().getResources().getAssets().open(
"one.pdf"
);
As I am testing a function of picking a PDF which get an intent from any file choosers. In order to do simulate such intent, I need to COPY the PDF file into some where so that the application under test is able to access first.
// Convert Asset to File by copying such file to our cache directory
File f2 = new File(InstrumentationRegistry.getTargetContext().getCacheDir() +"/one.pdf");
writeBytesToFile(input, f2);
where
writeByteToFile
is private static void writeBytesToFile(
InputStream is,
File file
) throws IOException{
FileOutputStream fos = null;
try {
byte[] data = new byte[2048];
int byteRead;
fos = new FileOutputStream(file);
while((byteRead=is.read(data)) > -1){
fos.write(data, 0, byteRead);
}
}
finally{
if (fos!=null){
fos.close();
}
}
}
Pack the file with an URI such that an intent can carry on after copying.
// Get an uri from such file object
Intent i = new Intent();
i.setData(Uri.fromFile(f2));
// Return the simulated intent
return new Instrumentation.ActivityResult(Activity.RESULT_OK, i);
Note that schema of such URI is
file://
. However, the schema of an URI sources from a real device is content://
.
Done.
Finally, assertions on added PDFs can be made.
// Verify the contents
onView(withText(PDF_ONE)).check(matches(isDisplayed()));
onView(withText(PDF_TWO)).check(matches(isDisplayed()))
Show me source code
Welcome to read the full source code here.
Reference
- http://johnpetitto.com/unit-test-resource-loading
- http://stackoverflow.com/questions/9898634/how-to-provide-data-files-for-android-unit-tests
- http://stackoverflow.com/questions/28923728/how-to-read-a-test-only-file-in-android-unit-test
- http://stackoverflow.com/questions/29969545/whats-the-difference-between-gettargetcontext-and-getcontext-on-instrumentat
- http://stackoverflow.com/questions/10402690/android-how-do-i-create-file-object-from-asset-file
- https://inthecheesefactory.com/blog/how-to-share-access-to-file-with-fileprovider-on-android-nougat/en
- https://developer.android.com/reference/android/support/v4/content/FileProvider.html#getUriForFile