After spending some time this week getting to know Ruby and some of its testing frameworks (Shoulda, rspec, and TestCase), I thought I'd put pen to paper and revisit why I started down this path.
Some background
The current project I am working on is a large data-driven WPF application, with a lot of complex scenarios to identify, develop and test. There is a group of testers on the project, but I can see an opportunity to use automated testing to verify functionality and allow testers to focus on areas of better value - exploratory testing, for example.
Yes, there are frameworks like White or Coded UI Tests, but these tools were designed with developers in mind. You have to write code like this to drive the tests, and the tests are commonly written after the feature is implemented.
Enter Automated Acceptance Testing
In an ideal world, business users would define tests in an English-like language, which can then be translated into an executable script and run against the application.
What I'm looking for in a framework for defining use cases:
Some inspiration from obscure corners
When I first saw the syntax for webrat, I was intrigued and jealous. To declare a test like this:
class SignupTest < ActionController::IntegrationTest
def test_trial_account_sign_up
visit home_path
click_link "Sign up"
fill_in "Email", :with => "good@example.com"
select "Free account"
click_button "Register"
end
end
was not far off what I'd had in mind for something that was easy to follow and easy to write.
So I spent some time this week experimenting with various ways of achieving this against a sample WPF application.
I'm using rspec at the moment to run the test cases, and IronRuby and White to support the integration with the hosted WPF application.
What does a test for the WPF application look like?
describe "new customers screen" do
subject { Host.new(File.expand_path('./app/WpfTestApp.exe', File.dirname(__FILE__)))
before(:each) do
click "Add Customer"
end
it "cannot save empty form" do
cannot_click "Save"
can_click "Cancel"
end
it "can enter details for customer" do
fill "FirstName", :with => "Brendan"
fill "LastName", :with => "Forster"
# and some other fields
can_click "Save"
end
it "can save and return to main screen" do
fill "FirstName", :with => "Brendan"
fill "LastName", :with => "Forster"
# and some other fields
click "Save"
assert_title "Dashboard"
end
after(:each) do
cleanup
end
def method_missing(sym, *args, &block)
subject.send sym, *args, &block
end
end
The fields used here are based off the UI Automation features of the .NET Framework (some reading here on recommendations) which I'll dig into a bit later if people are interested.
The method_missing method is used to reduce the noise of writing "subject." to start each line - I'm not quite sold on the approach, but it was cleaner than the previous approaches I'd tried. Also, rspec has a huge set of features which I've barely scratched the surface on.
So with a set of files like the file above, the testrunner is a simple script to load specific files found in the current directory:
require 'rubygems'
require 'rspec'
require 'host'
Dir[File.dirname(__FILE__) + '/*tests.rb'].each do |file|
load file
end
I'll share some more as I polish additional features (I'm most certainly doing Ruby wrong at the moment, so I keep refactoring code), just needed to write this post.