Archive for the ‘Ruby’ Category.

Selenium Fury is on RelishApp.com

Checkout Selenium Fury on relishapp.com. I found the site when I was searching for Rspec2 documentation. The site organizes your cucumber features into a really nice presentation so that your features can be consumed as documentation. It has been a great tool for learning more about Rspec 2. To illustrate the difference this is what it is like to view Features on github and here is the same feature on rellishapp.

Selenium Fury 5.5 released

I was able to restructure the gem and remove the dependency on Rspec. I have tested successfully with Rspec 1 and 2.

Selenium Fury 5.2 with custom generators has been released.

The latest release of Selenium Fury is ready for your install.  Checkout the new cucumber features at the project home  https://github.com/scottcsims/SeleniumFury. This version includes extended page element recognition, custom generators, and the git hub project includes support for bundler and rvm.

Install the new release:   gem install selenium_fury

https://rubygems.org/gems/selenium_fury

 

The Selenium Fury gem is ready! Page object factory for Selenium and Ruby.

I have been working on converting our page object factory to open source for a few weeks. Now it is time to launch the  HomeAway sponsored open source project under the Apache 2.0 license.  It is a furiously quick way to implement test automation.  I am planning to add more configuration options in the future.

This project started when I had to test a page with 300+ check boxes and I did not want to enter them by hand.  I used the page object generator to build a page of ruby variables with Selenium locators. Everything was great until some number of the check boxes changed their ids and my tests started failing.  I needed  a quick way to find out how many changed so I could update the locators by hand or regenerate the page.  This is where the validators came in.  I used Ruby’s support of reflection to open a class, navigate to the url of the page and use Selenium to validate the locators and return a list of missing locators on the page.  It worked perfectly for my page of 300+ check boxes.  I had over 40 that changed I quickly regenerated the page.

Install with:

  • gem install selenium_fury

Checkout the home page and examples at https://github.com/scottcsims/SeleniumFury

Thanks to HomeAway for sponsoring this project.

Use rspec partial mock to write a quick executing example.

I wanted to test an error message in my class that processes test results and sends them to Rally.  The problem was that I did not want to actually create a rally object and run the method to parse the results, just to test the error message.
This is what my class looks like.

class AutomationRun
  def send_results_to_rally
    @rally = RallyUtils.new(ENV['RALLY_WORKSPACE'])
    push_test_case_results
    raise("Test Case Results Were Not Parsed Correctly") if test_case_results.empty?
    test_case_results.each do |result|
      @rally.update_test_case_result(:tc_id =>result.test_case_number_from_spec_report, :build =>result.build_number, :verdict =>result.verdict, :notes => result.note.format_note)
    end
  end
end

I want to skip these steps to test the error message:

  • don’t instantiate RallyUtils.new  we don’t need @rally for the test
  • don’t parse the results so don’t call parse_test_case_results

This is what my test code looks like:

 it "should raise an exception if there are not test case results" do
    RallyUtils.stub!(:new).and_return(nil)
    automation_run=AutomationRun.new
    automation_run.should_receive(:push_test_case_results).and_return([])
    begin
    automation_run.send_results_to_rally
    rescue Exception=>e
    end
    e.message.should == "Test Case Results Were Not Parsed Correctly"
  end
  1. We use a rspec stub to intercept the new call to the RallyUtils class and return nil.  We could have also returned a mock object if we wanted to execute a call on the rally class. Now we are not creating a connection to Rally
  2. Now it is time to new up or AutomationRun class and setup our mock expectation to skip running the real push_test_case_results method.
  3. automation_run.should_receive tells us to intercept the symbol or method push_test_case_results
  4. and_return([]) will just return an empty array
  5. We setup a begin rescue block to capture the Exception object returned by our expected error message
  6. Now we call send_results_to_rally to get our error message
  7. Lastly we verify that the message attribute for our error is Test Case Results Were Not Parsed Correctly

So that is it, I created a partial mock  in that we are using a real automation run object but we stubbed out one of the methods.  We also stubbed out the new call to rally so we don’t create a connection.  Now I can focus my test on exactly the function I wanted to test, the error message.

Deep Test 2.0 prerelease is available.

Deep test allows you to run ruby rspec tests in parallel by providing a spec task that you include in your rake file. The 2.0 prerelease version of deep tests offers support for rspec 1.1.12. You can install it buy running: gem install deep_test_pre. Require it in your rake file like this:

gem “deep_test_pre”, “=2.0”
require “deep_test”

gem “deep_test_pre”, “=2.0”
require “deep_test”

There currently is a bug that occurs if you run Test::Unit tests with the deep test spec runner.  The tests will all run twice but are reported once.

Advanced Test Automation – Generate your own css locators using nokogiri

Some of the pages that I test have hundreds of check boxes. I needed a way to generate the locators to use in selenium and create classes to use those locators.
This is an example of a class that contains selenium css locators for navigation links

class Navigation
  def initialize * browser
    @location =  "css=a:contains(\"Location\")"
    @amenities =  "css=a:contains(\"Amenities\")"
    @photos =  "css=a:contains(\"Photos\")"
    @contact =  "css=a:contains(\"Contact\")"  
    @further_details =  "css=a:contains(\"Further Details\")"
  end
  attr_accessor :location, :amenities, :photos, :contact, :further_details
end

To use this class I would new it up and use standard selenium commands. This is how I would navigate to the amenities page

navigation = Navigation.new
browser.click amenities

