Remote Pair-Programming


AgileApprenticeshipDesign processSoftwareTestingThoughts

Seems like Pair Programming is “all the rage” lately in my circles. I haven’t exactly done it before but after hearing about the success and rapid knowledge growth amongst those that pair program…I was almost dying to try it! Especially after i saw David Chelimsky and Corey Haines at WindyCityRails in Sept 2009. I saw them pair and do BDD with Rspec/Cucumber and it was so fascinating, It was like I was watching a ballet as they hopped from RSpec to Cucumber and back and forth. I was like, wow…I wish I was that good! I would have paid good money for a recording of that so I could watch it again and again! I see Corey Haines traveling around pairing with people too. Some people get together and play cards, but Corey gets together to code!

So ok, I like code, I like people, I want to try it! I live a little south of Chicago so its a long commute and it seemed everyone was so busy to pair in person when I asked. I asked on Devchix mailing list for suggestions on how to do pairing online. I had found a few, and the group had some good suggestions. I even had a volunteer to try it with me! This week aimee and I set a few hours aside to try it and see if we could do it!

This article was also sort of “paired” as it was written from my perspective with input and suggestions from aimee!

We asked on Devchix mailing list for suggestions on how to do pairing online. I had found a few, and the group had some good suggestions. I even had a volunteer to try it with me! This week aimee and I set a few hours aside to try it and see if we could do it!

After introductions on Skype we set about getting a shared environment in which to code together. Ideally, we wanted some kind of desktop sharing so we could run tests, console and editor.

We had heard of a few tools and got suggestions from the devchix list:

IChat desktop sharing – we couldn’t get this to work, we did different things and it would appear to connect but then it failed. I tried to mess with settings for Sharing on mac, but nothing doing.

Rio seems to be a library to make collaborative apps, not to use in a pair programming environment.

BeSpin was hard to use.. we couldn’t figure out exactly how to use it. It almost seemed to offer to import the git repository we were working on, but then it said it only supports Subversion and Mercurial, not git.

SubEthaEdit worked but we would have to open each file individually and share each file… unless I was missing something. This would be fine for collaborating on a single file but then we could not share the test runs, terminal commands or view the browser together.

Etherpad – we didn’t end up trying this but I have used it before to debug some code or try out ideas with a friend. They recently got bought by Google, so it would be interesting to see what they do with it. This would suffer the same limitations as SubEthaEdit in that it’s just a text editor.

GoToMeeting (which is $40-50/month) its a little steep for the open source work I want to do. But people say it works really well.

VNC and Unix Screenaimee had used this successfully before but since we weren’t on the same network, just our laptops at home, we weren’t sure it how we could make it work easily.

Then we came to TeamViewer which worked brilliantly! We shared desktop and I could type in aimee’s console window, see the tests running and type in textmate. Even with aimee on her Dvorak keyboard and I on Qwerty! I could type fine but couldn’t copy/paste with keyboard shortcuts so I used the mouse to copy/paste and it worked fine.

All in all, it was an awesome experience and I picked up on a few tidbits of knowledge from aimee on git, and rake! I had some bits of code from another project i was able to quickly copy/paste and get us rolling. We had a few discussions about coding style as we went.

Since aimee was more familiar with the codebase, she mainly wrote the behavioral specs and I wrote the code to satisfy them. We plan to switch around next time, when we pair on a different project that I’ve been developing for a while.

Book Review: "Refactoring in Ruby"


BookDesign processEventsIntroductionsRubyTestingTips and Tricks

“Refactoring in Ruby” written by William C. Wake and Kevin Rutherford.
Published by Addison-Wesley

This is more like a “workbook” then a “how to write awesome code” book. You can download the code from github http://github.com/kevinrutherford/rrwb-code and you will find tests/specs for the exercises.

The book is arranged in three parts, The Art of Refactoring, Code Smells, and Programs to Refactor.

There are explanations of “code smells” which are one characteristic of code that could be improved. Some of them are long parameter lists, unnecessarily complex, global variable, feature envy sections, etc. One thing I find interesting is the “How did it get this way?” section. It gives some insight into the thought process and reasoning behind the smell. I think this is good, as programmers our ego may be rather miffed to hear “This code stinks” but with some reasoning, it makes the pain less and I think firms up in our minds when this happens again, to do it this other way. I always want to know why when someone says I could do such and such thing better.

In addition to the code smell examples there are three programs to refactor in the end of the book. In a conversational tone, it walks through and gives some hints on what needs refactoring. Its almost as if you had a pair programming buddy working with you and identifying in small chunks what can be improved. This is definitely something I want to work through more carefully.

