Uploading Images in Watir 6.0.2

Even when most of the automated checks in our test server are running via the HTTP layer instead of using the browser, I have kept the automated UI versions of those tests for review purposes. They’re not very practical for continuous integration but still fun to watch sometimes, at least for me. It is also good practice to fix them when they break, to see whether I’m still updated with how Selenium or Watir runs.

And recently I found out that I’m unable to upload images in Watir 6.0.2 using the usual way, giving me an error:

element located, but timed out after 30 seconds, waiting for true condition on <element location> (Watir::Exception::UnknownObjectException)

The test code in question was this, written using the page-object gem

self.photo = IMAGE_FILEPATH

where photo is just a given name for a file field in the page where an image is to be uploaded. In basic Watir, this can also be written as

@browser.file_field(:id, "LOCATOR_PATH").set(IMAGE_FILEPATH)

Both test code are timing out, and the test failing because of the exception error. When manually checked, there are no issues in uploading images whatsoever.

Apparently, this an open issue in Watir and the workaround at the moment is to properly set the values of Watir’s relaxed_locate before and after the actual image upload code, like so

Watir.relaxed_locate = false
self.photo = IMAGE_FILEPATH
Watir.relaxed_locate = true


Watir.relaxed_locate = false
@browser.file_field(:id, "LOCATOR_PATH").set(IMAGE_FILEPATH)
Watir.relaxed_locate = true

And that makes the image upload work again. Both work for Google Chrome and Mozilla Firefox. 🙂

Post-Installation Notes after Setting-Up Cucumber-Ruby-Watir Automated Checks with Jenkins on a Windows 10 Amazon EC2 Server

Had a chance to set up cucumber tests to run via Jenkins on a Windows 10 Amazon EC2 server last week. It’s been a while since I installed everything from scratch, so that was good practice. I ran into some problems, which was a bit expected since my local setup was on Windows 7, so this post serves as a guide for possible future installations.

The process:

  • Install desired browsers where the tests will run.
  • Install Java and the latest JDK. Include the JDK path to Window’s system environment variables. This is necessary for running the selenium server.
  • Install the latest Ruby and DevKit versions, required for installing ruby gems and running the test suite.
  • Install Jenkins, which will take care of scheduling and test results reporting. Also install Jenkins as a service, to run automatically after the server boots up.
  • Install Git on the machine, and setup the credentials for retrieving the test code from the remote repository.
  • Check out the test code from the remote repository.
  • Set the selenium server to run automatically after the machine boots.
  • Install the required ruby gems using bundler.
  • Check if cucumber tests run properly by running a sample via the command line interface.
  • Create/Import Jenkins jobs for the cucumber tests. Install the Jenkins plugins necessary for test results reporting. Possibly set up Jenkins to pull the latest test code from the remote repository.
  • Run cucumber tests via Jenkins.

Some reminders for future installs:

  • Install the 32-bit version of Ruby’s DevKit instead of the 64-bit because the latter version creates problems with gem installs.
  • Windows 10 has trouble installing ruby gems (using the bundle install command) from the default HTTPS source. To fix this, replace the gems source list in the Gemfile from HTTPS to HTTP.
  • Install Jenkins using the MSI-based Windows installer on its own directory on the C drive, then install it as a service afterwards.
  • Do not install all suggested Jenkins plugins at first, especially the ones related to Git. These will break Jenkins on Windows so install only those that are actually needed for cucumber tests to run.
  • Via Jenkin’s Configure System module, set the shell executable to the location of the command line’s executable file (i.e., C:\Windows\system32\cmd.exe) so that Jenkins can run cucumber tests via the default Windows command line interface. In addition, each Jenkins job Build needs to be set as “Execute Windows Batch Command” instead of “Execute Shell”.
  • Remember to change the timezone of the machine to the proper timezone.
  • Test a sample basic cucumber project first to see if cucumber is properly running on the machine before retrieving the actual test suite from the Git repository.
  • In saving the machine’s generated public SSH identification (via Putty or the ssh keygen command using Cygwin), do not include a name for the file to be saved so that the system generates the default id_rsa.pub file.

Defining What Cucumber-Watir-Ruby Checks To Run by Passing Parameters

