RUTL
This is the Ruby Ui Test Library, or RUTL. Not to be confused with The Rutles.
Framework goals:
- Define what's on a page in an easy, flexible way. Easy page objects!
- Abstract away things that make tests buggy and painful to maintain.
- Write test cases for native apps, the web, and desktop apps the same way.
- Make screenshotting and diffing screenshots sane and easy.
- TODO: I'm sure I'm missing some at the moment.
- Secondary-ish goal: Make fake browser to test the framework faster.
- Tertiary-ish: Stop calling browser "fake" because I'm sick of that word. Null!
Installation
Add this line to your application's Gemfile:
$ gem 'rutl'
And then execute:
$ bundle
Or install it yourself as:
$ gem install rutl
Usage
Page Objects
Page objects are a common paradigm in browser testing. This framework uses the following convention for page classes:
- must inherit from Rutl::BasePage (require rutl/base_page)
- by default, the class should follow the naming convention ending with "Page" (optional?)
- must have @url defined per page
- must have a layout method such that
- field types are defined by methods button, checkbox, link, and text (more tbd?)
- field type is followed by name as a symbol (add support for string? tbd)
- then a comma
- hash of selectors
- key is selector type as symbol (currently only :css)
- value is string path
- optional comma if there are destinations or error conditions
- optional array of destination page or error condition classes if clicking the element causes transition
- loaded? method returning boolean to determine when page is loaded
- defaults to just checking url; overide as needed
- go_to_here (better name?) method to navigate to the page if we can't just go to the url
- your own methods because it's a plain ol' Ruby class
Example:
require 'rutl/base_page'
class MyPage < BasePage
@url = 'https://url.string.com/page.html'
def layout
text :username, { css: 'some_css_input#username' }
text :password, { css: 'css#to_password_field' }
:log_me_in, { css: 'button#login' }, [SomeOtherPage, LoginFailurePage]
link :refresh, { css: 'link_css_to_refresh_page' }, [MyPage]
end
end
And here's some example RSpec:
require 'spec_helper'
RSpec.describe MyTest do
let!(:browser) do
Browser.new(type: :firefox)
end
it 'logs in' do
goto(MyPage)
username_text = 'drew'
password_text = 's3cr3T!'
.click
expect(current_page).to be_page(SomeOtherPage)
end
end
The framework loads and manages all the pages. You just have to interact with what you can see on whatever page you're on. Let's walk through this.
- TBD: Does RUTL come with browser drivers? Browsers? What needs to be added?
- We're using let! because:
- it forces instantiation of "browser" every time
- we include DefaultRspecToBrowser, defaulting missing methods to "browser"
- thus the terse lines that follow
- We didn't pass named param rutl_pages: to Browser so we must have done one of:
- setting environment variable RUTL_PAGES
- setting RUTL::PAGES
- Browser's type: parameter currently supports :chrome, :firefox, and :null.
- The first call to the browser is goto because it wasn't on a page.
- Auto-created fields are named "#friendly_name_#field_type".
- Getting and setting text fields is as easy as calling a String.
- When we call click, the framework polls for a next state.
- We verify that the current page is an instance of the intended page.
- Also note here that we have a matcher be_page which matches a page class.
RSpec Goodies
The tests here are in RSpec and use some conventions that may be common if your tests are also RSpec.
DefaultRspecToBrowser
This is a module that allows us to skip writing browser. in front of everything.
- We assume that
browseris defined. - On method_missing, we try to send the method to
browser.
It lets us turn this:
browser.field1_text = 'foo'
browser..click
expect(browser.current_page).to eq(NextPage)
into this:
field1_text = 'foo'
.click
expect(current_page).to eq(NextPage)
which means less boilerplate and it's easier to follow.
To use it:
require 'rutl/rspec/default_rspec_to_browser'
RSpec Matcher
Currently the only has the be_page matcher.
It lets us turn this:
expect(browser.current_page).to be_instance_of(MyPage)
into this:
expect(browser.current_page).to be_page(MyPage)
Both are acceptable but the second is more readable.
To use it:
require 'rutl/rspec/rutl_matchers'
Roadmap
Coming up soon in almost no order:
- A test framework should have better tests.
- Put more info in this readme.
- Take screenshots.
- Diff screenshots. Make this smart so we don't have to be experts.
- Move bugs and would-be features to Github Issues instead of this readme and scattered through the code.
- Make the framework make it easier to spot bugs in pages. Focus on exception-handling?
- The webdriver gem should already include InternetExplorerDriver. Maybe run tests on AppVeyor.
- Other browser drivers? Look at https://github.com/fnando/browser
- Get this working with Appium:
- Make TK app to test on desktops and test it.
- Can Ruby TK create accesible apps? Not in the simple demos.
- Make Android example app and get this to work.
- Corboba?
- Same with iPhone.
- Same Cordoba test app?
- Documentation. RDoc?
- Others?
- Spidering page object maker. Or selector checker/fixer?
- Possibly pair the null browser with auto-generated pages for ______?
- Optional install of test resources based on machine type.
- Instructions about machine installs to help people using gem.
- Pair with some kind of VM, Docker container, AMI, or something.
Development
Set everything up:
1. Check out the repo.
2. `cd` to the repo.
3. `bundle install`
4. `bundle exec rake`
Great! You've checked out the code, installed everything and run the tests.
Rubocop. I still have to tweak what I want it to complain about.
bundle exec rubocop
To install this gem onto your local machine, run bundle exec rake install. To release a new version, update the version number in version.rb, and then run bundle exec rake release, which will create a git tag for the version, push git commits and tags, and push the .gem file to rubygems.org.
Contributing
Bug reports and pull requests are welcome on GitHub at https://github.com/drewcoo/rutl.
License
The gem is available as open source under the terms of the MIT License.