Download - Migration strategies 4
Software Quality Assurance Feb. 28, 2013
Rejuvenate the legacy automation code
(Selenium + XPath) in IE
Wenhua Wang
Senior Software Automation Engineer
Marin Software Company
Email: [email protected]; [email protected]
Outline
• Why do we rejuvenate the legacy code ?
• Requirement changes, e.g., cross browser testing.
• Limited resources, e.g., budgets.
• Short release cycles, e.g., agile development.
• How to rejuvenate the legacy code ?
• Work at the code level.
• Work at the library level.
• Best practices.
• Q & A
Why rejuvenate the legacy code
• Requirement changes
• The legacy automation testing code (selenium + XPath)
was originally developed for regression testing in
Firefox.
• Cross browser testing was required, after front end
updated jQuery (1.7.2).
Our automation testing limitations
• The legacy code can not work in IE.
• Worked in Firefox 11
• Worked in Chrome 17
• Can not work in IE9
• Automation testing results analysis in IE9:
• Tests were failed due to the timeout at the beginning of each test.
Example: selenium.isElementPresent(“//a[@href=„/campaigns‟]”);
• As a result, there was no testing logic exercised at all. The testing
results can not help us in evaluating the quality of our application.
Develop new automation testing code
• Implement new automation testing code,
• if you have little legacy code, or
• if you have enough budgets and time.
• Implementing new automation testing code is not practical
in Marin, because
• Marin has lots of legacy code (invested between 2007 and 2013).
• Marin has short release cycles, i.e., release every 4 weeks .
• QA has to perform 3300+ tests each regression week.
• QA does not have that budget.
Lines Branches Methods Class
109,021 23,324 6,325 276
Table 1. The Legacy Code Statistics in Marin
Statistics are from Emma
Reuse the legacy code
• Reusing the legacy code may be a better choice.
• Software reuse is the most promising strategy for increasing
productivity and improving quality in the software industry
(http://en.wikipedia.org/wiki/Code_reuse).
• What we have ?
• Locators have already been externalized from the testing code.
• Locators were implemented by XPaths.
Testing code
Locators
Outline
• Why do we rejuvenate the legacy code ?
• Requirement changes, e.g., cross browser testing.
• Limited resources, e.g., budgets.
• Short release cycles, e.g., agile development.
• How to rejuvenate the legacy code ?
• Work at the code level.
• Work at the library level.
• Best practices.
• Q & A
Summary
• Migrate XPaths to CSS selectors
• Blocked by the limitation of CSS selectors.
• E.g., Can not handle parent elements
• High workload
• Migrate XPaths to jQuery selectors
• Solved the limitation of CSS selectors.
• Still tedious.
• Javascript-xpath library
• Minimized workload.
How to rejuvenate the legacy code
• Migrate XPaths to CSS selectors.
• Better performance and easy to use.
DOI=http://sauceio.com/index.php/2011/05/why-css-locators-are-the-way-to-go-
vs-xpath/
• Supported by popular browsers, e.g., IE, Firefox, Chrome.
• Map XPaths and CSS selectors.
• DOI=http://plasmasturm.org/log/444/
• Examples:
• //a[@id='chartButton'] => a[id='chartButton']
• //div[@class='container']//a[@class='remove']" =>
div[class='container'] a[class='remove']“
How to rejuvenate the legacy code
• Example from Marin
“LOGOUT_LINK” locator:
"//a[@href='/index/logout']"; => "a[href='/index/logout']";
Testing Code:
selenium.click(AppPage.LOGOUT_LINK);
• Problem: CSS selectors can not handle
parent elements.
In Marin, a lot of automation tests locate
elements through parent elements. As a
result, migration to CSS was blocked here.
No need to change the
testing code
Change locators only
Real life example of using a parent element in locators
selenium.click(gridPage.checkboxByName(“Marin Marketer”));
public String checkboxByName(String name) {
return "//a[text()='" + name + "']/../../td/input[@name='id[]']";}
Example of locating elements through parent elements
selenium.click(gridPage.checkboxByName(“Marin Marketer”));
public String checkboxByName(String name) {
return "//a[text()='" + name + "']/../../td/input[@name='id[]']";}
Scenario for explaining the logic in the above XPath:
1. Locate a link element whose text is “Marin Marketer” in the grid. Name it
as “MML” in this example.
XPath: //a[text()=' Marin Marketer ']
2. Go to the grand parent of “MML”. Name it as “GP” .
XPath: //a[text()=' Marin Marketer ']/../..
3. Go to the first td child of “GP”. Name it as “first_td” .
XPath: //a[text()=' Marin Marketer ']/../../td
4. Locate the input element of “first_td” with “id[]” name.
XPath: //a[text()=' Marin Marketer ']/../../td/input[name='id[]']
Address the limitation of CSS selectors
1. Refactor the testing code.
• Develop new testing code to move the logic (discussed in slides
11-12) from the XPath to the testing code. Retire some legacy
code, as shown in the following.
selenium.click(gridPage.checkboxByName(“Marin Marketer”));
public String checkboxByName(String name) {
return "//a[text()='" + name + "']/../../td/input[@name='id[]']";}
• This strategy downgrades the productivity.
Our legacy code heavily uses XPath to locate elements through
parent elements. As a result, this strategy takes much time to change
our testing code everywhere.
Develop new code
Use new locators
Address the limitation of CSS selectors
2. Use jQuery selectors to handle parent elements, which
helps control changes in the testing code.
• Supported by popular browsers, e.g., IE, Firefox, Chrome.
• Easy to handle parent elements.
• http://api.jquery.com/category/selectors/
Pros: • Migrate XPath locators easily.
• Effectively control changes in the testing code, compared with
CSS selectors.
Use jQuery to handle parent elements
Use jQuery to handle the parent element (example in slides 11-12).
Legacy code:
public String checkboxByName(String name) {
return "//a[text()='" + name + "']/../../td/input[@name='id[]']"; }
New code:
public String checkboxByName(String name) {
return "selenium.browserbot.getCurrentWindow().$(\"a:contains('"+ name
+"')\").parent().parent().children('td:first').children(\"input[name='id[]']\").click()"; }
The above new jQuery selector has been verified in both selenium and
the chrome console.
Use jQuery to handle parent elements
Use jQuery to handle the parent element (example in slides 12-13).
Legacy code:
selenium.click(gridPage.checkboxByName(“Marin Marketer”));
New code:
selenium.getEval(gridPage.checkboxByName(“Marin Marketer”));
Cons: • Still taints the testing code a little.
• Workload is still high. There are 8102 locators to migrate.
Rejuvenate legacy code at library level
• Why work at the library level ?
• Do not change testing code and locators, which does not require
development and debugging work.
• It dramatically reduces the workload.
• Ajaxslt vs Javascript-xpath
• “Ajaxslt” library is unbearably slow in IE.
• Cybozu Labs released “Javascript-xpath” library in 2007.
• “Javascript-xpath” is 5 times faster than “Ajaxslt” in IE8.
• “Javascript-xpath” is 3 times faster than “Ajaxslt” in Firefox3. DOI=http://www.bonitasoft.org/blog/tutorial/how-to-get-faster-selenium-test-cases-
execution/
• Switch from Ajaxslt to Javascript-xpath
selenium.start();
selenium.useXpathLibrary("javascript-xpath");
Ajaxslt vs Javascript-xpath in empirical studies
• Result s from one empirical study:
• With Firefox 11 browser, “Javascript-xpath” is similar to “Ajaxslt” in
Marin application.
• With IE 9 browser, “Javascript-xpath” is 5.08 times faster than
“Ajaxslt” in Marin application.
• Note:
Ajaxslt + IE9 produced false positives everywhere. We got timeout
failures at the beginning of each test. It means the testing results is
useless.
Ajaxslt +
Firefox
Javascript-
xpath+Firefox
Ajaxslt + IE9
Javascript-
xpath+IE9
4.46m 4.62m 4 7.34m 9.31m
Table 2. Performance comparisons
Why explored techniques to minimize code maintenance
• QA delivers quality.
• Quality is measured by passed tests and failed tests.
• “Don't Forget: You're A Tester” -- Zac Campbell.
http://www.meetup.com/seleniumsanfrancisco/events/98453302/
• Coding and debugging is time consuming.
• It takes time to learn internal knowledge.
• Tricks are lurking in the legacy code (different publisher
policies and strict DB policies in our own companies).
• People are error-prone.
• Save time to do develop new tests. • Avoid coding the same tests 2+ times.
Outline
• Why do we rejuvenate the legacy code ?
• Requirement changes, e.g., cross browser testing.
• Limited resources, e.g., budgets.
• Short release cycles, e.g., agile development.
• How to rejuvenate the legacy code ?
• Work at the code level.
• Work at the library level.
• Best practices.
• Q & A
Best Practices
• Externalize locators. • This decouples the testing logic from web page
structures.
• It minimizes the impacts from web page UI changes
that happen often in reality.
• Simplify locators. • Use logic-none locators, like ids and names.
• Use logic-less locators, like CSS path selectors.
• In reality, sometimes, there is no id/name or there
are duplicated ids/names. In this case, we have to
use path selectors.
• Use the simplest path selectors, if this happens.
Best Practices
• Develop automation tests with well
supported techniques. • This gives us the flexibility to handle new requirements.
For example, CSS, jQuery are well supported in various
browsers. They are good choices for cross-browser
testing.
• Consider existing resources first, like
“Javascript-xpath” library. • Save a lot of efforts.
• Reusing existing efforts is critical for the agile
development.
Thanks !