Using factories for cleanliness in Android testing

I am on a team building a native Android app for a local credit union. We are doing some really cool stuff around testing with unit tests, automated instrumentation tests using spoon, and manual user experience testing. We are working in a low-ceremony, flow-based process with continuous client feedback.

One tool we are using to greatly improve our test quality is factories. Android uses Java and so the very name “factory” on a Java project (for a credit union, no less) is probably making you think of BaseAbstractStrategyBuilderFactoryImpl and such, but such enterprisyness is not the case.

Factory chimneys billowing polution

In reality, factories aren’t obligatorily complex: we are simply building an object. If there was any business logic going on I’m sure it would be more complex, but we’re just using them in tests to make writing, debugging, and understanding them easier. Even with a test-first development flow, many tests end up needing some state setup to run correctly and hit to correct code paths. And state setup is a chore.

Java is fairly verbose. Factories allow us to hide that boring instantiation and assignment snooze-festing in a separate place from the main test function.

Take this example from a bit of code I’ve been working on recently. I’ve added some Arrange, Act, Assert comments to make this easier to follow.

@RunWith(AppTestRunner.class)
public class AccountsListActivityTest extends AppActivityUnitTestCase<AccountsListActivity> {

    public AccountsListActivityTest() {
        super(AccountsListActivity.class);
    }

    @Test
    public void selectingAccountListItemLaunchesAccountDetail() {

        // Arrange account
        Account account = new Account();
        account.id = "checking-account-id";
        account.name = "CHECKING";
        account.isInCashFlow = false;
        account.isFavorite = false;

        // Arrange group
        AccountGroup group = new AccountGroup();
        group.id = "group-id";
        group.owners.add("George E. Meade");
        group.owners.add("Robert E. Lee");

        // Arrange group account
        group.accounts.add(account);

        // Arrange list item
        AccountListItem accountListItem = new AccountListItem();
        accountListItem.build(group, account);

        // Act
        activity.onItemSelected(accountListItem);

        // Assert
        Intent startedIntent = assertThat(activity).launchedActivity(AccountDetailActivity.class);
        assertThat(startedIntent).hasExtra(AppExtras.ACCOUNT, account);
    }
}

Not very thrilling? At least it is straightforward, especially since you can see exactly what state is necessary to build make this action work. But why do we care that you can only build an accountListItem from a group and an account? Why do we care that account.isFavorite is required? “isFavorite = false” is my motto when it comes to this load of excess. All of the necessary state arrangements are clear, necessary, and completely irrelevant to what we’re testing. The boring explicitness makes the thing we care about hard to find. I told you this was a snooze-fest.

I’m going to take all the arrange stuff out and make a private method on my test class to hide all the boring setup.

@RunWith(AppTestRunner.class)
public class AccountsListActivityTest extends AppActivityUnitTestCase<AccountsListActivity> {

    public AccountsListActivityTest() {
        super(AccountsListActivity.class);
    }

    @Test
    public void selectingAccountListItemLaunchesAccountDetail() {
        // Arrange
        AccountListItem accountListItem = setupState();

        // Act
        activity.onItemSelected(accountListItem);

        // Assert
        Intent startedIntent = assertThat(activity).launchedActivity(AccountDetailActivity.class);
        assertThat(startedIntent).hasExtra(AppExtras.ACCOUNT, account);
    }

    private AccountListItem setupState() {
        // Arrange account
        Account account = new Account();
        account.id = "checking-account-id";
        account.name = "CHECKING";
        account.isInCashFlow = false;
        account.isFavorite = false;

        // Arrange group
        AccountGroup group = new AccountGroup();
        group.id = "group-id";
        group.owners.add("George E. Meade");
        group.owners.add("Robert E. Lee");

        // Arrange group account
        group.accounts.add(account);

        // Arrange list item
        AccountListItem accountListItem = new AccountListItem();
        accountListItem.build(group, account);
    } 
}

The setupState() method is still pretty overwhelming, but we can ignore it when we read the test method and that is an instant readability win.

