Monday, March 30, 2009

Programming through vagueness

It may sound counterintuitive, but one of the tidbits I’ve gotten from Russ Olsen’s Design Patterns in Ruby is the idea of writing classes and methods in as general a form as possible.  He discusses an example of different types of vehicles and writes:

By writing code that uses the most general type possible—for example, by treating all of our planes and trains and cars like vehicles whenever we can—we reduce the total amount of coupling in our code. Instead of having 42 classes that are all tied to cars and boats and airplanes, perhaps we end up with 40 classes that know only about vehicles. Chances are that the remaining two classes will still give us trouble if we have to add another kind of vehicle, but at least we have limited the damage.

In fact, if we have to change only a couple of classes, we have succeeded in separating out the parts that need to change (the two classes) from the parts that stay the same (the other 40 classes). The cumulative effect of turning down the coupling volume is that our code tends to be less likely to shatter in a horrendous chain reaction in the face of change.

This has tremendous value for testing.  Instead of writing methods like:

load_preferences_page()
load_users_page()
load_security_page()

we can create a single, general method and simply pass it parameters thus:

load_page(preferences)
load_page(users)
load_page(security)

This way, if the method needs to be changed, you only have to change one method, making the code easier to maintain and much less error-prone.

Pretty elementary for you object-oriented veterans…but cool stuff nonetheless!

Tuesday, March 24, 2009

Running “cleanup” the beginning of a test

Often a test will execute a “cleanup” method to delete items (often out of a database) that were created or used in the test, to make sure the next test has a clean environment to run in.  Sometimes though, the cleanup never gets run – if it is the last thing to run (as would seem logical), if there is a test failure it will never execute.

A better option is to run the cleanup method at the beginning of a test.  If the method simply executes SQL scripts to delete records, if the records for some reason aren’t found, it won’t generate any kind of error, so the script will run normally.  However, doing it this way (putting the cleanup at the beginning) insures the data cleanup will get executed on every test, insuring a clean environment for every test that gets run.

Wednesday, March 18, 2009

MountainWest RubyConf 2009 videos starting to appear…

Get them here

Some quick hits from MountainWest RubyConf 2009

I’ll write more on this later, but just wanted to drop a quick note on MountainWest RubyConf 2009, which I went to last weekend in Salt Lake City.  I really loved the conference, and hope it continues to grow.  I like that they don’t pack the conference with alot of expensive frills, and just basically focus on providing content.  Here’s my quick takeaways:

  • Wow…lots of Macs.  I feel like an endangered species here with my Windows laptop.
  • James Edward Gray II:  we should be reading more code than we write.  No one would think much of a writer who didn’t read much.
  • Sequel looks really cool.  Jeremy Evans, who is the creator, gave this presentation.  I have been just using DBI and sending SQL queries “natively”, but I really like the way Sequel Rubifies database access.
  • Jeremy McAnally was hilarious – and I learned some things too, but need to re-look at my notes to remember what those things were.
  • Ben Mabey gave an interesting talk on Cucumber…I’m still a little fuzzy on how it differs from RSpec, or what domain it occupies vs. RSpec…but I’ll definitely look into it further.  The RSpec book covers Cucumber as well, so I’m sure I’ll delve deeper.  Besides, any framework named after vegetation can’t be all bad.
  • Philippe Hanrigou spoke about learning lessons from Smalltalk…in a greater sense, he spoke of learning from the masters, which I think is a cool topic.  I think we can learn from everyone who comes before us, and learning about DaVinci can make us better Ruby coders.  Weird, huh.

All in all, a great experience.  Some of it went over my head, and some was Rails-specific.  But much of the conference was really useful, and I look forward to going back next year.  Maybe I’ll see you there.

Monday, March 9, 2009

Why Ruby is great as a “sticky” test framework

One great advantage of developing a test framework in a scripting language like Ruby is that it allows you to glue together different types of tests in a single framework. 

Here’s a perfect example.

I had to write a test checking all the log files in a directory structure for a text string (in this case, a password).  In other words, I wanted to make sure the password wasn’t stored in plain text anywhere in the log files.  I found that Powershell has some awesome tools for doing this type of search on a Windows machine.  So, I wrote a Powershell script to search the directory, and if a match is found, it creates a “fail.txt” file:

if (test-path fail.txt)
{
    del fail.txt
}

$adminSearch = dir -rec -filter *.log 'c:\windows\temp' |
select-string "PASSWORD=thisisthepassword"
if (!$adminSearch)
{
    Write-Output("pass")
}
else
{
    Write-Output("fail")
    Write-Output([string]$adminSearch.count + " instances of passwords in log files: ") |
        out-file -encoding ASCII -filepath fail.txt
    Write-Output($adminSearch) | out-file -append -noclobber -encoding ASCII -filepath fail.txt
}

This done, I then write a Ruby/RSpec script that simply checks for the existence of the fail.txt file:

require 'spec'

describe "Information Disclosure Prevention" do

  it "Should not show passwords in plain text" do
    system("powershell.exe -File ./lib/passwordsearch.ps1 -command \"& {set-executionpolicy unrestricted}\"")
    result = FileTest.exists?("fail.txt")
    result.should == false
  end
end

And that’s it.  As you can see, it’s easy to wrap RSpec examples inside any command/script that can be run from the command line.

Wednesday, March 4, 2009

Getting elements – Firebug to the rescue

In using Watir, probably one of the biggest challenges is accessing elements that are buried inside several layers of Ajax/HTML.  You can run the show_all_objects() method, but that doesn’t always show everything on the page, and it can be difficult to parse through manually.  So what’s a test developer to do?

Firebug to the rescue.

Firebug is a Firefox plugin that provides several useful tools, but one is that it has a great DOM inspector that allows you to easily copy any HTML element on a page by simply clicking the “Inspect” button and clicking on the element to be inspected.  It then allows you to easily copy the element text to the clipboard.

I will often use Firebug and watir-console together when building a test method.  There are times when I’m not sure of the best way to access an element, but with watir-console and Firebug running, I can experiment and fiddle with different code blocks, and find out what will work best.

Check it out here.

Here’s a screenshot:

firebug

Monday, March 2, 2009

Playing with Celerity

I’ve started playing with a cool port of Watir to JRuby…it’s called Celerity.

Here’s the website. 

This is how it is described on the website:

Features

  • Fast - No time-consuming GUI rendering or unessential downloads
  • Easy to use - Simple API
  • JavaScript support
  • Scalable - Java threads lets you run tests in parallel
  • Portable - Cross-platform thanks to the JVM
  • Unintrusive - No browser window interrupting your workflow (runs in background)

 

One issue I’ve had with Celerity (and JRuby in general) is that Watir supports SSL out-of-the-box, whereas with Celerity (or JRuby), when I try to access an SSL address, I get a Java exception that the certificate can’t be found.  I’m sure there is a workaround, but haven’t worked on it yet. 

Other than that, I’ve played with it on a non-SSL website, and it seems to work exactly like Watir, only much faster and with no browser showing up.  Pretty cool.