Six Weeks of Bathroom Reading

A little over 6 weeks ago, a number of flyers started appearing in the Lookout HQ bathroom. Named “Uncle John’s Bathroom Reader” (after John Hering, Lookout’s CEO), the reader contains a single page of software engineering tips and tricks.

Modeled after Google’s Testing on the Toilet newsletter, Uncle John’s Bathroom Reader aims to help raise baseline of institutional knowledge across Lookout Engineering.

UJBR

After nearly 6 continuous weeks of the reader, the issues are ready for publication:

I hope you find the issues as useful as we have.

- R. Tyler Croy

posted in: · · ·

The art of teaching a technical topic

Recently I gave a couple of talks at the Google Extended Day in Algiers (Algeria). Google Extended are events happening all over the world that Google sponsors and co-organizes with the local communities to allow the developers who couldn’t make it to their annual event Google IO to connect with other developers, learn about new trends/topics, try new hardwares and talk to Googlers. I was invited as a speaker to the event, in order to teach the local community how to develop an Android application.

I gave three talks:

  1. Android Overview - kind of a 101 session.

  2. Android DevTools - introducing different tools used to: develop, debug, test and deploy your android application.

  3. Advanced Android Development - live coding session with an emphasis on best practices to follow while building a mobile app in general and an Android app in particular.

This was literally my first experience as a speaker and I found the task very challenging and fun. In order to share that experience, I decided to come up with a list of good practices to consider when teaching any technical topic; here they are:

1. Set very clear expectations from the beginning

My talks had to be 45 mins long at most (including the Q/A sessions). That’s a very short amount of time and no matter how focused your presentation is, it is hard to teach everything that your audience needs within that timespan. On the other hand, your audience comes to your talks hoping to learn everything they need to magically build their first MVP (Minimal Viable Product) for the Hackathon. So, if you don’t want to disappoint them, it is important to set very clear expectations at the very beginning of your talk. Ultimately you want your audience to understand some fundamental notions and then take it from there to learn more by reading the online documentation. Your goal here, is to be the ice breaker between them and the technology you are presenting.

2. Choose your content carefully

As time is limited you have to make sure that every instant of your presentation is worth an important information. Prior to your presentation, you have to triage the different things that you want to teach. A good process would be:

  1. Brainstorm and write down all the notions you think should be taught.
  2. Classify those notions within 3 categories: Mandatory/Important/Optional.
  3. Prepare your normal presentation with the mandatory and important topics first.
  4. Take your time explaining the topics by their order of importance.
  5. Prepare some extra-slides with the optional notions in case you have extra-time or if they come up in the Q/A session.

3. Know your audience

In order to shape the right presentation, it is important to know who you are going to talk to. Are they students? Are they professionals with a lot of experience? Are they technical at all? Obviously, your material as well as the vocabulary that you are going to use will vary depending on who your audience is.

4. Have a clear narrative

There is a notion in writing called: the Tree-act structure. It is basically a model used in writing a modern storytelling which can be found in a wide range of domains: Drama, poetry, comics, novels, movies, video games, to name a few.

This notion basically states that to tell a good story we have to structure it in 3 acts:

  1. Acte 1: The Setup, which is where all the major characters of the story are introduced.
  2. Acte 2: The Confrontation, which is where all the story, its characters and conflict are all established.
  3. Acte 3: The Resolution, which represents the final confrontation of your story or dénouement.

The nice thing about this structure is that it provides a clear path to bringing some knowledge to an audience. In the case of Android, we could imagine the 3 following acts:

  1. Acte 1: Setting up the context, introducing the software architecture, explaining some fundamentals notions like the Android Runtime, what’s Dalvik and how it works, how does Android manage memory etc. This is probably the most boring part of the talk but it’s so important that you have to find an entertaining way for presenting it.

  2. Acte 2: Use the notions taught during Acte 1 to explain how to build an Android application.

  3. Acte 3: Do a demo.

5. Make sure that your knowledge is correct

There is nothing more embarrassing that teaching something wrong. Now, I suppose that you have been given the responsibility to teach a large group of people about a topic because you clearly have some experience in it. But here is the thing, because you are experienced and because you are using this technology everyday at work you are probably making a lot of assumptions about how certain things work and those assumptions might be a little off. There is a great quote by Yogi Bhajan that says: If you want to learn something, read about it. If you want to understand something, write about it. If you want to master something, teach it. Because your audience will drink your words as if it was water, you can’t afford being too vague you have to own your topic and master it. For example if you want to pass on some details on how Dalvik works, you could take an hour reading the official specification rather than trust whatever is written on Wikipedia.

