Gless
A wrapper for Watir (specifically watir-webdriver, which is built on top of selenium-webdriver) based on modelling web page and web site structure. It's intended to make it easier to model complex application workflow in an RSpec or Cucumber web site test suite.
This gem attempts to provide a more robust model for web application testing, on top of Watir-WebDriver which already has significant improvements over just Selenium or WebDriver, based on describing pages and then interacting with the descriptions.
Feel free to contact the author at rlpowell@digitalkingdom.org
Overview And Motivation
Gless takes Watir elements and collects them into pages. It then inserts a session layer on top of the pages. The session layer is in charge of knowing what page the browser is on, managing transitions, and checking that they worked. On top of this sits an application layer, which is the code that uses Gless for its testing.
The motivation is seperation of testing types.
At the page level, which is code provided by a user of Gless, the code has very little error correction, and mostly consists of just the elements themselves, but might have some light code tying elements together. For example, a "log me in" method that simply takes a username and password and clicks the login button, and does no error checking at any step, would go here.
At the session level, which is part of Gless itself and if you need more features please send me a pull request, are various functions to do page-level error correction. The big one here is long_wait, which watches a page for changes and only moves on when it sees what it expects.
At the application level, which is code provided by a user of Gless, you can write any multi-page workflows you like, without having to pay any real attention to what page your on in the code, except in as much as if your interactions don't match the site workflow your tests are likely to fail. :) For example, a method to register an account from scratch and log in with it, which presumably involves several site pages, would go here.
An Example
The best way to see how to use this library is to look in the examples/ directory, but here's some stripped down examples.
A partial page definition:
element :home , :link , :href => "https://github.com/" , :validator => true , :click_destination => :LoginPage
element :explore , :link , :href => "https://github.com/explore" , :validator => true , :click_destination => :ExplorePage
element :search , :link , :href => "https://github.com/search" , :validator => true , :click_destination => :SearchPage
element :search_input , :text_field , :class => 'text' , :validator => true
element :search_button , :button , :text => 'Search' , :validator => true
url %r{^:base_url/search}
expected_title %r{^(Code Search · GitHub|Search · \S+ · GitHub)$}
Given that definition, whenever the session code detects that it should be on the search page (i.e. when the "search" element is clicked), all of those elements will be checked for existence, the url will be checked, and the title will be checked.
All of that is entirely automatic; the code that would trigger all that would just be
@session.search.click
An example of page code that might use such a page definition:
def search_for stuff
self.search_input.set stuff
self.search_button.click
end
An example of applicaiton level code that might use that page level code (plus some other stuff not shown here):
def search_and_go name
@session.search.click
@session.search_for name
@session.goto_repository name
end
As you can see, the application level can encode extremely complicated actions, in this case "go to the search page, search for a repository, and go to that repository page", in a compact way that has a sensible abstraction pattern.
Writing Code Around Gless
Configuration File
Gless expects you to have a configuration file named lib/config/development.yml (the word "development" there can be altered by changing the ENVIRONMENT environment variable) under your test application. See examples/ for a detailed example.
The parts that Gless uses directly, and hence are required:
:global: # This tag distinguishes the global config from the per-test configs; *do not remove*
:debug: false
:thumbnails: false # Whether to create small-ish "thumbnail" pictures on the replay page; requires the imagemagick system package and the mini_magick gem
:browser:
:type: local # Local or remote
:browser: firefox # Which browser to use
:port: 4444 # If remote, port to connect to the selenimu server, otherwise ignored
The Pages
All of your site page description classes must be descendants of Gless::BasePage.
It is often useful to have your own base page class as well for headers and footers and so on. See examples/ for a complete example as usual, but here's a partial one:
rpowell@ut00-s00000> cat examples/test_github/lib/pages/test_github_base_page.rb
module TestGithub
class TestGithub::BasePage < Gless::BasePage
element :home , :link , :href => "https://github.com/" , :validator => true , :click_destination => :LoginPage
element :explore , :link , :href => "https://github.com/explore" , :validator => true , :click_destination => :ExplorePage
element :search , :link , :href => "https://github.com/search" , :validator => true , :click_destination => :SearchPage
element :features , :link , :href => "https://github.com/features" , :validator => true , :click_destination => :FeaturesPage
element :blog , :link , :href => "https://github.com/blog" , :validator => true , :click_destination => :BlogPage
end
class BlogPage < TestGithub::BasePage
url %r{^:base_url/blog$}
expected_title 'The Official GitHub Blog · GitHub'
# Stub page, but BasePage stuff still works
end
end
The Application
Your application layer that sits on top of Gless must itself have certain features, as other aspects of Gless do call back into the application layer and/or make use of it. Here's some minimal boilerplate that you should start with:
module TestGithub
class TestGithub::Application
include RSpec::Matchers
attr_accessor :browser
attr_accessor :session
attr_accessor :site
attr_accessor :base_url
def initialize( browser, config, logger )
@logger = logger
@browser = browser
@config = config
@session = Gless::Session.new( @browser, @config, @logger, self )
@session.should be_truthy
end
end
Debugging Gless Applications/Tests
If your configuration file has ":debug: true", then Gless will produce some pretty verbose logging of what it's doing.
A less crazy version is ":verbose: true".
If replay is true in the config file, it will also create a replay log directory which is intended to be viewed in a browser. The directory location defaults to ~/public_html/watir_replay/test/ ; the initialization of Gless::Logger determines that location. Most actions that Gless performs will cause the replay log to be updated a copy of the HTML source as Gless/Watir/Selenium/WebDriver sees it.
If you have ":screenshots: true" (along with debugging), screenshots will also be taken showing the visual state of the browser at the time. This is quite slow, especially if the page is large. In addition, if you have imagemagick installed, and the mini_magick gem, and ":thumbnails: true", then smaller pictures will be included on the main replay index page, rather than the full-sized ones.
Requirements
Ruby 1.9.3 is used for development of this project.
Gless expects that you're running tests under RSpec or Cucumber;
significant modification would likely be required to make it run
otherwise, as it uses RSpec's should
extensively.
The following should be sufficient to allow all the rake tasks to run:
gem install yard-tomdoc redcarpet watir-webdriver rspec
In addition, you'll need the mini_magick gem and the imagemagick OS package if you want thumbnails in the logging output.
Tests
Gless doesn't have any; if you can tell me how I should test something like this besides "just run the sample app", please feel free to suggest.
Documentation
Other than this readme, the internal API documentation is in YARD markup. Various things you can do:
rake doc
- generate the documentation
-
yard list
andyard ri
- command line access to the documentation
yard server
- pretty web interface to the documentation
Note To Self
To release a new version:
rake build
gem push [file]