Sahi Documentation

Sahi Framework - Scenario File

abstract The Sahi Framework allows testers to write their testcases in a Spreadsheet (Excel like) interface and run it from Sahi. Often a testing team consists of a mix of subject matter experts, some manual testers and testers with some automation experience. Writing tests in the language of the business allows all stake holders to participate and derive value out of the automation process.

Sample Scenario File

A sample Scenario looks like this:

These tests talk mostly in the language of the business (also called a Domain Specific Language or DSL for that business), and hide away all the implementation details of clicking buttons and populating textboxes.

Sahi Script Library

The implementation details are moved into an included Sahi script, which is linked to this Scenario via the initial
| loadSahi | sample_lib_new.sah |
statement.

The code in sample_lib_new.sah is given below:
_navigateTo("/demo/training/");

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

function AddBooks($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"));
}

function VerifyTotal($Total){
	_assertEqual($Total, _textbox("total").value);
}

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

function VerifyNotLoggedIn(){
	_assertExists(_textbox("user"));
}

function VerifyErrorMessage($Message){
	_assert(_isVisible(_div("errorMessage")));
	_assertEqual($Message, _getText(_div("errorMessage")));
}


Executing the Scenario file

Executing the Scenario file is no different from executing a Sahi script.

Playback Reports

On execution, Sahi generates logs showing success or failure. Logs are visible from the "Logs" link in Playback tab. Logs can also be accessed via http://localhost:9999/logs

A sample log is shown below. Clicking any step expands to show the underlying Sahi steps.
info Refer to ]sahi/userdata/scripts/sahitests/framework folder for some examples.

Syntax

The rules for writing a Scenario file are as follows

Variables

The Scenario file also supports variables, eg.

Simple variables

$amount=1000
verifyAmount$amount

Assigning value returned by function

Eg. To get the value returned by function createUserInGroup:

Using [ReturnValue]

createUserInGroup"My name""My group"
$userId=[ReturnValue]
verifyUserCreated$userId"My name""My group"
info[ReturnValue] is a keyword to access return value of function executed in previous step. Added since Sahi Pro 6.1.0
Inline declaration

$userId=createUserInGroup"My name""My group"
verifyUserCreated$userId"My name""My group"
Inline as code

$msg= _getText(_cell("msg"))   
_assertEqual $msg "abcd"  

SetUp and TearDown

Different testcases may need the same steps to be executed before and after. For example, one may need to login before and logout after each testcase. This can be accomplished through global SetUp and TearDown blocks. TearDown will be called inspite of any errors or failures in the testcase.
infoThe [Global] keyword is mandatory and defines these [Setup] and [Teardown] methods for all testcase blocks.
[Global] [SetUp]  
_log"In Global Setup"
login"test""secret"
 
[TearDown]
_click_button("Logout")
_log"In Global Teardown"
 
Verify books total [Documentation] Check once
addBooks 3 2 1
verifyTotal 1650
 
Verify books again [Documentation] Check again
addBooks 3 2 2
verifyTotal 2000
This will execute as:

 _log"In Global Setup"  
login"test""secret"
addBooks 3 2 1
verifyTotal 1650
_click_button("Logout")
_log"In Global Teardown"
 
 
 _log"In Global Setup"  
login"test""secret"
addBooks 3 2 2
verifyTotal 2000
_click_button("Logout")
_log"In Global Teardown"

Data driven testing

info Refer to Data Drive in Business Driven Test Automation for the simplest and latest way of data driving testcases in scenario files.
Data Driven Example[Keyword]Add Books Check Starts a testcase "Data Drivern Example" AddBooksCheck function will be called for the data set below.
   
 [SetUp]This will be called BEFORE each row of data
 login"test""secret" 
   
 [TearDown]This will be called AFTER each row of data
 _click_button("Logout") 
   
 [Documentation]javarubypythontotalIgnored by Sahi. Makes testcase more readable
 [Data]3211650[Data] denotes start of data
 4502100 
 0193350 