Now comes the point of this article. Since we don’t care about the details of the state setup for this test and the (redacted) others in this class, we can move all this out into a factory that will build the objects we need for us. Now other test classes that will need similar state just say “give me one” and no fuss will ensue. The reusability aspect is really nice. The test is now looking clean.

@RunWith(AppTestRunner.class)
public class AccountsListActivityTest extends AppActivityUnitTestCase<AccountsListActivity> {

    public AccountsListActivityTest() {
        super(AccountsListActivity.class);
    }

    @Test
    public void selectingAccountListItemLaunchesAccountDetail() {
        activity.onItemSelected(basicAccountListItem());

        Intent startedIntent = assertThat(activity).launchedActivity(AccountDetailActivity.class);
        assertThat(startedIntent).hasExtra(AppExtras.ACCOUNT_account, account);
    }
}

In my factory I’ve refactored the state into a few simple, reusable methods that I can mix and match. This arrangement grew out of the needs of the various tests as we wrote them and needed different pieces of data.

public class AccountsFactory {

    private static AccountGroup emptyGroup() {
        AccountGroup group = new AccountGroup();
        group.id = "group-id";
        group.owners.add("George E. Meade");
        group.owners.add("Robert E. Lee");

        return group;
    }

    public static AccountGroup groupWithAccount(Account account) {
        AccountGroup group = emptyGroup();
        group.accounts.add(basicAccount());

        return group;
    }

    public static Account basicAccount() {
        Account account = new Account();
        account.id = "checking-account-id";
        account.name = "CHECKING";
        account.isInCashFlow = false;
        account.isFavorite = false;

        return account;
    }

    public static AccountListItem basicAccountListItem() {
        AccountListItem accountListItem = new AccountListItem();
        accountListItem.build(groupWithAccount(), basicAccount());

        return accountListItem;
    }
}

The Aesop-approved moral to this story is to only put the relevant stuff in the test and hide the rest of the boring state-making in a convenient spot for reuse. On this current project we call them factories, and they work great.

You have to start somewhere

I started fresh in at SEP on Monday and by Tuesday the bananas were fresh out.

Fellow new guy Jackson and I were tasked with our first project on Monday just before quittin’ time: update the internal résumé reporting website from ‘ancient’ to ‘tomorrow.’ It currently runs on a mid-2006 vintage copy of Ruby on Rails (version 1.1.6). We’re supposed to be bringing it up to Rails 4 (coming soon, 2013) but some fundamental pieces of its inner-working were axed from Rails by the end of 2006. We’re not supposed to rewrite the project, just bring it up to date, but many important pieces cannot be upgraded.

Full disclosure: I’m fresh in when it comes to Rails (“never touched the stuff”), so by Tuesday afternoon my brains were fresh out. And, as I said before, so were the bananas.

As we passed through The Commons during the first-day tour, Laura from HR said “there shall be fruit” and, unfortunately, there was no fruit. In my hour of need: fresh out. To quote the great Barney Fife, “Well, Andy, a slender high-spirited person needs a sugar pick-me-up late in the day.” I had to settle for a cup of ice. Just then, something happened…

Chapter 2. Just when hope is almost lost, things start to look brighter for our young heroes.

A remarkable thing about SEP: everyone is willing to help. Not to be too self-critical (and Jackson’s effort, to be fair, was nothing short of heroic), but we needed help.

There are many things I don’t know. Rails is not the only thing on that list. Here are a few others to get you started. I don’t know:

  • The name of the git server (easy to guess)
  • The name of the TFS server (impossible to guess, sounds more like a band name)
  • The name of the database server (easy, but after the TFS server I was expecting anything)
  • The name of the project (five-digit number starting with 06)
  • The name of the guy in the next cube (I love the three-monitor setup)

I also don’t know about many company policies. For instance, do lowly developers need an official sanction from IT to brazenly install Ubuntu VMs on our machines (no). And I haven’t even started on all the questions we had about the résumé website’s architecture and history.

Chapter 3. Sorry about chapter 2, this is where things actually get better.

Matt Swanson. He has worked on the résumé system. We asked him a lot of dumb questions and he gave us a lot of good answers. He helped us a ton and he’s given the project a fresh start.

