RSS Feed
Jun 30

How to create Shadow classes in Robolectric 3

Posted on Tuesday, June 30, 2015 in Coding

Mobile application testing is one very important feature of app development. So is diagnostic logging for debugging purposes. Robolectric is one of the good frameworks out there for running very fast tests of your Android application inside the Java virtual machine.

Robolectric can be extended by use of shadow classes which modify the behaviour of certain classes in the Android OS. However, your application also depends on other libraries which are not included in the Android framework. Fortunately, Robolectric gives you the means to create shadow classes for external libraries which you use so you can modify or extend the behaviour of the library during testing.

Shadow classes for classes in the Android framework are automatically picked up and loaded by Robolectric during testing, but shadow classes for third-party libraries need a bit more work for Robolectric to use them. In Robolectric 3, the way to create shadow classes has changed from previous versions. There isn’t much documentation for the new release yet, so after some experimentation, I found a way to create shadow classes which I am documenting here for future reference.

In my case, I was creating a shadow class for the Crashlytics logging library so that I could disable all logging to the service during testing. I created my shadow class as follows:

@Implements(Crashlytics.class)
public class ShadowCrashlytics {

    @Implementation
    public static void start(Context context){
        System.out.println("Shadowing crashlytics start");
        //nothing to see here, move along
    }
}

The @Implements annotation allows you to specify which class you are shadowing. Also you need to implement the methods with the exact same signatures as in the original class. In this case, I only needed one method, the start() method which should do nothing.

Next thing to do is to implement a test runner which you can use to load the tests into the app. An example of such class looks like this (code adapted from this link):

public class GnucashTestRunner extends RobolectricGradleTestRunner {

    private static final List<String> CUSTOM_SHADOW_TARGETS =
            Collections.unmodifiableList(Arrays.asList(
                    "com.crashlytics.android.Crashlytics"
            ));
    public GnucashTestRunner(Class<?> klass) throws InitializationError {
        super(klass);
    }

    @Override
    protected ShadowMap createShadowMap() {
        return super.createShadowMap()
                .newBuilder().addShadowClass(ShadowCrashlytics.class).build();
    }

    @Override
    public InstrumentingClassLoaderConfig createSetup() {
        return new InstrumenterConfig();
    }

    private class InstrumenterConfig extends InstrumentingClassLoaderConfig {

        @Override
        public boolean shouldInstrument(ClassInfo classInfo) {
            return CUSTOM_SHADOW_TARGETS.contains(classInfo.getName())
                    || super.shouldInstrument(classInfo);
        }

    }

}

The test runner needs to be declared in your Gradle file in the defaultConfig section as follows:

testInstrumentationRunner "org.gnucash.android.test.ui.GnucashAndroidTestRunner"

Also, all the test classes should have the annotation:

@RunWith(GnucashTestRunner.class)
@Config(constants = BuildConfig.class, shadows = {ShadowCrashlytics.class})

Note that we declare our shadow class in the annotation so that it is loaded. If you have more than one shadow class, add it to the list separated by commas.

And that’s it! Now when you run your tests, your custom shadow classes should be loaded and executed.

 

Jun 22

Importing GnuCash XML in GnuCash Android

Posted on Monday, June 22, 2015 in Coding

GnuCash Android has for some time (since version 1.4.0) supported importing accounts from GnuCash desktop. However, the first iteration of this feature was not very easy to use. It was necessary to first export the accounts from GnuCash desktop as non-compressed XML and then feed that output file into GnuCash Android.

With recent updates, it is longer necessary to export accounts before importing into the Android app. Your GnuCash XML file from the desktop app can be directly imported by the GnuCash Android app without any modifications.  Also you do not need to worry about whether or not your XML file is compressed or not, both are supported. All you need to do is to make sure you save your GnuCash files as XML (and not SQLite database format).

GnuCash Android version 1.6.0 also supports backing up your transactions to GnuCash XML format, as well as limited support for parsing template transactions and scheduled transactions. This, combined with the scheduled exports feature, makes it possible to regularly backup your accounts and transactions as GnuCash XML and view these backups in the GnuCash desktop app.

We hope this simplification around file import improves the utility of the GnuCash Android app vis-á-vis GnuCash desktop. As always, feedback is always welcome.

Jun 19

GnuCash Android v1.6.0 release

Posted on Friday, June 19, 2015 in Coding, GnuCash

I am pleased to announce the release of GnuCash Android version 1.6.0 after 5 beta pre-releases. The update will be made available through the Google Play store on a rolling basis over the next week. So don’t fret if you don’t see an update notification immediately. This releases adds several new features including the following: v1.6.0_nav_drawer

  • Scheduled backup of accounts and transactions
  • Report summary as bar, line or pie charts
  • New backup and restore options
  • Export GnuCash desktop-compatible XML
  • Numerous bug-fixes and improvements

You can also see the changelog for a more detailed listing of the changes. The minimum Android version supported by this release has been increased to Gingerbread (Android 2.3.4). This means that Froyo (2.2) devices will no longer receive updates. Judging from the statistics in the Play store, relatively few users will be affected by this.

This release also refines a lot of features including but not limited to import of scheduled transactions from XML, creating/restoring backups and auto-balancing of transactions with an imbalance account. There is also  improved compatibility of backup XML with GnuCash desktop. GnuCash desktop can now read the XML generated by GnuCash Android. This compatibility, combined with scheduled sync to DropBox/Google Drive, enables some interesting workflows with GnuCash desktop. We shall continue working to improve the interoperability between desktop and Android GnuCash.

Enjoy the release and let us know what you think of it!