Michael Evans

A bunch of technobabble.

Stop Repeating Yourself: Sharing Test Code Across Android Modules

| Comments

It seems like nowadays, the best advice is to modularize your Android app. It’s a great suggestion for many reasons, including but not limited to:

- improved build performance
- enables on-demand delivery
- pushes you to build reusable, discrete components

Sounds great, right? Are there any downsides? There is one in particular which has been a a pain point for many.

Often times when you’re writing tests, you’ll want to use some test doubles like fakes or fixtures in order to help simulate the system under test. Maybe you have a FakeUser instance that you use in your tests to avoid having to mock a User every time your test calls for one. Generally these classes live alongside tests in src/test directories and are used to test out your code within a module.

For example, maybe you have a model object like:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class User {
    private final String firstName;
    private final String lastName;

    public User(String firstName, String lastName) {
        this.firstName = firstName;
        this.lastName = lastName;
    }

    public String getFirstName() {
        return firstName;
    }

    public String getLastName() {
        return lastName;
    }
}

You might have some code in src/test that creates a bunch of fake users for your tests like:

1
2
3
4
5
class TheOfficeFixtures {
        public static User manager = new User("Michael", "Scott");
        public static User assistantToTheRegionalManager = new User("Dwight", "Schrute");
    }
}

This works great if you’re testing code within a module, but as soon as you’d like to use these fake users in other modules, you’ll note that these classes aren’t shared!

This code can’t be shared between modules because Gradle doesn’t expose the output of your test source set as a build artifact. There are all kinds of solutions for this problem out there, including creating a special module for all your fixtures, and using gradle dependency hacks to wire up source sets.

However, that’s not necessary anymore! As of version 5.6, Gradle now ships a new ‘test-fixtures’ plugin! This plugin creates a new testFixtures source set, and configures that source set so that:

- classes in this set can see the main source set classes
- test sources can see the test fixtures classes

Using the Plugin

You can apply the java-test-fixtures plugin in your build.gradle script:

1
2
3
plugins {
    id 'java-test-fixtures'
}

This plugin will define the necessary source set, and handle all the wiring up of test artifacts. We can now move those test fixtures from src/test/java to src/testFixtures/java, and that’s it! These classes will be ready to be consumed by other modules.

Wiring it all together

Finally, we need to use a special keyword to pull these new fixtures in as a dependency for our tests. In our gradle configuration, we add a test dependency (either API or Implementation) like so:

1
2
3
dependencies {
    testImplementation(testFixtures(project(":lib")))
}

And that’s it! Our other module can now consume these test fixtures without any sort of intermediate modules or workarounds.

If you’d like to check out the complete configuration with examples sharing fixtures between both Kotlin and Java modules to a shared “app” module, I’ve uploaded a sample project demonstrating how to use this new configuration here.

Important Caveat

It’s important to note that this feature is currently only available with the java-library plugin, and has limited functionality in Kotlin modules, and not yet available for Android modules. There are currently feature requests on YouTrack and the Android Issue Tracker to take advantage of this new functionality.

Hands on With ViewPager2

| Comments

Today Google released their alpha of ViewPager2, a signal of the nail in the coffin for the original ViewPager, originally released in 2011!

Since then, I think it’s safe to say that most developers have needed to make a ViewPager. Despite how prolific it is, it certainly isn’t the most straightforward widget to include. I think we all have at least once wondered whether we should use a FragmentPagerAdapter or a FragmentStatePagerAdapter. Or wondered if we can use a ViewPager without Fragments.

And API confusion aside, we’ve still had long standing, feature requests. RTL support? Vertical orientation? There are numerous open source solutions for these, but nothing official from the support library (now AndroidX)…until now!

Let’s dive in and try to set up ViewPager2! You’ll need your project configured with AndroidX already, as well as supporting minSdkVersion 14 or higher.

Enabling Night Mode on Android Nougat

| Comments

If you’re like me, you loved the Night Mode feature that was added to the Nougat Developer Preview a few months ago. You might have been disappointed when you found out that it was missing in later preview builds, and was probably going to be removed because it wasn’t ready.

When the source code for Nougat was released this morning, my friend Vishnu found this interesting snippet in the SystemUI source (better known to end users as the System UI Tuner):

1
2
3
4
5
boolean showNightMode = getIntent().getBooleanExtra(
    NightModeFragment.EXTRA_SHOW_NIGHT_MODE, false);
final PreferenceFragment fragment = showNightMode ? new NightModeFragment()
    : showDemoMode ? new DemoModeFragment()
    : new TunerFragment();

Long story short, if you pass the right extras to this activity, and you’ll get access to the Night Mode settings (as well as the infamous Quick Tile!).

Fortunately for us, this is pretty trivial to accomplish with adb via adb -d shell am start --ez show_night_mode true com.android.systemui/.tuner.TunerActivity, but not everyone who wants this feature is familiar with adb. So I published an app to the Play Store that does exactly that – click one button, and get access to those settings! You can find the app on the Play Store here.

Using Build Types With the Google Services Gradle Plugin

| Comments

If you want to integrate your Android app with most of Google Play Services nowadays, you’ll find that you are instructed to set up the Google Services Gradle plugin to handle configuring dependencies. The plugin allows you to drop a JSON file into your project, and then the plugin will do a bunch of the configuration for your project, such as handling the API keys.

This is all well and good—unless you’re like me (and countless others) and want to use a different configuration for your debug and release builds. This would be useful, as an example, if you use Google Play Services for GCM and would like to have development builds recieve pushes from non-production systems.

It seems that the plugin is configured in such a way that it supports build flavors, but it does not yet support build types. However, with a little Gradle magic, we can hack that support in.

Changelog for N Support Libraries

| Comments

Pssst! If you’re an Android developer, you might not have heard yet…the N Preview started today! As part of the festivities, a new alpha version of the support libraries was released. There was no changelog that I could find, so I decided to make one. Here’s what has changed (so far) in the public API of a few of these libraries:

Testing Intents With Espresso Intents

| Comments

A few weeks ago, I wrote a basic introduction on how to use Espresso to test the UI of an Android application. However, when I went to write instrumentation tests for Aftermath, I ran into trouble testing things that exist outside my application’s process. For example, what do you do when your app needs to use the Android Intent system to call upon the dialer or the browser, or pick a contact with the contact picker? What about testing a share action? Because these apps run outside your application itself, you can’t use Espresso to interact with them. So how can you test your app’s behavior? You can either use Espresso-Intents or UI Automator (but that’s another show).

Using Espresso for Easy UI Testing

| Comments

One thing that I notice when I talk to Android developers is that a lot of them don’t put an emphasis on testing. They say that it’s too hard to write them or that they are too hard to integrate and set up, or give a bunch of other reasons why they don’t. But it’s actually pretty simple to write Espresso tests, and they really aren’t that hard to integrate with your code base.