I would like to give a You Rock™ card to Matt (like they told us about in orientation), but I don’t know where they are.

P.S. For non-SEPeers: if you are given two You Rock™ cards of the same color or one each of both colors, you can turn them in to receive Good Stuff™.

6 Tips for Maximum Adventure Between 20 and 28

Advice on Your 20th Birthday from the Perspective of 28 Years

Dear Friend,

The decade which you now commence is fraught with adventure.

When I was 20, I had lived my entire life in a conservative Christian environment. I was homeschooled, and I earned my bachelor’s at Verity Institute. I was a well-learned kid.

Since then I have held 8 job titles at 5 departments of 3 companies in 3 states. I’ve been on three international business trips. I’ve taken 20 church youth group kids to Magic Mountain in L.A. I’ve been turned down by the girl I loved. I’ve taught Austrian tourists how to surf. I’ve been let go from my job. I’ve eaten from street vendor carts in Mexico. I’ve been in 6 weddings: thrice as groomsman, twice as best man, and once as groom. I’ve been lost in the desert for two days waiting for a helicopter to find us. I’ve moved 6 times. I’ve had a daughter (another one on is the way). I’ve laughed a lot.

Life goes crazy after you turn twenty: after you leave schooling behind and start doing. There are lots of things to do and lots of things to have happen. Embrace it. Here are a few tips to get you started.

Don’t Live Temporarily. We often say “I’m just doing this for now” we don’t think we’ll be doing it for “the rest of my life.” Mortal life by its very nature is not permanent, why dwell on the fact? Live whole-heartedly where ever you are (Psalm 1:3). Who cares if you only ‘plan’ to be somewhere for 1 year? Get state residency, join a local church, attend a weekly/monthly group of your interest and settle in. You may only be there for a year, but at least you enjoyed it and belonged. If you end up staying for 20 years, at least you didn’t wake up 14 years in and realize you have been living like a homeless nomad, minus the change of scenery. Bloom where you are planted, and if you move, start blooming there too. of course, this principle applies to more than just locations, but jobs, etc. too.

Avoid Debt. Debt is slavery: don’t go there. If you only spend less than what you have you will never be short of money (although you not have many things). A person in debt cannot live more cheaply because they have obligations they cannot refuse.

Don’t Avoid Responsibility. Responsibility is power. Responsibility is the voluntary acceptance of the important things in life inspiring you to govern your behavior for the good of others. Irresponsibility seems like more freedom, but in the end you’ll feel like a kid, and that is not fun when you are an adult. In the end, irresponsibility makes you feel worthless, but responsibility makes you feel needed, important, and satisfied with the good things you create.

Be Involved. A good marriage is the best thing in life, and children are a close second. The people around us are what make life fun. Don’t do it alone. Don’t be stingy with who you like, like as many people as possible. Try to help them, good deeds have a way of making their way around, helping everyone, and often helping you in return.

Become Really Good At Something. If you start now, you will be really good at it in 10 years. Pick something you like doing; something that almost makes you feel more energized when you’re done with it then when you started, but be sure it’s something that someone might pay you for.

Make People Happy. Jesus said, “Sufficient for the day is the evil thereof.” (Matt. 6:24) Sometimes the word evil sounds like the simplest description. People live with hearts full of hurt, pain, disappointment (or in the words of Les Miserables “Life has killed the dream I dreamed”): Help ease other’s burdens being bring a wee bit o’ joy where ever possible. A merry heart is so powerful the FDA should regulate it (Prov. 17:22).

This decade is fraught with adventure. If you live according to my advice, and even more so if you follow the Bible’s wisdom, you can experience much adventure. A word of warning, adventure is sometimes difficult, but it’s always rewarding.

May God’s ample blessings comfort you and bring you joy and peace.

Ryan

Bending Linq-to-Entities to my will

I am building an ASP.NET MVC 4 application using Entity Framework as my ORM on top of an existing SQL Server database. This is model-first, not code-first. I am fairly new to Linq-to-Entities. Recently I ran into something that gave me many problems and I had great trouble finding any help online. I’ve now solved it, twice. This is my story.

