📜 ⬆️ ⬇️

Test Automation with Ruby and WATIR

image
Dear visitors of the resource habrahabr.ru! We want to introduce you to the article by Jeremy Suarez, a test automation engineer. If you are planning to organize automated testing on your project using Ruby and WATIR, this article will come in handy for you. Jeremy describes everything in simple terms, in elementary examples. After reading the article, you will form a clear understanding of the process - from its initial steps to the final stage.

Before we go directly to the material, I would like to devote a few words to the author. Jeremy has extensive experience in testing. On his many projects, he held various roles - from developer to tester and project manager. He currently works for ThoughtWorks.

So let's get started!
')
The target audience
This material will be useful primarily to testers who are planning to create automated test scripts, or for those who are going to maintain a ready-made framework. It is assumed that the reader has basic knowledge of Ruby syntax and is familiar with the basic principles of developing web applications (such terms as “link”, “form”, “JavaScript” do not lead to a panic attack).

Ruby is a relatively easy-to-learn language. If you already have some experience writing code in Python, C ++, Java or C, you will quickly learn it.

Preconditions and limitations
Here are some of the prerequisites for using WATIR to test web applications. Perhaps the main one is that the module only works with IE 5.5 and below. Unfortunately, it is not designed to work with Netscape, Opera, Firefox, or any other browser. This means that cross-browser testing using WATIR is not possible. The second important detail - WATIR does not have its own recorder. By and large, WATIR is a library of IE methods and objects that can be used when writing scripts manually. And finally, the third - WATIR does not have the means to identify the objects located on the page, as well as their types and available methods. It provides methods for collecting all links, images, forms, etc. Therefore, the process of developing a script often follows a trial and error method, which, incidentally, is not necessarily bad.

Training
Any process of writing automated test scripts must be preceded by a preparation process. The most important point in this case, perhaps, is that all auto tests, in fact, follow logically from the already prepared, manual test scripts. Most of the effort to develop a test framework is wasted due to incorrectly written manual tests. It is important to understand - this is the main point in the further support of both manual and automated testing. It is necessary to see a complete picture of the interaction of business processes implemented using the application and to approach their description covering the entire scope of tasks.

Understanding the specifics of the application under test
Collection of functional requirements (if any)
Before you go directly to the design of manual or auto tests, you need to understand what your application is. The easiest way is to familiarize yourself with the development requirements. Nowadays, documenting requirements is common almost everywhere. And if there are clearly formulated, complete and consistent requirements, this is a good starting point.

Expert survey
In addition to studying functional requirements, or, in the event that they are not, information can be obtained directly from product developers, as well as end users. Usually, architects, business analysts, etc. can also take part in this process. It is important that as many experts from different areas as possible participate in the discussion, since developers usually have their own idea of ​​how the application should work. And as a rule, their point of view is different from the expectations of the client.

Presentation of a business process through test cases
All testing activities, whether manual or automated, should be based on detailed, step-by-step test scenarios. Without this, it becomes problematic to track test progress, as well as code coverage percentage and other metrics. It is wrong to think that auto tests are their own documentation. They are constantly changing, edited. This approach leads to a lot of time and error multiplication.

Creating the data preparation process
Many applications use or create some data in their work. In order to test, both manual and automated, the state of the data in the system should be the same from cycle to cycle. Depending on what exactly the program should do in this case — collect, create, or both, data preparation scripts and cleanup scripts should be prepared. Tests for the preparation and cleaning of data should be arranged in the same way as usual scenarios and used as preconditions in the latter.

Identification of cases suitable for automation
As the well-known advertising slogan says: “Not all yogurts are equally useful.” The same applies to test cases. Not all of them should be automated. Only the most simple and often repeated are good candidates. Start with the cases that work with the UI, then pay attention to those that often have to create and delete data. Finally, try creating a set of scripts covering the most important functional segments (the most frequently used functions).

Creating an automated scripting framework
As soon as you have a clear vision of what specifically needs to be tested, after you document the required functions as step-by-step cases, then you can safely begin developing the auto-test scripts themselves. Copy your manual test case into an empty Ruby script file. Comment out the steps of the script and divide them into separate sections. When splitting, you can also follow the principle - creating data in one place, use - in another. If some data was generated while the script was running, but for some reason the case itself did not reach the end, it would be wiser to delete this data and try to restore the script.

