QA City

Join Hands to Build a Smarter India: Sign in | Join now
   QA City >> Expert Column
Dont Miss Experts

Sahi Writing Maintainable Scripts

Narayan Raman
Narayan Raman
CEO, Tyto Software Pvt. Ltd
Narayan Raman is the founder, CEO of Tyto Software Pvt. Ltd, a Bengaluru based software products ... more>>
One of the challenges of automation is to be able to write scripts which work in the long run. Scripts should be maintainable and easy to understand for newer team members.

In this article, we will explore writing good maintainable Sahi scripts. While this article uses Sahi for illustration, the concepts used are independent of the testing tool. We will be using the sample application available at http://sahi.co.in/demo/training/
GOAL: To automate a scenario in the sample application, which is a simple book store. We shall perform the following actions

1)Login
2)Add different quantities of books to a shopping cart
3)On addition of books, the application displays the total amount to be paid. We will verify the total.
4)Logout

First, let us record the sequence
1)Open a browser from the Sahi Dashboard.
2)Bring up the Controller (ALT-Double Click on the page)
3)Start recording a script. Give it a name of 1_raw_recording.sah



4)Enter http://sahi.co.in/demo/training/ as the start URLand click Go



5)Enter “test” as username and “secret” as password and login
6)Add books in different quantities (say 3, 1, 2) and click Add



7)On clicking add, the bottom portion is populated and the total is visible.



8)Press the CTRL key and hover over the total text field.



9)Once the Accessor field is populated, Click on Assert.
The “Evaluate expression” box gets populated with possible assertions. Let us select the _assertEqual statement, which asserts that the total is 1800.



Clicking on Test prints the output of the selected expression in the bottom box.
Add this assertion to recorded script by clicking on “Append to Script.

10)Click the Logout button on the application to logout.
If all went well, we should have a script which looks like this:

_navigateTo("http://sahi.co.in/demo/training/");
_setValue(_textbox("user"), "test");
_setValue(_password("password"), "secret");
_click(_submit("Login"));
_setValue(_textbox("q"), "3");
_setValue(_textbox("q[1]"), "1");
_setValue(_textbox("q[2]"), "2");
_click(_button("Add"));
_assertEqual("1800", _getValue(_textbox("total")));
_click(_button("Logout"));

TIP: To open the script for editing, click on the “Scripts” link on the dashboard, and then open the .sah file in a text editor like Notepad
A few points to note about the script:
1)The script does not have any waits
2)The script is fairly readable except for the setValue statements after login

Now let us compare the script to our initial goal statements. One difference to note is that the goal talks about functionality of a book store application. The script, on the other hand, shows steps at a more basic level. The script only communicates “how” a user interacted with the system, without communicating the intention. A test script which does not communicate the intention is much more difficult to understand and maintain later.
Let us now modify the script to express our intention too. Creating functions out of groups of functionality, we arrive at:

function login($username, $password){
_setValue(_textbox("user"), $username);
_setValue(_password("password"), $password);
_click(_submit("Login"));
}

functionaddBooks($numJava, $numRuby, $numPython){
_setValue(_textbox("q"), $numJava);
_setValue(_textbox("q[1]"), $numRuby);
_setValue(_textbox("q[2]"), $numPython);
_click(_button("Add"));
}

functionverifyTotal($total){
_assertEqual($total, _textbox("total").value);  
}

function logout(){
_click(_button("Logout"));
}

login("test", "secret");
addBooks(3, 1, 2);
verifyTotal(1800);
logout();

Notice how various steps are grouped logically into functions to express intention. If we look at the last 4 statements,
login("test", "secret");
addBooks(3, 1, 2);
verifyTotal(1800);
logout();

it communicates the intention of the script very well.
SIDE NOTE: Sahi script is like Javascript. Functions, parameters, variables, conditions, loops etc. are all available and follow the constructs of Javascript. One significant difference is that all variables start with a $ in Sahi script. (Sahi script is parsed by Sahi to produce pure Javascript code)

The above is a significant improvement over our original recorded script. But we still see some clutter with all the function definitions at the top. So let us move them off into a new file and separate the function definitions from the calls

library_functions.sah

function login($username, $password){
_setValue(_textbox("user"), $username);
_setValue(_password("password"), $password);
_click(_submit("Login"));
}

functionaddBooks($numJava, $numRuby, $numPython){
_setValue(_textbox("q"), $numJava);
_setValue(_textbox("q[1]"), $numRuby);
_setValue(_textbox("q[2]"), $numPython);
_click(_button("Add"));
}

