I opted to use Cucumber with Ruby, interfacing to the browser under test using Selenium. There are good alternatives like Mocha, or Cucumber-js. My choice was based on what I knew and was comfortable with.
The output of the Cucumber tests are here. Warning - or perhaps not a warning. The tests contain the solution of the puzzles in the game.
Installed XCode and then the command-line tools (which you do from inside Xcode / Preferences / Downloads).
Installed Ruby Version Manager rvm.
Using rvm installed Ruby 1.9.2 using the command rvm install 1.9.2. Set 1.9.2 as the default Ruby by command rvm default 1.9.2.
Installed the Cucumber gem by the command gem install cucumber.
Installed the rspec gem by the command gem install rspec.
Installed the Selenium gem by the command gem install selenium-webdriver.
Here is the start of the feature file as it stood at the time of writing:
Feature: Walkthroughs To prove the game works check that solutions work for each difficulty level Background: Given menu page is displayed in browser Scenario: No puzzles at all When I click on texts "New game" "Calm" "Decks" "122" "122" Then I see text "The journey of a thousand miles"
So in the scenario what we want to happen is the browser be started, the menu page for the game displayed, then clicks be simulated on a number of text strings, then we verify we see an expected text.
There is an art to writing good feature steps. A challenge here is not to end up with scenarios which are hundreds of lines long. Compromises have to be made.
So the feature steps have to be wired up using step definitions. For the step:
Given menu page is displayed in browser
The step definition is:
Given /^menu page is displayed in browser$/ do open_menu sleep 5 end
Where open_menu is a method added to the World.
For the step:
Then I see text "The journey of a thousand miles"
The step definition is:
Then /^I see text "(.*)"$/ do |text| find_text( text).should_not be_nil end
Having got our step definitions we then need to wire those up to the browser using Selenium. So the method open_menu is implemented as:
def open_menu @@driver = Selenium::WebDriver.for :firefox @@driver.navigate.to "file://localhost" + ENV["MENU"] mask = @@driver.find_element( :id, 'mask') @@x_offset = mask.location.x @@y_offset = mask.location.y end
where we pass the file location of the game's index.html page as an environment variable.
We need the x_offset and y_offset data to work out locations relative to the container holding the game elements.