Like any other type of document, automated checks can build up to so many files. There can be many features we would like to run tests on and it can be hard to keep track of all them every time. Maybe we prefer writing varying groups of checks in one single file, which cucumber does not restrict us from doing. We may also like to run our checks on different test environments, browsers, or locations that does not necessarily require a change in a feature to test but rather only an adjustment in configuration. Fortunately, there are ways to perform all of this without remembering numerous commands to run our checks. Here are some of them:

  • Cucumber Tags (-t)
    Using Cucumber tags is an easy way of defining groups of tests in a feature file, so we can choose to only run a select group instead of running everything when we test a particular feature. Here is an example of a feature file (with sample filename of policies.feature) with tags (displayed in bold, characterized by the @ symbol):

      Feature: Booking Engine Rate Plan Policy Copies

       @prepay @partial
       Scenario: ShowRooms Prepayment Policy, DWH Partial
         When guest views the policies for a DWH property for a partial rate plan
         Then a copy of 'Only 10% prepayment is required to confirm your reservation' is displayed in the prepayment policy

       @prepay @full
       Scenario: ShowRooms Prepayment Policy, DWH Full Non-Refundable
         When guest views the policies for a DWH property for a full nonrefundable rate plan
         Then a copy of 'Full prepayment is required to confirm your reservation' is displayed in the prepayment policy

       Scenario: ShowRooms Reservation Policies, DWH Partial, Lead Time Early Modification
         When guest views the policies for a DWH property from 4 DAYS FROM NOW to 6 DAYS FROM NOW for a Public_Partial_LT rate plan
         Then a copy of 'We don't charge you a modification fee if you choose to modify before' is displayed in the modification policy

    If we want to run the prepayment policy copy tests (the first and second scenarios in the example), we can run those checks as:

      cucumber policies.feature -t @prepay

    And if we want to run only the single reservation policy copy check in the example feature, we can run that as:

      cucumber policies.feature -t @reservation

    More information about how to use cucumber tag are found in the Cucumber tags Wiki page.

  • Custom Environment Variables
    We can create custom variables we can use for specifying how we want our tests to run. For example, we might like to run the same feature test for a different browser, or on a mobile application instead of on a desktop web app.

    To define what custom variable we want to use for our checks (say, a browser type), we could write the following code in the env.rb file:

      def browser_type
        (ENV['BROWSER'] ||= 'chrome')

    which means that we are stating a browser type variable of name ‘BROWSER’ we can use for describing which browser we would like to use during the test run.

    If we want to run the policies feature check on a firefox browser (assuming that functionality is built in our test code), we could say that as:

      cucumber policies.feature BROWSER=firefox

    And if we want to run the same checks on a chrome browser, we can either say that the browser type variable should equal to ‘chrome’:

      cucumber policies.feature BROWSER=chrome

    or just omit the browser type variable altogether, since the browser defaults to the value of ‘chrome’ based on the code above:

      cucumber policies.feature

  • Cucumber Profiles (-p)
    Eventually there will be a situation where we would need to use common cucumber commands, tags, or custom environment variables in running our checks, and typing all of those may prove tiring and unproductive. For example, would you feel good typing in

      cucumber policies.feature FIG_NEWTON_FILE=staging.yml --no-source --color --format pretty -t ~@not_ready BROWSER=firefox

    to run the policy copy checks (not including the checks that are not yet ready) for the firefox browser in the staging test environment with test results display in the terminal displayed with color and formatted properly? I personally wouldn’t enjoy writing all of that, and this is where cucumber profiles help. To use profiles, we could state desired profiles in the cucumber.yml file, like so:

      default: FIG_NEWTON_FILE=staging.yml --no-source --color --format pretty --tags ~@not_ready
      dev: FIG_NEWTON_FILE=dev.yml --no-source --color --format pretty --tags ~@not_ready
      uat: FIG_NEWTON_FILE=uat.yml --no-source --color --format pretty --tags ~@not_ready
      parallel: FIG_NEWTON_FILE=staging.yml --no-source --color --format pretty --tags ~@not_ready --format html --out reports/parallel_.html

    where in the example above we can see that there are four profiles, namely: default, dev, uat, and parallel.

    When we want to run the same checks as before in the uat test environment, we would only need to type in the following:

      cucumber policies.feature -p uat BROWSER=firefox

    And when we want to run the same checks in staging (where we would usually run them), we can even omit writing the profile since the default profile runs whenever the profile is not defined:

      cucumber policies.feature BROWSER=firefox

    More information about how to use cucumber profiles are found in the Cucumber cucumber.yml Wiki page.

About failing Automated Watir checks on Firefox v.48 and successfully running them on Google Chrome v.52

The recent updates on the Mozilla Firefox browser starting from version 46 onwards broke my automated end-to-end checks. The browser loads when started but does not go to a test page or do anything until it eventually fails, because the latest versions of Firefox supposedly doesn’t use the FirefoxDriver anymore for automation and instead makes use of a new driver implementation in what is called Marionette. In order to get my checks running again in Firefox, I had to resort (as what many others in the community also did) to using the Extended Support Release version of Firefox v. 45, a temporary measure until I finally get my Cucumber-Watir checks running properly on the latest Firefox version.

At the moment I am stumped by an error when running automated checks on Firefox v. 48.0.1 using Marionette (which seems to be a problem on permissions on my local Windows machine, and not on watir or selenium, although port 4444 points to the port which selenium grid is connected to):

