views:

83

answers:

2

I'm writing an Android JUnit test and want to copy/reset a test fixture file (it's an SQLite database file.) If I were within the main application, I know I could just place the file in the assets directory and use getResources().getAssets().open(sourceFile)

However, this API appears to be unavailable from the ActivityInstrumentationTestCase2 class.

Is there an easy way to copy a file over from the testing PC, or should I just keep a fresh copy of a test fixture on the device and copy it over a temporary file?

Thanks!

+1  A: 

The resources in your test application and your main application are accessible separately in an instrumentation test case. If you want to access resources that are in the res/raw or assets folder of the test project itself, you can use

getInstrumentation().getContext().getResources()

To access resources in the application being tested (the "target" application), use

getInstrumentation().getTargetContext().getResources()

Note, however, that you can never modify files in the assets folder;

getResources().getAssets().open(sourceFile)

returns an InputStream. There's no way to modify the file. That's because assets are stored compressed inside the APK, and are not really writeable at all.

If what you want to do is modify the path to the files the Activity you're testing uses, you should use ActivityUnitTestCase and setActivityContext() with a RenamingDelegatingContext. This allows you to redirect file and database access in a context to a new directory by specifying a directory prefix. You can even use the more complex constructor to wrap the target context for most operations, but use your test application's context for file operations, so the activity will access files stored in the test application rather than the primary application but still use other resources in the primary application.

Alex Pretzlav
Thanks so much for the great answer. I see that I still have a lot to learn about Android testing. I'll update you when I'm able to implement one of these solutions.
glenviewjeff
When I tried to execute the InputStream in = getResources().getAssets().open("test.txt") in my test application, and placed a file named "test.txt" in my assets directory, I got an exception.
glenviewjeff
@glenviewjeff In what context were you calling getResources()? In a test method or inside an activity launched from a test? Are you sure the `Resources` you were using came from the Instrumentation's `getContext()` and not `getTargetContext()`?
Alex Pretzlav
This was from within a test method. It seems you are implying that I can and should create an activity from within my test code, and that is where I should perform this file access?
glenviewjeff
A: 

What I've done to accomplish this (in a not very elegant way) is to copy the test fixture onto my device (or emulated device.) I named it "cleantestdatabase.db." Then in the test code, I copy it to "testdatabase.db," so that I can modify it with my tests but reset it to a known state. Here's the code:

copyFile("cleantestdatabase.db", "testdatabase.db");

private void copyFile(String source, String dest) throws IOException{
    String rootPath = Environment.getExternalStorageDirectory().getAbsolutePath() + getActivity().getString(R.string.default_dir);
    File newDir = new File(rootPath);
    boolean result = newDir.mkdir();
    if(result == false){
        Log.e("Error", "result false");
    }

    InputStream in = new FileInputStream(rootPath + source);    
    File outFile = new File(rootPath + dest);
    if(outFile.exists()) {
        outFile.delete();
    }
    outFile.createNewFile();

    OutputStream out = new FileOutputStream(outFile);
    byte[] buf = new byte[1024];
    int len;
    while ((len = in.read(buf)) > 0) {
        out.write(buf, 0, len);
    }
    in.close();
    out.close();
}
glenviewjeff