This roughly translates to:

 login"test""secret"
 Add Books Check3211650
 _click_button("Logout")
 
 login"test""secret"
 Add Books Check4502100
 _click_button("Logout")
 
 login"test""secret"
 Add Books Check0193350
 _click_button("Logout")
 

Using External Data

info Refer to Data Drive in Business Driven Test Automation for the simplest and latest way of data driving testcases in scenario files.
Normally, parameter data is passed inline to keywords/functions in scenario files. However, one may want to keep the parameter data in a separate file for easier maintenance. Sahi Pro 6.2 adds the ability to represent data in external files or database and allows an easy way of accessing such externalized data.

There can be three different ways of accessing external data in Sahi's excel framework:

1) Through CSV file by using _readCSVFile api

D1=_readCSVFilesample_data.csv
2) Through excel file by using _readExcelFile api

D2=_readExcelFilesample_data.xls
3) Through database by using _getDB api

$db=_getDB($jdbcDriver, $jdbcURL, "", "")
$sql="SELECT * FROM EXTERNALDATA"
D3=$db.selectWithHeader($sql)

To understand how this data can be used in scenario files.

Consider a situation where a new user is to be created and added to the database. Each user has four properties lets say firstname, lastname, age, gender.

One wants to pass these parameters as data in a function called "addUser()", which takes these four parameters in the same sequence as mentioned above.
function addUser(firstname, lastname, age, gender) {
	...
}

function addUserEmail(firstname, email) {
	...
}
Now, lets have a look at how the external data can look like.


sample_data.csv
Case 1 data1 Shyam Sundar 11 male
Case 2 data2 firstname lastname age gender
Shyam Sundar 11 male
Jack Sparrow 21 male
Case 3 data3 age gender firstname lastname
11 male Shyam Sundar
21 male Jack Sparrow
Case 4 data4 firstname lastname age gender
Jack Sparrow 21 male
Shyam Sundar 11 male

From database:
Case 5 firstname lastname age gender
Jack Sparrow 21 male
Shyam Sundar 11 male

sample_data.xls
firstname email
Shyam shyam@gmail.com
Jack jack@gmail.com

When data has a single row

Case1
Here data1 is a 1-dimensional array, which can be directly accessed as [D1:data1] and passed to the addUser function.

TC:addUser [Documentation] Add User to the database
addUser [D1:data1]
Or

TC:addUser [Keyword] addUser
[Data] [D1:data1]

When data has multiple rows

Case2
Here data2 is a 2-dimensional array and column sequence is same as that required by the function. So it can either be passed directly as [D1:data2] or each parameter in the same sequence as required.

TC:addUser [Keyword] addUser
[Data] [D1:data2]
// or [Data] [D1:data2:firstname] [D1:data2:lastname] [D1:data2:age] [D1:data2:gender]

Case3
Here also data3 is a 2-dimensional array but sequence of the columns is not the same as the function. So here we can not pass it directly as [D1:data3].

TC:addUser [Keyword] addUser
[Data] [D1:data3:firstname] [D1:data3:lastname] [D1:data3:age] [D1:data3:gender]
Case4
This is same as the Case2. Empty rows will be ignored.

Case5
This is the case when we fetch data from any database using _getDB. There is no key like "data1" here so each column can be accessed as [D2::columnName].

TC:addUser [Keyword] addUser
[Data] [D3::firstname] [D3::lastname] [D3::age] [D3::gender]
Case6
This is the case when we fetch data from any individual row. Each column can be accessed as [D1:data2#Jack:username]. Here #Jack is the reference to the required row and "username" is the required column's name.
infoReference (for example: here #Jack) should be always from the first column of the required row.
TC:addUser [Documentation] Add User to the database
addUser [D1:data2#Jack:username] [D1:data2#Jack:lastname] [D1:data2#Jack:age] [D1:data2#Jack:gender]
Or

TC:addUser [Keyword] addUser
[Data] [D3:data2#Jack]
Case7
This is the case when we fetch data from two or more files. Here username is fetched from sample_data.csv file and email is fetched from sample_data.xls file.

TC:addUserEmail [Documentation] Add User Email to the database
addUserEmail [D1:data2:username] [D2::email]