2017/03/22

How to load test files when testing in android's application

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();
            }
        }
    }
If you are confused with getContext and getTargetContext, read the answer from Stackoverflow here
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

沒有留言:

張貼留言