Monday, November 13, 2017

Types of Android Tests

I saw this Reddit discussion on Android testing concepts, which tries to categorize tests into short, medium and long. I don't find that a very useful way to think about different types of tests, so I thought I'd give offer my view.

Two dimensions

I think it's more useful to think of tests in two dimensions

  • Does it run on the JVM or needs a device?
  • Does it test the UI or not?

Depending on the answer to these two questions you get 4 types of tests.

JVM tests

JVM tests are the faster to run since you don't need to deploy to a device (physical or emulator), and should be preferred. Try to structure your app so that the logic is in pure Java classes i.e. does not use the Android framework.

Since we are writing Android apps, it is difficult to test the UI without the Android framework. There are two ways you can do that.

Robolectric

The first way to test the UI on the JVM is Robolectric, which mocks the Android framework. I don't recommend that, because the mocked classes don't necessarily reflect the actual behavior on the Android framework.

Model-View-Presenter (MVP)

The second way is to make your Android classes as logic-free as possible. There are various architecture patterns you can use to achieve that, for an example Model-View-Presenter (MVP). MVP allows you to encapsulate the Android part inside the View (Activity or Fragment) and extract the logic into the Presenter, which does not use any Android framework code. This way, you can test the Presenter on the JVM.

Espresso

After you have tested your logic extensively on the JVM (you may want to aim for 100% test coverage), you should add some UI tests. Think of these as sanity checks, going through the happy path to make sure the app does not crash when you bump up the library version. I use Espresso for UI tests, together with Mockito and MockWebServer to set up a hermetic environment for repeatable tests.

More info

Thursday, May 11, 2017

Why I run a conference

As some of you know, I'm one of the organizers for 360|AnDev. It's a lot of work to run a conference, so why do I do it?

I started the conference because I want an inclusive place for people to learn about Android:

  1. We want it to be welcoming to beginners so that they can plug into the community right away. That's why we have a "Getting Started" track (see our CFP).
  2. We want to encourage first-time speakers, so we run Q&A Hangouts to answer as many questions as we can.
  3. We want people to speak regardless of their financial situation, which is why we cover the travel costs for speakers if their companies do not.
  4. We have inclusivity scholarships to help people who cannot otherwise attend.

We did not collect attendee statistics last year, but you can see from our speaker lineup that we were off to a good start in terms of inclusivity.

We need your help

Last year we managed to break even, which was really good for a first-year conference that covers travel costs for speakers. We hope to keep it up, to have a financially viable event that we can run again and again. But we need your help:

  1. Please spread the word. Tell everyone about the event:
    July 13 - 14, 2017. Denver Colorado. 360andev.com.
  2. If you plan to attend, please buy a ticket right away so us organizers are not sitting at the edge our seats wondering if anyone would come.
  3. If you are at a company, please ask your employer if they would like to sponsor the conference: 360andev.com/sponsorship.
  4. Support us via Patreon: https://www.patreon.com/360andev

Every bit helps. Thank you for your support!

Sunday, April 16, 2017

Droidcon Boston Keynote

I just came back from the inaugural edition of Droidcon Boston last week, at the beautiful Calderwood Pavilion.

Keynote preparation

I had the honor to deliver the Day 2 keynote at Droidcon Boston.

I prepared extensively when I first gave this keynote at Android Summit, so this time I was relatively chill about it. I updated some of the slides, and gave a practice version at Denver Droids. For a last minute refresher, I brought the video recording on my laptop and watched myself give the talk on my flight to Boston.

Fresh material

Normally I do not tweak my talk the day before the conference, but after seeing the shout-outs in Annyce's opening keynote I was inspired to do the same.

My talk is about how sharing makes you an expert, and I used tweets from day 1 of the conference as examples.

Learn from each other

That is the beauty of going to a conference: we learn, we share what we learn, and we lift each other up. It was really rewarding to see people getting out of their comfort zone to tweet, blog, sketchnote, and plot to give their very first talk. This is how we build a community.

Watch the keynote

Thursday, March 16, 2017

Lint stuck after upgrading gradle plugin to 2.3.0

app:lint hangs after I upgraded the gradle plugin to 2.3.0.

Unexpected failure during lint analysis (this is a bug in lint or one of the libraries it depends on)

It complains about ProblemReporter.isClassPathCorrect(ProblemReporter.java:4761) and other places in ProblemReporter, but I was not able to pinpoint the problem.

Turns out this is caused by libraries that uses old lint APIs, in my case Timber and Butterknife. Once I updated those dependencies, lint finishes.

Thanks Josh Burton for sharing his solution with me!

Monday, February 13, 2017

Constraint Layout beta5 lint error

Constraint Layout beta 5 is the release candidate, and added a lint to deprecate older versions.

The easiest way to get rid of the lint error is to press Alt-Enter and choose the first option to upgrade.

