This is the P2PU Archive. If you want the current site, go to www.p2pu.org!

Learning Web UI Automation

Week 1 - Automation Basics and Locators

David Burns's picture
Thu, 2011-01-27 15:44

Introduction

Test Automation is becoming a skill that all developers and testers need to have. Concepts like TDD and BDD have helped the idea of test automation grow. The other main driving force has been the need for quick turn around in features that users ask for. A manual regression of an entire application can take weeks or months to do but the user may expect it in a weeks time.

With this in mind a lot of effort has been placed on to creating tests that can run in a continuous integration so that we can create have feedback on our code extremely quickly. There are many types of automated tests that we can do in automation. Below is a break down of these terms

  • Unit Testing
  • Integration Testing
    • This is where you start testing more that your small succinct of code. When bits of code need to speak to another bit of code it will not have a fake to send back data unless its to help with a specific issue. Microsoft have a decent explaination of it.
  • Functional Testing
    • This is the testing that checks the functionality of the application. People do BDD tests at this level as it checks that it meets the specification of the business. This could tests at an API or at GUI level. We are going to be concentrating our tests at this level for this course

Automation Core Concept

In all of the different types of automation we need to make sure that we follow the following rules

  • Tests should always have a known starting point. In the context of Selenium, this could mean opening a certain page to start a workflow.
  • Tests should not have to rely on any other tests to run. If a test is going to add something, do not have a separate test to delete it. This is to ensure that if something goes wrong in one test, it will not mean you have a lot of unnecessary failures to check.
  • Tests should only test one thing at a time.
  • Tests should clean up after themselves.

Now that we have this information lets have a look at locating elements on the page

Locators

For this section you will need the following

  • Mozilla FIrefox
  • Firebug addon for Firefox
  • Firefinder addon for Firefox
  • If you are running Windows it might be worth installing Selenium IDE from http://seleniumhq.org as it has a find button that can highlight elements on the page by their locators.

Selenium has the ability to find elements on the page by a number of different techniques. These allow us to interact with the elements so we can test the work flows a lot better. Below is a break down of the different techniques and how we can go about using them.

Locating Elements By ID

It is good practise to have IDs on elements on the page. It increases the testability of the page and allows Selenium to find the unique item, as IDs should be unique, and then complete the action that it needs to do against that element. Since elements can be moved around the page to help with the usability we don't want our tests to fail since the functionality hasn't changed just the layout.

So to use an id we have to look at the HTML source of the page. Below is a snippet of a button with an id.

<input id=myButtonID type=button value='My Button'>

to click on this we would use the selenium command click and pass in the id of element. In this case our call would look like selenium.click("id=myButtonId"). The id= prefix isnt needed but makes it a little more readable for other people who may maintaise it.

Locating Elements By Name

If elements do not have IDs its good to try get them to have names. Like IDs it  increases the testability of the page and allows Selenium to find the quickly and then complete the action that it needs to do against that element. Since elements can be moved around the page to help with the usability we don't want our tests to fail since the functionality hasn't changed just the layout.

So to use an id we have to look at the HTML source of the page. Below is a snippet of a button with a name.

<input name=myButtonName type=button value='My Button'>

to click on this we would use the selenium command click and pass in the id of element. In this case our call would look like selenium.click("name=myButtonName"). The name= prefix isnt needed like above but if possible make little changes to the way you write your tests to make it more maintainable.

Locating Elements By Link Text

Since the most useful way for a user to get around a site is by clicking on links. We need to be able to click on the links. Selenium takes a globbing approach to finding Links on the page. This can be quite useful but the is a major downside to useing link text for tests. If your test needs to work against different locales it will not work.

But nevertheless there are times where using link text is useful for those times we need to us link=Text in link. So clicking a link command would look like selenium.click("link=my link text"). If the link goes to another page it is good practise to follow it by selenium.wait_for_page_to_load("30000"). This tells selenium to do nothing until the page has loaded or after 30 seconds (30000 is a timeout value in milliseconds) throw an error.

Locating Elements By Xpath

Unfortunately, best practices cannot always be followed when building the markup, or if they are, they may have a dynamic edge to them. An example of this would be working against a page that uses a key from the database as the element ID. To get around this we have to use Xpath or CSS locators.
Since HTML is a markup similar to XML we can use XML Xpath queries to find the elements on the page.

Things to note

/html is a direct xpath query. if you put another element it would fail find it
//input is indirect xpath query. It searchs the page until it finds the first element that matches.
[@attribute=valueOfAttribute] allows us to search attributes on nodes in the DOM.

Lets see this in action

<li id="c-37">
          <a href="/en-US/firefox/extensions/language-support/">Language Support</a>
        </li>

The xpath to the link is //li[@id='c-37']/a. To use it in Selenium it would be selenium.click("xpath=//li[@id='c-37']/a"). Read up more on Xpath here

Locating Elements By CSS

As was mentioned above, not eveeryone follows best practise. Xpath is really good for finding elements but unfortunately it has a major downside. It is extremely slow to use within Browsers. This is even more noticeable in Internet Explorer. To get around this we can use CSS locators. These are extremely fast compared to XPath but can only read forward through the DOM. XPath can find an element and then walk the DOM backwards.

CSS locators need to have the css= prefix to tell Selenium that they are CSS locator. The above snippet in CSS would be css=li#c-37 a. The Selenium call would be selenium.click("css=li#c-37 a")

Selenium supports CSS2 and CSS3 selectors.

Tasks

Please send in your answers to the task to me via the site. Please use the forums to ask questions but do not submit your answers there. You can also find me on IRC on irc.mozilla.org in the #Mozwebqa channel if you need to ask questions. My nick is AutomatedTester.

Prerequisites

  • Firefox
  • Firebug
  • Firefinder
  • If on WIndows, Selenium IDE from seleniumhq.org

1) Visit http://addons.allizom.org. Look at the links on the left and write down the Name of the link and the current locator to use it. Bonus marks for locators that are locale agnostic. Answer in the form of a table.
2) How would you change the locators above to make them easier to use and more maintainable while still being locale agnostic.

You can test out you locators with the following python code. Run it in the python REPL by loading the terminal/command prompt and typing Python. Remember to start the Selenium Server before running the python code.


from selenium import selenium

selenium = selenium("localhost", 4444, "*firefox", "http://addons.allizom.org")
selenium.start()

selenium.open("/")
selenium.click(insert your locator here)