Back to the joys of coverage testing: Vagrant, Guard, Spork, RSpec, Simplecov

Tests are important because programmers are human.  I know that I’m going to forget, make mistakes, and change things that I didn’t mean to change. Testing lets me improve my chances of at least noticing. Coverage tools show me how much of my code is covered by tests, improving my chances of seeing where my blind spots are.

In one of my last projects at IBM, I convinced my team to use coverage testing tools on a Rails development project. It was great watching the coverage numbers inch up, and we actually reached 100% (at least in terms of what rcov was looking at). I occasionally had to fix things when people broke the build, but sometimes people added and updated tests too. Although coverage testing has its weaknesses (are you testing for edge cases?), it’s better than nothing, and can catch some embarrassing bugs before they make it to the outside world.

Although I’m not currently taking on any web development work (I’m saving brainspace for other things), I have a few personal projects that I enjoy working on. For example, QuantifiedAwesome.com lets me track different measurements such as time. I had written some tests for it before, but since then, I’d been adding features and making changes without updating the tests. Like the way that unpaid credit card balances turn into financial debt (very bad habit, try to avoid this if possible), unwritten or out-of-date tests contribute to technical debt.

It was a little daunting to sit down and slowly work my way through the knots of out-of-date tests that had accumulated from haphazard coding. Here’s how I made the task more manageable:

  • I set up a virtual Linux development environment using Vagrant and Puppet. Many tools are much easier to set up on Linux than they are on Windows, and using a virtual machine for development means that I can easily isolate changes from the rest of my system. Vagrant allows you to specify the configuration of a VirtualBox machine and quickly set up a new instance of it. I copied the Puppet configuration from rails-dev-box and modified it to match my requirements. I also compiled and installed Emacs 24 from source, along with a few Ruby-related tools like haml-mode and rinari. (If you’re going to do a lot of development, you might as well do it with your favourite tools!) I copied the Vagrant private keys and imported them into Pageant (an ssh agent for Windows) for easy logins, and I forwarded the ports too.
  • I used Guard and Spork to efficiently run subsets of my tests. Guard is a tool that re-runs specific tests when it detects that files have changed, while Spork lets you run tests without reloading your entire Rails application. Instead of running rake spec (which runs the whole test suite) or rspec ./spec/path/to/file (and  having to copy and paste the failing test’s filename), I could let Guard take care of rerunning failed tests for me.
  • I worked on getting the old tests to pass. I wanted to get those cleared up before writing new tests. Good thing too – found a few bugs and some old code along the way.
  • I reviewed the recommendations for better tests. Better Specs has tips on using RSpec with Ruby.
  • Then I wrote new tests to cover the rest of my models. I used Simplecov for coverage testing. Since Vagrant uses shared folders, I could use Google Chrome to view the coverage webpages from my host computer. I still have some technical debt left – I need to write integration tests, and there’s more beyond that – but it’s satisfying to know that the models (data + logic) are covered. For some reason, my Guard+Spork combination doesn’t result in cumulative Simplecov scores, so I occasionally regenerate my coverage stats with rake spec. These tests will be useful as I write new features or move to Rails 4.

image

(… 21.5 hours of coding/development/infrastructure…)

New things I learned:

I use Mechanize to work with the Toronto Public Library’s webpage system so that I can retrieve the list of due books, renew items, or request holds. I wanted to test these as well. FakeWeb lets you intercept web requests and return your own responses, so I saved sample web pages to my spec/fixtures/files directory and used FakeWeb to return them. (ex: toronto_library_spec.rb)

Paperclip also needed some tweaking. I replaced my Paperclip uploads with File assignments so that I could test the image processing. (ex: clothing_spec.rb)

Always remember to wrap your RSpec tests in an it “…” instead of just context “when …” or describe “…”. I forgot to do this a few times and got confused about why stuff got left in my database and why the error messages weren’t formatted like they normally are.

Progress! Next step: Update my Cucumber tests and add some more integration tests…