What I find odd, is that not all the code smells have code examples. The inspiration for the book I think is the Martin Fowler book “Refactoring Improving the design of Existing Code” which has examples for every code smell. Maybe Ruby smells less than Java? Or those fixes are really trivial? I don’t know. Overall, this is a great book and is certainly worth the price and investment and you will be a better programmer because of it!

Migrating from Test::Unit to RSpec


RailsRubyTestingThoughts

At Streeteasy, nearly half of our tests are still written in Test::Unit, so it’s hard to see what our actual test coverage is using Rcov.

I read recently that RSpec got support for Test::Unit interoperability. Obviously now is the time to make the switch from Test::Unit to RSpec. You can do it without a mass exodus from Test::Unit. Use your existing tests inside the RSpec test harness.

So here’s how I converted all out legacy tests to rspec.

Step One: update RSpec

This is fairly self-explanatory and written up elsewhere. However, in short, I updated both our rspec and rspec_on_rails plugins, remembering to rerun

$ ruby script/generate rspec

Make a back-up copy of the spec_helper if you’ve customized it. Compare it to the one generated for the new rspec version to see if there’s been any significant changes, and if so, merge them into your helper.

Step Two: move your files from test/ to spec/

This is what I did: I copied test/unit/* to spec/models/, renaming them appropriately:

  ## current_path is a hash where :tu => test::unit path and :s => spec path
  def make_tests_specs(current_path)
    current_path[:tu].each do |file|
      unless file == "." or file == ".."
        full_file = File.join(current_path[:tu].path, file)
        if File.directory? full_file
          spec_file = full_file.gsub(/test/, "spec")
          spec_file.gsub!(/unit/, "models")
          spec_file.gsub!(/functional/, "controllers")
          FileUtils.mkdir_p(spec_file) unless File.exists? spec_file
          make_tests_specs({:tu => Dir.new(full_file), :s => Dir.new(spec_file)})
        else
          new_spec = File.join(current_path[:s].path, file.gsub(/_test/, "_spec"))
          puts "converting TestCase #{full_file} to ExampleGroup #{new_spec}\n"
          File.copy(full_file, new_spec)
        end
      end
    end
  end

Step Three: change your assertions

While that would move all my tests over to the specs directory and rename them, I figured, why should I stop there? I realized I could probably do a lot of the Test::Unit to RSpec syntax conversions programmatically. Here are the regular expressions I used to do the substitutions – while these worked great for our codebase at StreetEasy, your mileage may vary, so be sure to use caution before running this against your code base (and hey, you do use source control, don’t you?):

if line =~ %r@require.*?test_helper@
  new_file.puts "require '#{RAILS_ROOT}/test/test_helper'"
  new_file.puts "require '#{RAILS_ROOT}/spec/spec_helper'"
elsif line =~ %r@class.*?TestCase@ and line !~ %r@Controller@
  new_file.puts "describe 'transitioning from TestCase to ExampleGroup' do"
elsif line =~ %r@class\s*(.*?)Test@
  new_file.puts "describe #{$1}, 'transitioning from TestCase to ExampleGroup' do"
  new_file.puts "integrate_views"
elsif line =~ %r@def setup@
  new_file.puts "before do"
elsif line =~ %r@def test_(.*?)\n@
  new_file.puts "it \"should #{$1.humanize.downcase}\" do"
elsif line =~ %r@assert_response :success@
  new_file.puts "response.should be_success"
elsif line =~ %r@assert_response :redirect@
  new_file.puts "response.should be_redirect"
elsif line =~ %r@assert_redirected_to (.*?)\n@
  new_file.puts "response.should redirect_to(#{$1})"
elsif line =~ %r@assert_equal (.*?),\s(.*?)\n@
  m1 = $1
  m2 = $2
  unless m1.nil? or m2.nil?
    unless m1.match(/nil/) or m2.match(/nil/)
      new_file.puts "#{m1}.should == #{m2}"
    end
  end
elsif line =~ %r@assert assigns\(:(.*?)\)$@
  new_file.puts "assigns[:#{$1}].should be_true"
else
  unless line =~ /^class.*?Controller.*?rescue_action.*?end$/i or line =~ /require '.*?_controller'/i or line =~ /^#/
    new_file.puts line
  end
end

The above block of code will convert any response (:success, :redirect, redirect_to), assigns, and equality assertions. It will change your method declarations to “it ‘should…’ do/end” block syntax. It will require both the test_helper and spec_helper. It will integrate_views by default on your functional (controller) tests; you might want to go through those by hand later and separate out the front-end stuff into a set of view tests, depending on how you feel about them.

You could definitely write more substitutions – there are more assertions in Test::Unit, of course. If your code base makes extensive use of other assertions you’ll probably want to add to the regexes above. In our case, however, I found the above satisfied converting the most straight-forward Test::Unit assertions, leaving me with the slightly more complicated examples to convert by hand, which brings me to the next step.

FYI, you can find a table of Test::Unit assertions and their RSpec equivalents here on the RSpec documentation site.

Step Four: run rake:spec and see what happens

You might as well see what situation any automated conversion process left you in. I had a few errors during this phase – mostly due to the fact that I forgot to move my fixtures, woops – but it didn’t take me very long to resolve them.

Step Five: go through each sparkling new spec and convert any remaining Test::Unit-based assertions into RSpec syntax.

The good news: you can take your time on this step since RSpec now plays nice with Test::Unit. I was in a particularly motivated and productive mood after finding myself with a big directory full of specs (and an amazingly empty test/ directory) so I just went through them all right then and there. It took me most of the afternoon, but when I left work that day I was able to see this, which is just awesome:

$ rake spec
........................................................................................................................................................................................................................................................................................................................................................................................................................................................

Finished in 70.023361 seconds

440 examples, 0 failures

As you can see from the amount of time it took all 440 examples to run, we could definitely benefit from a greater use of mocks and stubs in our controller tests. 70 seconds is a tad bit long. That’s next on the to do list – mock and stub wherever I can in our controller tests, followed by integration/big picture testing using Story Runner, and then, if there’s time*, refactor our specs to be better organized and efficient – I can think of several places where I had wished for nested examples, or could have used shared examples, had I been aware they existed at the time.

I’ll be writing up my experience with Story Runner in the next couple of weeks. Til then, though, best of luck in your specs!

* always a compromise when you’re trying to do things the right way and add business value simultaneously.

For more information Behavior Driven Development, check out Dan North‘s article, “Introducing BDD.”

You can find the documentation for RSpec at http://rspec.info.

Many thanks to Joshua Sierles, Paul Marsh, and Josh Knowles for their time in reviewing this!

RubyEast Recap, Slides, and Other Thoughts


ApprenticeshipPresentationRailsRubyTestingThoughts

I spoke at RubyEast this past Friday and I think the presentation went pretty well. It was my first presentation in a speaker/audience type setting so I was very nervous. I have presented at Agile 2006 but it was a game (interactive) and was co-presented by several other people. This presentation was the first time I stood in front of a room full of people and spoke and everything went very well. Like I said I was really nervous but as soon as I got started the nervousness went away. I think I am very lucky because I was able to present to a room full of very nice/cool people and that made the experience a great one. I want to actually thank the people who came to hear me present and who gave me great feedback and encouragement afterwards it really made my day. If you are interested here are the slides for the presentation. A Tour Of Rails Testing using RSpec

I didn’t get to see many of the sessions because I was busy preparing for my talk but I was able to catch Obie’s presentation – Advanced ActiveRecord which was really good (and I am not just saying that because he is my boyfriend). I also caught the ending Keynote where Nap (I actually don’t know his real name) announced the Rails Rumble winners. There were several screencasts and it made me wish that Obie, Clay, Nick and I would have had time to get the video that was shot of us over the weekend edited and ready for prime time. We had a blast doing the competition and while we didn’t win (we got honorable mention) we learned a lot and I think we all grew closer in those 48 hours. The teams that did win did a tremendous job on their apps and well deserved the loot. Take a look at the winners there really are some great apps. Rails Rumble Winners

Friday evening a bunch of people got together after the conference and played several games of Werewolf which is a really fun game to play. I got to know a lot of people during that game and it was a great way to wind down.

Couple of other thoughts before I end the post. ShesGeeky (un)Conference sounds like it is going to kick major ass so any of you ladies out there who can attend make sure you get registered. Additionally, ladies if you want to talk during the conference please contact the organizers.

GrrrlCamp seems to be getting a good footing. I was lucky enough to meet THE Gloria this past Friday and I look forward to being a part of GrrlCamp.

I have taken on an apprentice and she will soon be posting to the blog about her experiences. I am in the process of trying to see if creating an apprenticeship type program run by DevChix is possible because after speaking with Sonia (one of the women on DevChix) she helped me figure out that I would really like to have a program that fits the apprenticeship model rather than a mentoring program. Look for more to come on this in the future.

Sprites in the Machine: Selenium Remote Control on Windows


SeleniumTesting

The first time I was played with Selenium (the IDE) was a jaw-droppping moment. It was as if little sprites had taken over my computer and were gleefully doing my job. Sitting back and watching a form being filled in, a button selected, links linked — it was an incredible, mafia-man type experience: things were just getting done, and fast. The little guy rushed through my tasks in seconds, cheerfully, leaving green check-marks in his midst, while I sat back and kind of stared, the way you’re supposed to stare at a national monument. These days there are too many hot-dog stands and camera-d tourists at national monuments to merit my awe, but it’s safe to say that my little browser sprite was stepping up to the plate nicely. One could get used to this, I thought. Me, the sprite, and Firefox: what could be wrong in the world?

This didn’t last (amazing how quickly one gets spoiled). The problem with Selenium IDE is that the tests only play back in Firefox. I love Firefox, but the whole gist of my job is that the stuff we do needs to work in all browsers, on all machines (ok, most on most, but you get the idea). At any rate, I went looking for how I could extend the power of Selenium so I could test my web apps cross browser.

There are two approaches: Selenium on Rails (not covered in this article but you can find info here), and Selenium RC (Remote Control). After poking around a bit it seemed that RC was the solution for me. I was testing old apps, not Rails ones, so the Rails solution was overkill — and I had heard a general buzz that RC is a more robust, ‘best-practice’ solution. Whether that’s commonly held wisdom I can’t say (and if anyone wants to do a comparison, I’d love to hear), but it fit my requirements so I dove in.

If you’re not familiar with what Selenium RC lets you do, here: it lets you write tests in most languages (java, perl, python, ruby, php (NOTE: at the time of my testing I could not locate 0.9.1, with php support. It may be available now)) and then run them from the command line. Assuming the selenium server is running (see steps below), a proxy browser is fired up and your script is executed. In short, a browser opens and is interacted with. Each test is run and you’re fed a success or error message. It’s the same process you see when you run tests back using the IDE: your application being lovingly and quickly manhandled by invisible testing men (though based on the current online discussions I should probably make it clear that the gender of the magic sprites is unknown and irrelevant — and that they do not want to have sex with you, even if they are running in heels :) )!

To the docs

The openqa docs are great resources. My one caveat is I would suggest a larger font and a clearer navigation scheme. It’s all there though, and it works, so read carefully, try the examples, and be patient.

From here on out I’m going to transcribe the steps I took to get up and running. This is the order I did things, so hopefully this is helpful as a list of steps and guidelines:

STEPS To set up Selenium RC on Windows

  1. Read the openQA tutorial:
  2. Download selenium RC here: [NOTE: 0.9.1 says it has php but I couldn't find it anywhere. I got 0.9.0]
  3. Extract it using winzip
  4. Put in your c dir (or wherever you keep programs), like so: c:\selenium-remote-control-0.9.0.. I renamed it to selenium, so mine reads c:\selenium. NOTE: make sure you have right java version by typing java –version in your cmd shell. You must have at least 1.5 (1.4???)]. If you don’t, upgrade your java.
  5. Put selenium.rb in your ruby lib dir so it will be accessible to ruby using require ‘selenium’. If you don’t do this you’ll have to run your scripts from w/in the same directory as selenium.rb: you don’t wanna do that. For me I put it in C:\ruby\lib\ruby\1.8\selenium.rb
  6. Start Server. You need to run from cmd line from WITHIN your selenium\server dir [ in my case c:\selenium\server] or feed it the path. [NOTE jar is Java Archive: To run an application packaged as a JAR java -jar app.jar]
java -jar selenium-server.jar --interactive.

At this point you can execute commands on the command line or you can execute a standalone script. There are commands in the tutorial that you can follow along with. To do the latter (execute a program), simply navigate to a test (there’s one in ruby/samples called selenium.rb ) and run it. The one that shipped with my ruby opens google and searches for the string “Hello World”.

C:ruby\\samples>ruby selenium.rb

Once this was done, it was time to start working on a real app. I had an 4 y/o php app in a frameset that I decided to use for testing. Motivation: if I got this stuff working, I would never have to manually slog through all the test cases on that app again. Motivation enough!

Making your tests

You can do this one of two ways: Read the API and manually code your tests in your language of choice (I was using Ruby), or, create your test cases by recording your actions in Selenium IDE (in Firefox) and then save as a .rb script. [File-->export tests as...]. The latter is the much more efficient solution: it’s quicker (do instead of write), and it’s a quicker way to learn the API. Not sure what the method for selecting a frameset is? Just select the frameset in the IDE, export, and the script will come out with that method written right in. It’s @selenium.select_frame “framename” btw.

The way I proceeded was to create (record) an individual test for each action. Because it’s a web app and not a unit test, each test has lots of smaller steps in it that create the overall story of what you are doing. Some of my examples are: create_program, create_test_one_question_no_domains, add_evaluation_to_test, add_test_to_program, etc. The same sorts of things we’d give in a list to QA. You can tell what they are by the titles, which is a common-sense way to keep things clear: descriptive naming is the name of the game. When done, I could run each test from my command line, like so:

ruby create_program.rb

and the browser would open and go through all the steps to, in the case above, create a new program in my application. However, this was repetitive: each individual test used the same setup method and only ran itself. So, I created a master suite called createProgramAndTestSuite.rb. I pasted my individual tests as methods into this class, so that in running the suite I’d be executing all the individual actions (tests) necessary to test this part of the app. Now, one line could run my 16 tests at once:

ruby createProgramAndTestSuite.rb

And, bingo: all my previously individual tests: create_program, create_test_one_question_no_domains, add_evaluation_to_test, etc. were all run in one fell swoop.

The other beauty of consolidation it allows you to take advantage of the setup method. The setup method is run before each test so you can start each individual test where it needs to start — rather than backing up to login or some equivalent “setup” (hence the name) actions. You get most of this for free: tests exported from Selenium IDE come with auto-generated setup and teardown methods that you can leave or modify. Also, note that you can customize your variable names and script conventions in the IDE by going to Options->format and choosing the language you’re working with. Putting all my tests in one suite allowed me to DRY up my repetitive setup actions in one place.

My final setup for the suite looks something like this — I added a bunch of stuff to log me in, select the main frame and gets me ready for each individual action.

def setup
@verification_errors = []
if $selenium
@selenium = $selenium
else
@selenium = Selenium::SeleneseInterpreter.new("localhost", 4444, "*firefox", "http://urlofapp.com/", 10000);
@selenium.start
@selenium.open "http://urlofapp.com/admin/admin.php"
@selenium.type "staff_email", "secret@email.com"
@selenium.type "level_passwd", "magic_password"
@selenium.click("login")
@selenium.select_window "main"
@selenium.wait_for_page_to_load "30000"
# more stuff
end
end

the teardown (again run after each test) is the default from the IDE (I did not change this).

def teardown
@selenium.stop unless $selenium
assert_equal [], @verification_errors
end

And my test methods are pretty straightforward — here’s a few lines just to give you an idea of what it looks like:

def test_create_new_program
@selenium.click "link=Programs"
@selenium.wait_for_page_to_load "30000"
@selenium.click "link=create program"
# more stuff
end

def test_create_test_one_question_no_domains
@selenium.click "link=Questionnaires"
@selenium.wait_for_page_to_load "30000"
@selenium.click "link=create questionnaire"
@selenium.wait_for_page_to_load "30000"
@selenium.click "submit"
@selenium.wait_for_page_to_load "30000"
@selenium.type "test_name", "Selenium: Test
# more stuff
end

Testing is verbose and simple. You write a lot, but, like with most tests, I found I relied on a few basic calls again and again. The typical browser work-horses are going to be select, type, click, wait, etc. I found I had to use wait_for_page_to_load a lot. But there’s an API in the contextual menu if you have the IDE installed (right click when you’re recording tests and you’ll see the showAllAvailableCommands submenu that you can insert into your recording tests). Or, you can check out the Selenium API online.

As a result of executing (and recording) all the actions once in the IDE and doing some copy-pasting and rearranging, in a few days you can have a library of test suites for your application, and voila! your app is not only running itself, but, more importantly, testing itself. You no longer have to run these by hand, you can spot errors more quickly, you can test simultaneously on multiple platforms, and you can easily pinpoint, and fix, failures. It’s a beautiful thing.

Of course, there are lots of complicated browser interactions, especially nowadays, that are not easy (or possible) to test in Selenium. Apps using drag-and-drop, for instance. And if you get into RJS or other types of javascript browser effects that we associate with “web 2.0″, you’ll need to look elsewhere. Actually, if folks know resources or have experiences in this domain, please post to the comments so we can build a resource. But, outside of these cases, Selenium RC is great for running acceptance tests. It’s easy to set up, well integrated, and, most importantly, highly addictive.

Happy testing!