Implementation
In general, the implementation of the automation script testing process using Ruby and WATIR boils down to a few simple steps:
• A test case is selected and can be programmed using a set of functions.
• Initializing an IE object or connecting to an existing browser window
• Go to the initial link of the application
• Collection of all links, images, forms necessary for further action
• From the collected information, the link name, form information, picture name, etc. are obtained.
• Perform actions on a link, form, image
• Repeat steps 3-6 until necessary. At the end of each step, there must be a check that the action performed was successful.

To achieve maximum efficiency, it is extremely important to accompany each step of the test. If such a check is not performed - you can - you can take a screenshot, copy the logs, or at least give a sensible error message. Otherwise, you risk getting something like "Link not found" or "Form xxx is not available."

Only the developer of the script determines how informative the error message will be if something went wrong. Low quality scripts will have to be run manually to understand what happened after all, while a correctly composed script is able to provide all the necessary information about the failure.

Technical aspects of implementation
IE object initialization
Start by creating a new IE browser object or connect to an existing one.

$ ie = IE.new ()

Or

$ ie = IE.attach (: title, “...”)

Go to start link

Start testing the application by clicking on the link given. All cases begin with this. And sometimes it is necessary to follow links during the execution of the script itself.

$ ie.goto (“http: // ....”)

Content verification

The easiest way to check content is with the assert command. Check that the form exists, a button is available, the page contains some text, and so on ... There is no TRY loop in Ruby, for this reason we use the keyword rescue.

begin
assert ($ ie.pageContainsText (“Logged out Successfully”))
assert ($ ie.form (: name, “Login”). exists)
$ log.info (“Test step 5 passed!”)
rescue
$ log.error (“Test step 5 failed”)
$ log.info (“Error text was:“, ie.text ())
end

Collection of necessary links, images, forms

In the process of writing a script, it is not always easy to determine the exact name of the link or image, the format of the URL, the names of the fields, etc. In such cases, you can upload a dump to a log file or on the screen. This information will be useful when creating a test or debugging it, but it should be disabled in the final version of the case. Output data can also be output to files and to standard output devices.

$ log.info (), $ log.error (), $ log.warning () all output to the log4j log file.

Show all links:

puts $ ie.show_links ()

Show all forms:

puts $ ie.show_forms ()

Show all images:

puts $ ie.show_images ()

Show all objects:

puts $ ie.show_all_objects ()

Show full page with all frames:

puts $ ie.html ()

Click on the link

Link activation can be done through its name or direct URL. When working with JavaScript, the link can be activated only by the URL, or if it is a link-picture, by the tag of its image (src, image tag). The click method is one of the standard WATIR methods for link activation.

$ ie.link (: text, “Portfolio”). click

If the link text can change over time, but its location is not, then it will be safer to use the link index (use $ ie.show_links () to search for indexes of various links):
$ ie.link (: index, 20) .click

In the case of using JavaScript, a URL (or href tag) can be used:
$ ie.link (: url, / javascript: deleteClient \ (\ d,. * /). click

Note that URLs should be encoded (spaces expressed as% 20, etc.). You can resort to using regular expressions, as in the example above.

Click on the image
Click on the image is not much different from clicking on the link, except for the presence of additional scr and alt tags.
$ ie.image (: name, “login.gif”). click

Form submission
Filling out and submitting a form is probably the most difficult step performed during the site navigation step. To do this, you need to know the names of all text fields, selection lists, or any other elements present on the form. Use ie.show_all_objects () for this purpose.
$ ie.textField (: name, “username”). set (“testuser”)
$ ie.textField (: name, “password”). set (“testpass”)

Sending is made by "clicking" on the corresponding object:
$ ie.button (: value, “Login”). click

A small tour of the common objects
Work with pop-up windows

Actions
new, back, forward, send_keys, goto, close, refresh, minimize, maximize, restore

$ ie.back ()
$ ie.forwards ()
$ ie.send_keys (“{TAB} {TAB} {ENTER}”)
$ ie.close
$ ie.goto (“http://www.google.com”)
$ ie = IE.new ()

Display functions
showFrames, show_frames, showForms, show_forms, showImages, show_images, showActive, show_active, showLinks, show_links, showAllObjects, show_all_objects, show_tables, buttons, show_spans, show_labels

$ ie.show_tables
$ ie.buttons.each {| m | puts m}

Inherited objects
frame, textField, span, row, selectBox, radio, select_list, text_field,
checkBox, button, checkbox, link, cell, form, table

$ ie.frame (: index, 1)
$ ie.textField (: name, “q”). set (“Test”)
$ ie.button (: value, “OK”). click
$ ie.link (: text, “Happy link”). click
$ ie.select_list (: name, “Day”). select_value (“today”)

Object Lists
checkboxes, labels, images, spans, radios, select_lists, text_fields, buttons, tables, links

$ ie.checkboxes.each {| m | puts m}
$ ie.radios.each {| m | puts m}
$ ie.links.each {| m | puts m}

Checks
getText, text, getStatus, status, getHTML, html, pageContainsText, contains_text, title

if ($ ie.text.match (“Hallo”)! = nil)
puts 'Passed!'
else
puts “Failed! '
$ ie.contains_text (“Google”)
Returns: True

Other features
getImage, getIE, enable_spinner, set_fast_speed, enable_spinner =, wait, popup, down_load_time, getLink, set_slow_speed, getTablePart, focus, url

Text fields
Description
text name = question id = value = alt = src =

Objects
textField, text_field

Recognition methods
$ ie.show_all_objects
$ ie.show_active
$ ie.textfields.each {| textfield | puts textfield}

Other methods
value, value =, clear, click, send, set, enabled ?, flash, html, append, getContents, focus, verify_contains

Most used methods
value, set, append, verify_contains.

Examples
$ ie.textField (: name, “q”). value = ”Sam”
$ ie.textField (: name, “q”). append (“I am”)
$ ie.textField (: name, “q”). value
Returns: “Sam I am”
$ ie.textField (: name, “q”). getContents
Returns: “Sam I am”
$ ie.textField (: name, “q”). set (“Happy”)
$ ie.textField (: name, “q”). verify_contains (“app”)
Returns: true

Buttons
Description
submit name = btnG id = value = Google Search alt = src =

Objects
Button

Recognition methods
$ ie.show_all_objects
$ ie.show_active
$ ie.buttons.each {| button | puts button}

Other methods
value, display, click, send, enabled ?, flash, html, disabled, freeze, focus

Most used methods
Click

Examples
$ ie.button (: name, “btnG”). click
$ ie.button (: name, “btnG”). value
Returns: “Google Search”

Links
Description
"name = id = innerText = Business Solutions href = http: //www.google.com/services/"

Objects
Link

Recognition methods
$ ie.show_links
$ ie.show_active
$ ie.links.each {| link | puts link}

Other methods
value, title, click, link_has_image, enabled ?, flash, html, href, src, text, focus, name, innerText, equal?

Most used methods
Click

Examples
$ ie.link (: text, “Business Solutions”). click
$ ie.link (: text, “Business Solutions”). enabled?
Returns: true
$ ie.link (: text, “Business Solutions”). link_has_image
Returns: false

Notes: The reference is returned without a type if the show_active or show_all_objects methods are used.

Pick lists
Description
select-one name = logonForm: _idJsp15: 0: Question id = logonForm: _idJsp15: 0: Question value = What is your cat's name?

Objects
select_list

Recognition methods
$ ie.show_all_objects
$ ie.show_active

Other methods
option, select, value, getSelectedItems, click, enabled ?, flash, select_item_in_select_list, html, getAllContents, select_value, clearSelection

Most used methods
select, getSelectedItems, getAllContents, select_value, clearSelection

Examples
$ ie.select_list (: name, /Question/).value
Returns: “What is your cat's name?”
$ ie.select_list (: name, /Question/).getAllContents
Returns array: ["What is your favorite color?", "What is your cat's name?"]
$ ie.select_list (: name, /Question/).select_value (“What is your cat's name?”)

Checkboxes
Description
checkbox name = option1 id = value = Milk alt = src =

Objects
checkbox
checkBox

Recognition methods
$ ie.show_all_objects
$ ie.show_active
$ ie.checkboxes.each {| checkbox | puts checkbox}

Other methods
value, clear, click, set, enabled ?, checked ?, flash, html, isSet ?, getState

Most used methods
click, set, clear, checked?

Examples
$ ie.checkbox (: name, “Milk”). set
$ ie.checkbox (: name, “Milk”). isSet?
Returns: true
$ ie.checkbox (: name, “Milk”). click
$ ie.checkbox (: name, “Milk”). isSet?
Returns: false
$ ie.checkbox (: name, “Milk”). clear
$ ie.checkbox (: name, “Milk”). isSet?
Returns: false

Radio buttons
Description
radio name = group1 id = value = Butter alt = src =

Objects
Radio

Recognition methods
$ ie.show_all_objects
$ ie.show_active
$ ie.radios.each {| radio | puts radio}

Other methods
value, clear, click, set, enabled ?, checked ?, html, isSet ?, getState

Most used methods
set, checked? (clear, carefully)

Examples
$ ie.radio (: value, “Butter”). Set
$ ie.radio (: value, “Butter”). isSet?
Returns: true

Note: Clear method for radio buttons is best not to use. Reset the radio button is better by pressing another
$ ie.radio (: value, “Butter”). Clear

Frames (they are layers)
Description
HTML Document name = message id = src = frameshop-intro.html

Objects
Frame

Recognition methods
$ ie.show_all_objects
$ ie.show_frames

Other methods
Note: the frame behaves like a normal IE window. It can be accessed by name (you can by last name), as well as by index and usually create a separate variable to access it. Also, frames are often nested in other frames.

Most used methods
Examples
$ f1 = $ ie.frame (: name, “message”)
$ f2 = $ ie.frame (: index, 1)
$ f1.show_all_objects
The last line returns all frame objects, just like a normal ie object.

Technique
Popup handling
Due to the common pattern of client-side checks by JavaScript and other technologies, pop-up windows are quite common in testing web applications.

They are divided into two types: generated by IE browser and generated by the application itself.

IE usually generates pop-up windows that appear only once. Take at least the Windows warning window that appears when you try to send unencrypted data, submit a form, or ask you to remember a password. It is recommended to block the display of such windows in IE settings and not to process them in the script. JavaScript and ActiveX create their own windows, requiring the user to confirm this or that action, displaying incorrect data, etc. IE does not perceive the page to be fully loaded until the javascript dialogue is closed, therefore the Ruby script will not complete its work until the dialogue is closed.

This can cause a problem, since closing the window requires the previous step to work, but it cannot be performed due to the dialog box.

To prevent such a situation, it is recommended that any actions that may trigger a javascript pop-up window be performed in a separate thread. This will allow the main script to continue working while another thread is waiting for the window to close.
Thread

Click on the confirmation button to close the dialog:
Clicker = WinClicker.new
Clicker.clickJavaScriptDialog (“OK”)

Hidden frames
Sometimes, although the show_frames function returns 0, many or even all frames on a page can be part of a hidden frame. If you are faced with a situation in which the page visually contains objects, but returns an empty list, check if they are not in a hidden frame. Use the following command:
$ ie.frame (: index, 1) ...
This will allow to refer to the frames by index. The main frame has an index of 0, the second in a row, respectively, 1.

Interactive Scripting
After you get used to the process of writing scripts for Ruby and WATIR, you will probably find it very exhausting and time-consuming due to the lack of your own recorder. One of the ways to dispel sad longing is to use the built-in ruby ​​interpreter from time to time.

The interpreter kindly gives you the opportunity to debug the script in the mode line by line in an open browser. You can use the methods discussed above, such as show_links, show_all_objects, to recognize objects on the displayed page, instead of starting the script from the beginning each time.

An alternative is the interactive function show_active_method. It is used to recognize the object that is currently in focus.
puts $ ie.show_active ()

Tips and Tricks
Built-in substitution
Set the todaysDate variable to the current date value in month month format (04212006)
$ todaysDate = Time.now.strftime ("% m% d% Y")
Replace date in line with current date value.
pimsSQL "delete from blotter_funds where name = '# _ 1' and prime_broker = 'Bobby Brown'"
Or the same, only using string concatenation
pimsSQL "delete from blotter_funds where name = '" + $ todaysDate + "_1' and prime_broker = 'Bobby Brown'"

Link to the original article:
www.thoughtworks.com/insights/blog/creating-automated-test-scripts-ruby-and-watir

Source: https://habr.com/ru/post/248203/


All Articles