I like this part of being a developer, even though writing new code is more fun. Testing is one of those time-consuming but powerful tools that can reduce frustration in the long run. I’ve experimented with applying automated testing techniques to everyday life before. I wonder what it would be like to take that even further… Any thoughts?

Things I learned from the GenArtHackParty

I spent Friday evening and all of Saturday at the Generative Art Hack Party that Xavier Snelgrove organized. It was a good excuse to learn paper.js and d3js.

Here’s what I made:

  • Bouncing spline: Reminds me of that old screensaver, with a little bit of randomness thrown in.
  • Flowers: Playing around with opacity
  • Faces: Simple shapes for awesomeness
  • Kapow: I read too many comic books.
  • Pasketti: Because drawing curves like this made me think about spaghetti, but not quite.

I thought Partycles was cool. infinitedaisyworld was nicely done, too. =) Check out the rest of the submissions.

In addition to learning more about HTML5 canvas drawing with Javascript, I learned that:

If I start thinking of things as “art”, I can get stuck waiting for an interesting idea, especially if I’m in that mid-afternoon slump. If I don’t worry about coming up with a vision first and instead read the documentation or play around with functions, I can let curiosity take me to interesting places.

A room full of 20-30 geeks coding away isn’t distracting, although I still haven’t figured out how to interrupt people and ask about stuff.

Add another ~20 people and switch into party mode, and I begin to shut down socially. I don’t particularly feel like engaging in conversation, and I don’t feel like I’m completely there in conversations. It might be a decibel thing, it might be a listening thing. I wish I’d thought of sneaking downstairs for quieter conversations instead.

Xavier Snelgrove, Jen Dodd, and TinEye know how to have a great event with awesome healthy food.

After lots of social interaction, I tend to get wiped out. I slept for twelve hours the following day.

An evening and a full Saturday feels like it was enough to disrupt our home routines, which is not good news in terms of my participation in hackathons. I think I need to be more social in order to make the most of hackathons, anyway.

So, how do I want to follow up on this?

I’d like to add that d3js calendar visualization to QuantifiedAwesome.com. I think it would be interesting to see heatmaps of activities.

HackLab will probably be a good way to practise being around other people when I’m coding, and the open houses on Tuesday would be good desensitization for mingling.

I’d love to learn more about Quantified Self and visualization.

Sometimes, if I start thinking of things as “possibilities,” I get stuck waiting for an interesting idea. What if I set aside one morning each week to do this kind of planning / brainstorming / looking ahead, knowing that the rest of the week can be focused on actually trying things out and making things happen, even if they’re not Super Brilliant things? If I brainstorm a list of things I can explore, then I can keep moving forward even if the creative part of my brain wants to procrastinate. I trust that if I keep exploring, curiosity will lead me to interesting places.

Good experience. Would do it again, especially if I can figure out how to hack the social parts.

Web app idea: Stamp mix calculator

2013-01-03 11.05.45

I’ve resolved to send more paper letters. I also have an odd mix of stamps that I want to use up: some with Canada Post’s permanent postage, and various denominations throughout the years. There are different rates for domestic, US, and international letter mail. Naturally, I want to optimize my stamp use so that I use the minimum number of stamps and avoid exceeding the required stamp rate.

Some examples for the $1.80 international rate:

  • 2 x $0.89 + 1 x $0.02
  • 2 x permanent postage (currently valued at $0.61 each) + 3 x $0.02 + 1 x $0.52

And lo, someone has actually built a stamp optimizer. Also, only one in Google Search? What do people call these things?

Next question: Has someone built a stamp optimizer that lets you keep track of your stamp inventory, maybe through bookmarkable parameters? It would be neat to be able to not have to enter in your particular mix of stamps each time. That might be overengineering this, though.

Who knows, I may sit down one day and code this just for fun. It totally fits the profile of the programming competitions we used to do in high school and university.

Test-driven development and happiness

Me: Happiness is a test suite that passes.
@philiph: Do you practice test-driven development for your happiness?
Me: Why, yes, actually, I do. It gives me a tangible sense of accomplishment and minimizes my mouse-clicking. =)