The spec below demonstrates how to get data you need using nokogiri. I want to click an anmenity check box with the label beach whose input name is “amenity_1_1_6”. I could click this checkbox with this command browser.click “amenity_1_1_6”, but I want to have a way to store all of the amenities on the page with the variable named by their label.

require "spec"
require "nokogiri"
describe "Find elements to use as locators in a web test" do

  it "should find the value of name for the input element and the text in span" do
    sample_html = ''
    attribute_name=""
    attribute_value=""
    doc = Nokogiri::HTML(sample_html)
    doc.css("label").each do |check_box|
      attribute_name =  check_box.text
      attribute_value = check_box.children.css("input")[0]["name"]
      attribute_name = attribute_name.strip
      attribute_name = attribute_name.to_s.downcase

    end
    attribute_name.should=="beach"
    attribute_value.should=="amenity_1_1_6"
  end
end

To take this further I can print the contents of my class file to generate my locators from this spec.

puts "@#{attribute_name} = \"#{attribute_value}\""

Rubymine 2.0.2 and the gem bundler

I use bundler 0.9.6 with all of my projects. Checkout my earlier post on how to add bundled gems to your project.  I am excited about the updated bundler support in Rubymine 2.0.2 for a few reasons.

Rubymine can easily find my bundled gems in my Gemfile and attach gems to my project with suggestions. Now I can Go To Declaration for all of my attached gems.

Attech gems from the Gemfile

Attech gems from the Gemfile

I don’t have to navigate to my project through the terminal to unlock the Gemfile and add a new gem. I can use the bundler menu for all bundler functions.

Bundler 9.0 options

Bundler 9.0 options

I can get feedback from my bundler commands inside the Rubymine run window.

Unlocking through rubymine

Unlocking through rubymine

Deploy your Ruby project with out the need to install gems.

I have been using the gem bundler lately with my ruby projects to deploy to team city build agents.  My project needed to run on multiple OS X and Cent OS systems without having to manage ruby gems manually.  The bundler gem repository is located on github at http://github.com/carlhuda/bundler.  There are a few different ways to use it so I decided to write about how use it.  The short answer is that I lock and pack the gems I need, and fall back to sudo installed gems when needed. I am using bundler 0.9.6. The prerequisite is that you gem install bundler.

Use a begin / rescue to try to require the environment file.
If the file is not found then execute the bundle install command

begin
  # Try to require the preresolved locked set of gems.
  require File.dirname(__FILE__) + "/../.bundle/environment"
rescue Exception=>e
  # Fall back on doing an unlocked resolve at runtime.
  if (!system("bundle install"))
        puts $?
  end
end
require File.dirname(__FILE__) + "/../.bundle/environment"

On the first run the bundle install command will execute
This operation will create a .bundle directory in the root of your project that will contain an environment.rb file that will contain all of your gem configuration information.
All your files need to do, is include this environment file and they will have access to your bundled gems. If you run the bundle install command twice in a row it will not install again if your gems have already been installed.

Three step process to setup your bundler.
Create a Gemfile that will list what gems to install. Lock your gem file and then pack your gems.
Check out the information on github to see the format of the gemfile. You can use the bundle init command to create the Gemfile for you in the base of your project. Now run the bundle lock command. A Gemfile.lock file will be created you will check this in to your version control system. Next you need to pack the gems. Run the command bundle pack. You will see that a vendor/cache directory will be created. You will need to check in the vendor cache directory into your VCS. Now when your deploy your code will self execute the bundle install command making all of the gems you need available too your project.

Working with compiled gems
I really like using the Nokogri gem but I foud out that when I execute my project with in the Team City execution environment with a Cent OS build agent, that Nokogiri cannot build correctly because it cannot access the system files it needs. The work around is to list nokogiri in your Gemfile, but don’t check in the gem into the gem cache. Install it as the user that will be executing your scripts so it will be available to your execution environment. The bundler will resolve the dependency to your system installed gem.

That was a quick rundown of what you can get using the bundler and how to set it up. I will continue to post updates as I come across more challenging situations. For now I still have to touch every machine that needs odbc ruby configuration and nokogiri.

Run selenium ruby scripts in parallel from Team City.

I recently found out why my automated tests run in parallel from my workstation, but then run in sequence from a team city build agent.  It all comes down to the rake runner in team city.  Team city uses a customized rake runner that extends rspec’s spec task.  You get all of the per test reporting, graphing and historical information from team city’s customized rspec reporting.  All this is great if you don’t mind running your tests in sequence, but If your using team city to launch automated web test using the selenium grid this is bad news.

I use a rake file to control the execution of my ruby selenium scripts. I modeled it from the ruby example in the selenium grid distribution. What is important to know about the run in parallel rake task is that it is not your normal rake task. It is first a rspec spec task.  This is a test runner from rspec that allows you to use a rake task to run specs. Not only is it a spec task, it also has been overridden by deep test, the software package that adds parallelization.  Since the spec task is actually deep test’s spec task and not the rspec spec task there are dependencies on what version of rspec deep tests needs.  You must run with rspec 1.1.8 so that the spec task that deep test overrides will work correctly.

So what happens when you run your deep test spec task from team city with their rake runner?   Deep test cannot launch your tests in parallel because Team City is using their customized spec task.  The solution is to use the command line runner to launch your rake task for the selenium grid, then your spec task will have access to the correct rspec gem for deep test to use as a spec runner.