6. Be prepared to fail

This is a no brainer and kind of related to any type of presentation that involves demoing something. To put it simply: Expect everything to fail! That includes: Internet connection will go down during the event, your favorite IDE will crash, your project won’t compile for some odd reasons and so on. When preparing for your presentations you have to prepare at least 1 backup plan for each failure scenario. Internet will go down? Then download everything that you need so that you can use it offline (example: save the result of an API call in JSON in a file). Afraid that your favorite IDE will freeze and crash many times during the demo? Then be ready to use Vi/Emacs/Sublime Text/ or whatever you love and be ready to use the command line to build and deploy your project. Now, if you experience a demo fail during your presentation then instead of apologizing and running away try to discover what is going on live by thinking loudly and by showing them the tools that you use in order to track down bugs and fix them. Once you recovered from that failure, pass the details along to the audience, explain why it failed and how it is possible to avoid it in the future. This is how you should apologize, by making the failure useful.

7. Be funny & entertaining

You, as a teacher, have great power and that comes with great responsibility. As a matter of fact, the way you are going to teach is likely going to determine whether your audience will develop a passion for that topic or will develop an aversion for it. Everyone has some bad memories about that weird, boring, tyrannical teacher who made every instant of their classes, feel like a nightmare. It is possible that some students end up hating the subject just because of the teacher. The moral of that, is that by making your presentation pleasant to watch and entertaining you are eventually going to create passion for whatever you are teaching. Passion is important, because this is the reason that will motivate your audience to spend their free time reading the official documentation or the specification and building interesting stuff.

8. Only teach topics that you are interested in

This point is slightly related to the previous one. If you want to entertain and interest your audience, you have to show some passion on the topic you are presenting. If you are bored, your talk will be boring and your audience will not follow.

9. Take advantage of the situation to find talent

When teaching a topic to a group of people, you’ll likely encounter three 4 types of persons:

  1. Those who don’t pay too much attention (wrong room may be?)
  2. Those who pay attention but struggle at understanding the content.
  3. Those who understand everything.
  4. Those who understand everything and who want to know even more details about each topic. By their questions, they sometimes force you to think hard and they might as well teach you something new.

This is the ideal situation for you to track down the persons who fit into the last category. Go talk to them after the sessions or during the party, find out who they are, where they work and hire them!

10. Determine success

It is important for you, to determine and measure the success of your interventions. That way you will know what to keep and what to change next time (and yes there will be a next time). In the case of teaching Android to beginners, I defined success by the following metrics:

  1. The number of questions asked during Q/A.
  2. The quality of the questions asked during Q/A. Are they silly questions, like: What is the difference between an Activity and Intent again? Or are they more specific and clever?
  3. Whether the attendees knew how to start building their application during the Hackathon and whether they followed the platform guidelines.

By the way besides all of these points, you should also consider all the good practices that you need to follow to do a great presentation.

Final words: why you should care about doing it well?

Teaching is hard, doing it well is even harder but if you are successful at it, the return on investment will be huge for your company:

  1. Attendees will be happy and will associate their happiness to your products.
  2. These guys will ultimately be your best ambassadors, they will talk about you and your company to their friends and colleagues.
  3. You will attract talented engineers to your team. If you show passion and a certain level of mastery on the topic that you are presenting, it is likely that the talented engineers who attended your talks will develop interest in your company and will try to know more about it and eventually they will want to join you there!
  4. If your presentation was good, it will be shared hundred or even thousands of times. It will go viral!
  5. The Q/A session might bring some interesting discussions from which you can learn new things.

And finally, if you can, take some time to network, socialize and talk to other developers or even non-technical participants. A simple discussion during an event like that can be the origin of your next big idea!

So go out, teach what you know and do it well!

- Amokrane Chentir

posted in: · · ·

Android instrumentation and "FAILED BINDER TRANSACTION"

Enumerating the list of all tests to run

Recently we’ve been focusing on reducing the amount of time it takes to run our Android test suite. As part of this effort we’ve written code to support running our Android tests in parallel across multiple builders in Jenkins.

While this system currently works, something else doesn’t: our tests. Running the tests like this has changed the order of our tests, and uncovered some very unfortunate inter-test dependencies.

In trying to track down exactly which tests make assumptions about the state of the system, I’ve written up a little Jenkins job that uses Android’s am instrument command to enumerate all the tests that would be run, then runs each of them individually. Theoretically, I could also reset the emulator state (using snapshots) between each one, to ensure a completely clean slate, but so far I’m happy with just having the application in-memory state wiped.