Developers find their own balance of how much project structure works with them. Some people like seat-of-their-pants coding. Others want detailed architecture diagrams. Me, I’m getting the hang of agile development practices, and I really enjoy using them.

Test-driven development, for example. Yes, I could just plunge ahead and write Drupal code, and I could test it by clicking on buttons and typing into forms. I don’t particularly like using the mouse or doing repetitive actions, so I write tests for functionality and occasionally for web interaction. Tests also mean that  I can check small pieces of functionality before I have to build a web interface. And when something breaks – not if, but when – tests help me narrow down the error.

It’s so satisfying to see the tests pass, too.

There are tests that exercise functionality, and tests that set up test data just the way we like it so that we can demonstrate features or try things out using the web interface. One of my team members showed me a wonderful technique for repeatable, well-structured test data by using a spreadsheet to generate PHP code. I’ve been extending the pattern for other things.

Drupal + Simpletest is awesome. It can’t handle everything, but it makes my Drupal life better. Happy developers write happy code!

Think! Friday

One of the things I like about IBM is the Think! Friday initiative,
which encourages people to use their Friday afternoons to learn about
something new.

My job is to think all the time—ah, the life of a grad student!—and
Think!Friday gives me that additional impetus to go out there and do
something.

A few Think!Fridays ago was Hack Day, an ad-hoc 5-hour hackathon
across IBM. I built a social discovery web application that took a
list of e-mail addresses, names, Lotus Notes mail IDs and even
community IDs. Given a list of people, the tool displayed the latest
three blog headlines and bookmarks for people who used the internal
blogging and bookmarking services. I’d been meaning to build it for a
few weeks, and thanks to the enthusiastic Hack Day vibe, I finally
made the time to hack it all together.

Fast forward to today. IBMers voted on their favorite Hack Day hacks.
Mine won Best Mashup! That made me ridiculously happy. It was a simple
hack—most of the time was spent writing libraries to interact with
IBM’s services and figuring out how to resolve different kinds of
names—but it turned out to be quite useful for finding people.
Throwing it all together in Ruby was a lot of fun, too. Ruby makes my
brain happy.

Hack Day was a terrific way for me to meet a lot of other early
adopters and geeks within IBM. We presented our hacks in two
teleconferences, and that was awesome.

Today, I decided to deal with some of the other little projects I’d
been meaning to do. I set up RSS2Email (Python) and made it easier for
people to have comments on their blog e-mailed to them. Again, a
simple hack (took me a leisurely hour or so)—but I think it will have
a lot of benefit. I also wrote a little Ruby script that summarized my
bookmarks in bloggable form. Happy!

I like days like this a lot. I like sensing the need for a little tool
and writing that tool. I like being in the zone, trying things out,
geeking out, creating something useful…

Happy girl. =)

On Technorati: , , , , , ,

Random Japanese sentence: この鼠は私の猫に殺されました。 This mouse was killed by my cat.

ACM

I went to Ateneo early this morning, fully intending to just say hi and then go back home to revamp the network. Doc Mana somehow managed to talk me into joining the students for the morning contest, and I’m very glad I did so.

Yes, Eric and I lost. We solved only three problems compared to the four problems Allan, Mark and Miguel solved. Knowing how rusty I am, knowing how uncertain the dynamics were, it was a no-win kind of thing—but I went and joined it anyway, just for kicks.

I think it turned out really well.

I think we all won.

Winning isn’t just a matter of points. It’s not a matter of beating someone or keeping your reputation intact or whatever. It’s nothing like that at all.

So, yes, the next generation beat me. Yes, they had one additional person, but that doesn’t make their achievement any less cool. Heck, if you’re going to go for absolute ranking, Eric solved more problems than I did. I solved one on my own and made a passable attempt at another; he solved two problems completely.

Someone just looking at the numbers will not understand why I enjoyed that contest so much. I loved it, every single moment of it: from scribbling tentative solutions and working through them with a pen, frowning at stubborn bugs… Yes, even until the last few minutes when I was, like, gaaaaaaaaaaaaaaaaaaaaaaaaah.

It was fun.