However, I encountered a bug, which forces me to stay with beta4 until the next version comes out with the fix. I still want to get rid of the lint error so my continuous build does not fail. I didn't want to change lintOptions abortOnError to false in build.gradle because I still want my build to catch other fatal lint errors.

I tried to get Android Studio to fix this lint error for me by choosing Disable inspection from Alt-Enter. Alas, that only changed the local settings. Turns out that I need to go to Settings → Editor → Inspections to undo that.

The option I wanted is Suppress: Add tools:ignore="MissingConstraints" attribute, which modifies the xml for me to add the appropriate lint suppression.

<android.support.constraint.ConstraintLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:app="http://schemas.android.com/apk/res-auto"
  xmlns:tools="http://schemas.android.com/tools"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  tools:ignore="MissingConstraints">
<!-- Cannot upgrade to beta5 due to http://b.android.com/233863 -->

Finally, I added a comment to remind me why I suppress the lint error.

More info: Suppress Lint Warnings.

Monday, January 16, 2017

Java compatibility in build.gradle

I got an email from Google asking me to update Fit Cat for Android Wear 2.0, so I tried to compile that app after I haven't touched it for a few months.

Since Android Studio evolves so quickly, I wasn't exactly surprised when I got an error:

Error converting bytecode to dex:
Cause: Dex cannot parse version 52 byte code.
This is caused by library dependencies that have been
compiled using Java 8 or above.

It asked me to add sourceCompatitbility and targetCompatitbility to Java submodules. What does that mean? After a lot of searching plus trial and error I found the answer.

In your top-level build.gradle, add this:

allprojects {
  tasks.withType(JavaCompile) {
    sourceCompatibility = JavaVersion.VERSION_1_7
    targetCompatibility = JavaVersion.VERSION_1_7
  }
}

Thursday, December 1, 2016

Elite Worship

Yesterday I read an article called In a world..., which talked about the problem of elite worship in the iOS community. I'm an Android developer, but I see the same problems in our community as well.

Here is how I see it:

  • People who tweet, blog, speak and open source are considered elites
  • Elites are held above the rest of the community, making it unwelcome for others

Does being loud make you a better developer?

Or, flipping the question, are people who don't share their work inherently worse? No, of course not. Unfortunately, unseen work is just that: unseen. Without external evidence, there is no way to tell if a developer is good or not, so we assume they are average. Not better, not worse.

I, too, would like to believe that we live in a meritocracy where good work is automatically recognized. But how? How do people know what you are doing if you don't tell them?

This encourages people to run up a hill and yell on top of their voice. And the people who are comfortable doing that are rewarded, are seen as "better".

However, this is not automatically lead to elite worship. Yes, there will always be some people who are more visible in the community. But that does not mean it has to be a small group who are revered above all else.

What you can do

When you see good work, point it out

One problem of elite worship is that we ended up comparing ourselves with people with more Twitter followers, more mentions in the industry newsletter, more conference talks etc and feel defeated. We can counter that by pointing out the good work we see that is not enshrined on the internet.

Here is a concrete thing you can do: When you do a code review, don't just point out the things to fix. Remark on the good parts as well.

When something takes longer than expected, write it down

We need more voices in our community. Blogging is great, because there is no gatekeeper to decide who gets to publish and who doesn't. But there is still one hurdle: What to write about?

Pay attention to what you do day to day. If you spent more time figuring out how to do something than you thought you would, it is worth writing down.

Don't worry about looking stupid because others must know how to do it already. You don't have to push the boundaries of human knowledge. That's PhD theses, not blog posts.

Think of it as notes to your future self, a place to put codes and commands in monospace font so you can come back in 3 months to copy and paste them.

Just because some people share more doesn't mean there is no place for you to do it. Everyone has a different experience, and we want to hear from you.

Speak at local meetups

In the original article, the author laments that there is no diversity at conferences. Always the same faces, always the same topics. As a conference organizer, I can tell you that speaker selection is hard. There were so many people that very much deserved a speaking slot but didn't get one, because we had a very limited number. You can read more about how we try to have a balanced speaker roster at 360|AnDev.

That said, we don't have to let conferences be the only place where technical talks are given. There are numerous meetups happening all over the world on any given week. And they are always, always looking for speakers. Sure, it does not come with the prestige of conference speaking, but does that make them worthless?

If you think the local audience is too small to worth your time, record your talk and post it on the internet. I wrote a guide on how to record your screen and voice with QuickTime. Would love it if someone write one for Open Broadcaster Software (OBS)!

Give talks yourself, and encourage those around you to do it. That is how we get new voices. Don't let the conference speaking circuit dictate who gets to speak and who doesn't.

Sharing != Elite Worship

People are lazy. If we see the same name over and over, we think that person must know something. This is fundamentally what leads to elite worship. We can't change human nature, but we can spread the love. Point out each other's good work, encourage each other to make it visible. Make the elite circle so large that it is no longer elite.