The command I originally used to enumerate the tests is this one:

adb shell am instrument -w -e log true -e package com.lookout \
  -e notAnnotation com.lookout.annotations.ExcludeFromDefault \
  com.lookout.tests/android.test.InstrumentationTestRunner

You can read more about the various options to am instrument at the Android Developer reference for InstrumentationTestRunner

The important part of this command is -e log true, which makes InstrumentationTestRunner only print what it would do, and not actually do it.

Hanging instrumentation (FAILED BINDER TRANSACTION)

The problem that I encountered was that am instrument would never return (on an emulator running 2.3.3), and I’d get a bunch of errors in adb logcat like the following:

I/TestRunner(  531): started: testSignalFlareDoesNotRunBecauseDisabled(com.lookout.utils.SignalFlareTests)
E/JavaBinder(  531): !!! FAILED BINDER TRANSACTION !!!
I/TestRunner(  531): finished: testSignalFlareDoesNotRunBecauseDisabled(com.lookout.utils.SignalFlareTests)

Doing some quick Googling revealed nothing useful - people mostly talk about hitting this error when resizing bitmaps, which I’m not doing. As far as I know, none of the code we’ve written is actually executed in this scenario.

It turns out that the something inside the Android test runner is using Binder to pass data for each test, and the sheer volume of these requests is causing JavaBinder to run out of buffer.

So, what’s the solution? Hackishly, but trivially, all it needs to do is limit the frequency of these requests. Luckily, the default InstrumentationTestRunner already implements a feature for doing just that. By passing -e delay_msec X to am instrument, it’ll sleep X milliseconds between each test. Experimentation showed that 5ms seems to be enough, which makes the final command this:

adb shell am instrument -w -e delay_msec 5 -e log true -e package com.lookout \
  -e notAnnotation com.lookout.annotations.ExcludeFromDefault \
  com.lookout.tests/android.test.InstrumentationTestRunner

With this change, am instrument logs all the tests it would run (to adb logcat) and returns successfully!


Hopefully this will help anyone else who comes across this issue, and give you some inspiration to make a really awesome distributed Android test runner! :-)

- Jørgen P. Tjernø

posted in: · · · ·

I18n testing with Cucumber

Earlier this year we announced support for various languages in our products, but we haven’t discussed any of the engineering work that went into the effort.

In order to localize our main Rails application powering mylookout.com we wanted to make sure that we were correctly localizing many of the user flows that we already test with Cucumber and Capybara.

In this post I’ll detail some of the challenges we faced in our localization testing and the solutions we implemented.

1. Stringy Cucumber

It is not entirely uncommon to see Cucumber scenarios which reference very specific strings in the UI, e.g.:

Scenario: Log in to the site with valid credentials
  Given I am a registered user
  And my name is "Jonas"
  When I log in
  Then I should be greeted with "Welcome Jonas!"

The last step would be implemented with the following step definition:

Then /^I should be greeted with "([^"]*)"$/ do |greeting|
  page.should have_content(greeting)
end

This means that this scenario is going to fail 100% of the time if the user’s configured locale is German. Instead of seeing “Welcome Jonas!” the page would render “Wilkommen Jonas!” and the scenario will fail.

There are really two issues at hand here to be addressed:

  1. Hard-coding UI text into Cucumber scenarios

    When text is hard-coded into a scenario in this fashion, it makes the test more brittle not just to localization changes, but also marketing or product teams updating copy in the web application. If anybody updates a strings file and forgets about the Cucumber scenario, tests will all of a sudden start failing.

  2. Asserting page content based on hard-coded text

    It’s generally a good practice to check for specific CSS or XPath selectors instead of text, since the asserting page content based on the text can be slower and more brittle. If it can’t be avoided, let’s say if you’re checking for a specific error message, then there are ways to make the check localizable which is covered below.

2. Localized assertions

There are valid cases where you cannot avoid asserting that a specific message is displayed to the user. Since your Cucumber scenarios are running in the same general environment that your Rails application, you can access the same I18n methods that your controllers and views can access.

Let’s take the scenario above, and update it a bit to make it easier to test with localization:

Scenario: Log in to the site with valid credentials
  Given I am a registered user
  And my name is "Jonas"
  When I log in
  Then I should be greeted

Then we’ll change our step definition to check for a localized string:

Then /^I should be greeted$/ do
  page.should have_content(I18n.t('dashboard.welcome', :name => first_name))
end

Now we’re validating that the page is using the right localized string key ”dashboard.welcome” and passing in our first_name variable. If this user uses a German localization, then we’ll be checking that they have the right welcome message for their locale.

3. Testing around the world

By far the hardest challenge faced was testing the various languages. The first step for us was running all of the scenarios using the different locales as the default.

Notice in the scenario used as an example above, we never explicitly stated the locale that the user would have, we naturally assume “en” is going to be Jonas’ locale, but it’s not specified.

Whenever we create a user, we use the “default locale” of “en” with the ability to override the locale with an environment variable, e.g.

Given /^I am a registered user$/ do
  # Call a remote API to create a randomly generated user
  user = create_user(:type => :free,
                     :locale => ENV['CUCUMBER_LOCALE'] || 'en')

  # Hold onto this user object for future steps
  current_user = user
end

This allows us to run the entire test suite with German users by simply invoking Cucumber with:

% CUCUMBER_LOCALE=de cucumber

Now we’re running scenarios with German localizations, or so we hope, but how can we check to make sure that the page has the correct translations? In some cases we can check specific strings as mentioned above, but it is impractical to do that for every string we render.

Instead, we want to make sure we’re just not missing translations, which required a custom Capybara driver to check the page after actions.

Since some content might be rendered after an onclick action or other on-page event, we’ve hooked the Capybara Selenium driver to run a few checks after certain actions. The hooked Selenium driver itself can be found in this gist, and then configure it properly with:

Capybara.register_driver :selenium do |app|
    # Using a custom http client for performance reasons
    http_client = Selenium::WebDriver::Remote::Http::Default.new
    http_client.timeout = 120

    # Create a new driver object
    HookedSelenium::Driver.new(app, :http_client => http_client)
end

To trigger the driver’s assertions, we use the CHECK_I18N environment variable, making our cucumber invocation look like:

% CUCUMBER_LOCALE=de CHECK_I18N=1 cucumber

During this run of Cucumber, all users will be created with the “de” locale by default, and the tests will raise an exception if we find anything that looks like a missing translation (see line 55 of the gist above).


A combination of the approaches detailed above have allowed us to continue to ensure the scenarios we write in Cucumber are portable across locales, as well as making sure we continue to properly support a plethora of languages in our Rails applications.

- R. Tyler Croy

posted in: · · · ·

Grok code with Puppet

(The following is a cross-post from R. Tyler Croy’s blog)


As the Lookout code-base grows, both in individual repositories but also in the sheer number of repos we maintain, I’ve found it often difficult to find what I’m looking for.

Some of that difficulty is due to ActiveRecord’s determination to implement the world through meta-programming, but for everything else I’m turning to OpenGrok.

OpenGrok itself is a Java-based code cross reference and search engine, which works surprisingly well with Ruby. While not perfect, it certainly blew LXR away in both ease-of-use but also cross-referencing of Ruby, Java, and C code.

Below is an example of searching for the AWS class in my Blimpy project.

Searching for Definitions in OpenGrok

You’ll notice in the search results that there is a green-colored annotation to the right of the code snippet denoting the actual definitions compared to other search results.

When I click on aws.rb and dive into the code itself, I can navigate based on method definitions, but also pull in git-annotate(1) style annotations (not pictured).

Navigating code itself

Since I’m no longer in the business of hand-crafting machines, I went ahead and created puppet-opengrok. This OpenGrok Puppet module, while lacking in rspec-puppet tests (see @glarizza, I’m a hypocrite), will allow you to stand up a simple OpenGrok instance on an Ubuntu Server of your choosing.

Take the following manifest for example:

node default {
  include opengrok

  opengrok::repo {
    "puppet" :
      git_url => 'git://github.com/puppetlabs/puppet.git';
  }
}

The module will handle installing the packages tomcat6, git-core and a few others to make things possible, but after you’ve run Puppet you can navigate to: http://yourhostname.lan:8080/source and you’ll find OpenGrok has indexed the Puppet code base for you!

The module will also install a cronjob which updates the source trees and indexes every 10 minutes.

Currently puppet-opengrok is quite rough around the edges, since I used TDD (Tinker Driven Development) to build it intead of TDD (Test Driven Development). It will most certainly work on Ubuntu 10.04 LTS, but anywhere else your mileage may vary :)

If you’re familliar with Puppet Forge, you can install the rtyler-opengrok module with the puppet-module tool.

posted in: · · ·