jueves, 26 de marzo de 2009

Installing Rails Full-stack testing environment: Cucumber + Selenium

Hey people!,

I've just had to configure an environment for running both plain Cucumber features and enhanced features (the ones that relies on Javascript) with the help of Selenium, so I decide to centralized the information I found in order to install the full-testing stack.

Environment

First of all, I'll be working on Rails 2.3 environment. And I'll assume that you got Rails/Rspec already installed since I had covered that in a previous entry. Also it would help to check http://wiki.github.com/dchelimsky/rspec/configgem-for-rails to fix issues related to Rails > = 2.2 and Rspec.

Install cucumber is really easy, you just got to follow the instructions of the cucumber homepage: http://wiki.github.com/aslakhellesoy/cucumber/ruby-on-rails

Selenium

Selenium is a suite of tools, developed by Thoughtworks, to automate web applications testing across many platforms (http://seleniumhq.org/). In particular, it provides us the capability to run features written with Cucumber's semantics within a real web browser. That gives us the benefit to run features that we couldn't test without a browser (i.e. Javascript dependent functionality).

Install Selenium within Rails

1) First of all we need to follow this document: http://wiki.github.com/aslakhellesoy/cucumber/setting-up-selenium (I). As you can see from there you'll need Java > = 1.5 installed in order for selenium server to work.

2) Then you should install selenium-client gem for our Rails application, as usual:

sudo gem install selenium-client

3) After that, we need to install selenium-on-rails plugin. I used the following repository for that matter: http://github.com/paytonrules/selenium-on-rails/tree/master (because in this one some issues with Rails 2.x are solved)

Setting up a test environment in our Rails application

As you can see from (I), it would be nice to organize selenium features and non-selenium features in different directories, as they need different libraries and initialization. So, I decide to organize it like this:

features/
|-- common
| -- step_definitions
| `-- common_steps.rb
|-- selenium
| -- step_definitions
| `-- browser_dependent_steps.rb
| -- support
| `-- env.rb
| `-- some_ajax.feature
|-- plain
| -- step_definitions
| `-- webrat_steps.rb
| `-- non_ajaxy.feature
`-- support
`-- env.rb

This way, I maintain the support/env.rb file for general environment configuration. But I used selenium/support/env.rb for the selenium's features. The same concept applies to step_definitions that are separated in: common (used by plain & selenium features), plain (non-selenium features) and the ones for selenium.

This separation helps a lot for creating appropiate tasks to run cucumber. I used the following guide to create those tasks http://gist.github.com/73771.

Transactional fixtures

When running test, by default, Rails doesn't save our record into the database (use_transactional_fixtures = false) to isolate test which is a good thing (for our specs for instance). But, for selenium we want to save them! Because selenium server and web server runs in different process (so they don't have visibility for our saved records!). See http://wiki.github.com/aslakhellesoy/cucumber/troubleshooting

As it is suggested there, I used database_cleaner (http://github.com/bmabey/database_cleaner/tree/master) to manage transactions for selenium feature's setup.

Issue with sqlite3

Besides that, I've found some complications to run selenium features with sqlite3. In particular, the problem is that I couldn't disable transactional fixtures for that. But using Mysql worked perfectly for me.

Selenium API

For information on Selenium and the methods provided by SeleniumDriver class that represent our browser you can check the following links:

http://seleniumhq.org/documentation/core/reference.html

http://selenium.rubyforge.org/rdoc/classes/Selenium/SeleniumDriver.html

Other interesting tool is Selenium IDE which is a Firefox plugin that can record your actions and write the correspondence script using Selenium API (that can be re-used within your tests)

See ya!