Permission denied - bind(2) for "::1" port 4444 (Errno::EACCES)
C:/Ruby/lib/ruby/gems/2.2.0/gems/selenium-webdriver-2.53.4/lib/selenium/webdriver/firefox/service.rb:103:in `stop_process': undefined method `poll_for_exit' for nil:NilClass (NoMethodError)
from C:/Ruby/lib/ruby/gems/2.2.0/gems/selenium-webdriver-2.53.4/lib/selenium/webdriver/firefox/service.rb:83:in `stop'
from C:/Ruby/lib/ruby/gems/2.2.0/gems/selenium-webdriver-2.53.4/lib/selenium/webdriver/firefox/service.rb:64:in `block in start'
from C:/Ruby/lib/ruby/gems/2.2.0/gems/selenium-webdriver-2.53.4/lib/selenium/webdriver/common/platform.rb:161:in `block in exit_hook'

So, while I’m trying to sort out that problem (anybody experienced this?), I decided to move my checks to run on the latest version of Google Chrome by default instead of running them on an old version of Firefox. To do that, I needed to update my browser capabilities:

if browser_type == :chrome
    arguments = "--ignore-certificate-errors" // Add more desired arguments
    capabilities = Selenium::WebDriver::Remote::Capabilities.chrome "chromeOptions" => {"args" => [ arguments ]}
elsif browser_type == :firefox
    capabilities = Selenium::WebDriver::Remote::Capabilities.firefox
browser = Watir::Browser.new :remote, :url => url, :desired_capabilities => capabilities

And all that is left is to see how the checks behave on Google Chrome.

Some findings:

  • Button or link elements in the browser (especially when they are only span or heading elements that are being used functionally as buttons) that are not immediately visible in the Chrome viewport fail to be clicked properly. To fix this, focus on the element first (or alternatively call a scroll method in the browser using javascript to a position where the element becomes visible in the viewport) before running the click step.
  • Some wait methods that didn’t necessarily have to be written (when checks were run in Firefox) need to be explicitly stated when running checks on Chrome.

Steps In Starting A Cucumber-Watir-Ruby ATDD Automation Project using TestGen (Windows)

I said that I was going to lay low on automation this year. However, I was also still curious about implementing a Watir-Ruby counterpart of my existing Java-Webdriver automation framework, including an acceptance-test driven development (ATDD) or a behavior-driven development (BDD) functionality built-in, just so I can understand how different the two frameworks are, based on my own experience. Long story short, I learned how to do it, with help from Jeff Morgan’s “Cucumber & Cheese” ebook, and was surprised how easy it was to start, and eventually write code.

If you ever want to try building a Cucumber-Watir-Ruby project from scratch on a Windows machine, try this:

  1. Download the latest version of Ruby for your machine
  2. Run the installer, ticking the following options when prompted
    • Install Tcl/Tk support
    • Add Ruby executables to your PATH
    • Associate .rb and .rbw files with this Ruby installation
  3. Run the command prompt, a shortcut is by pressing the Window and R keyboard buttons at the same time, typing in cmd, and then pressing Enter
  4. Test the Ruby installation by running ruby -v
  5. Close the command prompt if the Ruby version is displayed in the screen. If not, try re-installing Ruby or checking if Ruby is set in your machine’s Path under system environment variables
  6. Download the Ruby Development Kit for your version of Ruby
  7. Create a new folder under C:\ directory called devkit
  8. Extract the Development Kit files to the newly created directory
  9. Run the command prompt again
  10. In the command prompt, navigate to the devkit directory by running cd C:\devkit
  11. Once inside the directory, type in ruby dk.rb init and then press Enter
  12. After that, type in ruby dk.rb install and press Enter
  13. Then let’s install some gems by running this: gem install cucumber testgen rake bundler yard watir-webdriver page-object fig_newton
  14. When the gems finish installing, go back to the command prompt and run cd C:\Users\Your_Machine_Name or go to a desired directory where you want to house your automation project
  15. Still in the command prompt, run testgen project Project_Name –pageobject-driver=watir. This should create a new directory structure inside your project folder which cucumber will use to run your automated checks.
  16. Create a test_filename.feature file (without anything in it) inside your project directory
  17. Test if the project works by going to the project directory and then running cucumber test_filename.feature in the command prompt

If you encounter problems with a ffi_c file, such as a “cannot load such file — ffi_c (LoadError)” error, doing the following may help:

  1. Run gem uninstall ffi
  2. Then run gem install ffi –platform ruby

If the ffi_c issues persists, uninstalling the latest version of Ruby, installing an older Ruby version (say v2.1.8) and redoing Steps 3-17 may fix the problem.

Note: For a Mac or an Ubuntu machine, the Ruby and Devkit installations may differ.