functionverifyTotal($total){
_assertEqual($total, _textbox("total").value);  
}

function logout(){
_click(_button("Logout"));
}


verify_total.sah

_include("library_functions.sah");
login("test", "secret");
addBooks(3, 1, 2);
verifyTotal(1800);
logout();


We move all the function definitions into library_functions.sah and then just include it in verify_total.sah using the _include API of Sahi. Now verify_total.sah communicates very clearly what the intention of the test script is.
Apart from making the intention clear, functions allow reuse of functionality. If we were to create another test case which needs login and logout, we just include library_functions.sah and call login() and logout() functions.
SIDE NOTE: In our trainings, we see that,testers who are just starting automation do not grasp the difference between a function definition and a function call.
This is a function definition:
function logout(){
_click(_button("Logout"));
}
This does not get executed unless we call it using
logout();
We define a function once in a script, but can call the function logout() any number of times.


NOTE: Recorders are a stepping stone to automation. We should use them only as code generation tools. We should convert recorded scripts into functions, at the earliest, so that they become reusable.
Let us examine our script once more. Look at addBooks function

functionaddBooks($numJava, $numRuby, $numPython){
_setValue(_textbox("q"), $numJava);
_setValue(_textbox("q[1]"), $numRuby);
_setValue(_textbox("q[2]"), $numPython);
_click(_button("Add"));
}


We see here that the 3 textboxes on the webpage are identified as _textbox("q"),_textbox("q[1]"),_textbox("q[2]"). All these textboxes have the same name “q” which is not an uncommon scenario in a dynamic application. Sahi tries its best to uniquely identify the elements by adding an index, but that is not enough. Suppose another book is added to the list or the order of the books changes, this script is going to fail. To fix this we will use Sahi’s _near API to associate a textbox with the name of the book instead of the index. Here is the modified code:

functionaddBooks($numJava, $numRuby, $numPython){
_setValue(_textbox("q", _near(_cell("Core Java"))), $numJava);
_setValue(_textbox("q", _near(_cell("Ruby for Rails"))), $numRuby);
_setValue(_textbox("q", _near(_cell("Python Cookbook"))), $numPython);
_click(_button("Add"));
}


Now, even if the book moves up or down in the order, the test will still pass.
Conclusion: To write maintainable tests one needs to separate the script into logical reusable functions and remove of any hard coding that may cause errors during playback.

Information on Sahi:

Website: http://sahi.co.in/
Forums: http://sahi.co.in/forums
Twitter: _sahi
Experts on QA
Praveen  Mohan
Principal Engineer
Yahoo
Mangesh Shrikant Gokhale
SeniorTestEngineer
Sigma Software
Vimal Raj Selvam
SoftwareTestEngineer
BNP Paribas
Harsha  Nutalapati
Sr.Vice President
Indium
Punit  Thakkar
CEO
Shivaami Corporation
Vaidyanath  Ramalingam
Director-Engineering
Huawei
Arobinda  Tripathy
Senior Manager
Mindfire Solutions
Soumik  Ghosh
Product Management
Robert Bosch
SiliconIndia About Us   |   Contact Us   |   Help   |   Community rules   |   Advertise with us   |   Sitemap   |  
News:       Technology   |   Enterprise   |   Gadgets   |   Startups   |   Finance   |   Business   |   Career   |   Magazine  |   Newsletter   |   News archive  
Cities:        CEO   |     Startup   |   Mobile   |   CIO   |   Women   |   BI   |   HR   |   SME   |   Cloud   |   Marketing   |   QA   |   Java   |   Web Developer  
Community:      Members   |   Blogs   |   Indian Entrepreneurs   |   Gyan   |   Advice   |   Community   |   Find   |   CXO Insights  
Job Board:      Jobs   |   Freshers   |   Companies   |   HR Speak   |   Forum  
Online Courses:   Web Developer   |   Java Developer   |   CCNA Training   |   SEO   |   SAS   |   SQL Server 2005   |   J2EE
Education:   MBA   |   MCA   |   Engineering   |   Training Institute
Life:          Real Estate   |   Travel   |   Finance   |   Gadgets   |   Movie Reviews   |    Jokes  
Send your feedback and help us continue to improve SiliconIndia
© 2014 InfoConnect Web Technologies India Pvt Ltd. all rights reserved