I have a view that need to display a list of Modules (as in, classroom teaching). Each Module belongs to a Unit, but each Unit can have many Modules. Each Module can have multiple Instructors, and each Instructor can teach many Modules. There is a ModuleInstructor table to join that relationship.

Unit -1:N- Module -N:1- ModuleInstructor -1:N- Instructor

EntityFramework has these for objects [unnecessary properties trimmed for brevity]:

Anyway, I wanted to display: UnitName, ModuleDate, Instructor(s) in a comma-separated list. My problem was that I had the hardest time getting Linq to get the Instructors, all I could retrieve was the ModuleInstructors which didn’t have any of the Instructor information loaded.

My first solution was to modify the Module class to add another collection:

In the ModuleController I got everything except the Instructors, then the Instructors separately and for looped through inserting them into the collection.

According to LinqPad this take two SQL statements. Not too bad. It’s not that much of strain on the server either because I don’t have many Instructors and there are only 20 Modules being shown at any one time.

However, I figured there must be a way to do it in one database call. Here’s my new solution. I still loop through inserting Instructors into the Modules object’s Instructor collection, but I get all the Instructors with everything else.

 

According to LinqPad it takes only SQL statement and it performs slightly faster that the first method.

To be perfectly honest, I have trouble picturing exactly how this works and why, but it does. I am very happy that I stuck with the problem, coming back to it several times more until I got it “just right.”

My one question: is this the best way to do this or is there a still better way? Maybe I’ll never know, but at least it’s better that it was before.

See Linq-to-Entities with a many to many relationship on StackOverflow for more discussion regarding this problem.

How to join T-Mobile’s Monthly4G prepaid service with a micro-SIM phone

T-Mobile is offering customers an incredible catch-22… I mean, deal. I have wanted a Windows Phone for a year now but could not justify paying a smartphone-priced cell plan. So when I saw T-Mobile’s $30 per month online-only plan I pounced. My Windows Phone dreams would happen–and all while saving $20 over my current Verizon plan.

But it’s all a cruel trick and the system is broken. You see, the deal is only on the web, so I couldn’t buy the $20 in-store SIM card kit since they don’t let SIM kits walk out inactivated. No problem, that’s what e-commerce is for. So I got my card online and only paid $1.06 with shipping. Feel the savings!

T-Mobile SIM Card

But on arrival, it turned out to be the full half-acre: way too big to fit the cute little slot in my Nokia Lumia 710. I need micro-SIM, not full SIM. I went back online to get the other kit. Wait a minute, there is no other kit. Yes, I called and no, they do not sell micro-SIMs online at this time.

So here’s the T-Mobile Web/Store Deadlock™: the website won’t provide micro-SIM,the  store won’t provide the deal. I won’t retell the full three-day saga of phone calls and web searches, but I tried everything and even considered buying a SIM cutter (it’s always amazing how manythings there really are to buy). The system was completely broken and I couldn’t figure out why. The frustrating thing was the thought that there’s no way I’m the only one trying to do this.

In the end I didn’t buy the tool, as cool as it looks. Turns out you can simply go into any T-Mobile store and get an activated SIM card switched out for a micro-SIM. Activation involved entering long serial numbers from both SIM and phone into the website and doesn’t involve turning the phone on. So I activated the big card online without it ever touching my phone and got the deal. Then went into the store and asked for a switch-out to micro-SIM. Total price: free.

The system is not broken; instead it is simple and friendly. Too bad they never say how to do it! So I’m putting it here so that the world might know.

Steps to get a T-Mobile Monthly4G micro-SIM phone running:

  1. Buy SIM Activation kit on prepaid-phones.t-mobile.com
  2. Activate online at the same site, remember to record the SIM serial number (helpful for step 4)
  3. Go to a T-Mobile store and have them switch the full-size SIM for micro-SIM
  4. Call T-Mobile customer service and make sure the new micro-SIM serial number is on your account (ensures the store representative did it right)
  5. Wait for confirmation text
  6. Fill account with enough money to get the first month started

If this saves even one person 1) from emotional stress or 2) overspending for a smartphone plan then I will be happy. I’m happy anyway because I now have a Windows Phone 7.5 and it’s connected: what a great experience.