CI CD and Selenium WebDriver

Once you have learnt writing the Selenium Tests by implementing various different framework, the next step is to understand how to share the code repository with team, version control, Concepts of CI/CD and the tools that help in achieving that.

So the first step is to setup a sample test script with the help of Maven Project (You can setup a ordinary java project too, in which case the configuration steps in Jenkins would differ from what i’ve explained in this post). Below is my Test class

 
public class SimpleSearchTest {

 WebDriver googleDriver;

 @Test
 public void searchTest(){

 File file = new File("C:/Selenium/JarFiles/chromedriver.exe");
 System.setProperty("webdriver.chrome.driver", file.getAbsolutePath());

 googleDriver = new ChromeDriver();
 googleDriver.get("https://www.google.com/");
 WebElement searchTxt = googleDriver.findElement(By.name("q"));
 searchTxt.sendKeys("vishwas");
 }

 public void somef(){

 }

}
 

So first lets see how to setup and maintain a local code repository and then shared code repository. A remote repository can be shared privately or with public.

Once you setup the repository, you can commit the code to this repository. Time stamp of the commit, developer name, commit message will be saved with the commit so that at anytime, one can see who did changes to central repository. Also, you can pull the repository to your local and start working on it anytime.

 

I used Git to create and share my code repository. You can find the detailed steps to setup GitHub in this link: Selenium Github Tutorial in Guru99

Points to Note:

  1. For the first time when you share the code, a local git repository is created by Git. For this to happen, you need to install Git in your local. The same website guru99 will help you with step by step process of installation
  2. If you want to commit it to GitHub(online central repo) then you will do Team–> commit
  3. You will notice a GitStaging window gets activated in your eclipse(note: i am using eclipse Neon. Git Plugin is pre-installed, so i didn’t install it again)
  4. Since Eclipse has git plugin, you need not again work on command prompt and pass the commands with file location etc, to commit the code, everything can be done in eclipse (i suggest you to watch is video tutorial so that you will appreciate how much of a headache of working on command prompt is eliminated by eclipseGit video tutorial)
  5. In GitStaging window, it will show you what files are ready to be staged to git Staging server and then committed to your remote repository. See the screenshot below
    gitStage
  6. You can select the files you want to push to the Staged changes window. Files are now ready to be committed to GitHub
  7. Enter the message, select the Author, contributor and click commit and push. Done.
  8. At any given time, you can also pull the version of code you have in GitHub and start working on it.

That is it, you are all set to use one of the most popular source version control system. Note that the free version of github is public repository – i.e anyone can search and locate your repository and see the code.

You can also explore other options like BitBucket-SourceTree for helping you with  version control repository.

So now lets switch to the topic of build Automation i.e performing auto build of our Selenium Scripts.

 

There are several options available to do the job of performing build automation. But the most popular among the lot is Jenkins. I am going to discuss about the same below.

I suggest you to learn what-why-how of Jenkins by going through this edureka video

This learn-automation Video tutorial provides step by step details of creating a Jenkins Maven project and integrate it with your Selenium Test project (Maven based). In the video, the instructor has not used online repository(github) as source. However, the steps would remain the same even if you have your project in GitHub except the following:

  1. You need to select Git as your source repository (git plugin may needs to be installed)
  2. jen1
  3. You need to specify the pom.xml path as /<projectName>/pom.xml
  4. jen2

Save and that’s it. Done. You have setup auto-build job. Depending on build trigger you have selected, the build process will start, runs you test cases and reports the results.

Note that when you run the job, depending on which OS you are using, you may or may not get to see the Test run on browser. In my case, i am using windows 7. All i had to do was, make some changes to Jenkins service in windows services as mentioned here. Once done, i restarted my Jenkins. Next time when i ran the job, a small window opened as shown below.

Services

When i clicked on View the message, I navigated to the server where Jenkins was running the Test. The browser window was seen there.

Selenium Framework – Data Driven Testing with Cucumber

In this post i am going to discuss how we can do data driven testing while doing BDD – Cucumber based Framework implementation.

Pre-requisites:

Before you proceed, you will need to know the following

  1. Writing Features
  2. Maven
  3. Cucumber framework
  4. Basic parameterization technique in cucumber feature file

In my application under test, i am building a script to test Account Transfer function

This is how my Maven project structure looked like at the end:

projectStructure

The excel file in which i’ve saved the Test data

excel

My Feature file 

Note that i’ve parameterized the test data such as customer ID, account transfer details etc. as s “row_Index”

Value for the row Index is provided in the Examples. 1 and 2 corresponds to excel row#2 and 3 (row#1 being header row)

These values are picked up by Step Definition class file and available as parameter for all the corresponding annotated functions (@Given, @when etc. wherever applicable. Refer to feature file screenshot below)

What happens next? First take a look at the Feature file screenshot below and then we will proceed to next section

feature

 

So as i said above, row_index value is available as parameter for my stepDefinition class which looks like below:

public class AccountTransfer {

 WebDriver sunViewDriver;
 POMSunViewLoginPage l; 
 POMTreasuryDBPage t;
 POMTransferCenterPage ct;

 public List <hashmap<string,string>&gt; dataSet;

 public AccountTransfer(){

 File file = new File("C:/Selenium/JarFiles/chromedriver.exe");
 System.setProperty("webdriver.chrome.driver", file.getAbsolutePath());
 sunViewDriver = new ChromeDriver();
 sunViewDriver.get("https://wholesaleportal-itca.suntrust.com/SunView/user/login?contextType=external&amp;username=string&amp;initial_command=NONE&amp;password=secure_string&amp;challenge_url=https%3A%2F%2Fwholesaleportal-itca.suntrust.com%2FSunView%2Fuser%2Flogin&amp;request_id=6651191237148972048");

 dataSet = DataHelper.readExcelDatafromFile("C://Selenium//TestData//AccountTransfer.xlsx", "Sheet1");
 }

 @Given("^Login to SunView as \"(.*?)\" customer$")
 public void login_to_SunView_as_customer(String excelDataRow) throws Throwable {

 //access the first hashmap in the List
 int dataRow = Integer.parseInt(excelDataRow)-1;
 l = new POMSunViewLoginPage(sunViewDriver);
 //Make sure that they key name matches with column name you provided on header row in Excel
 l.loginToSunView(dataSet.get(dataRow).get("customerID"), dataSet.get(dataRow).get("userID5x"), dataSet.get(dataRow).get("password5x_SunView"));
 sunViewDriver.manage().timeouts().implicitlyWait(20, TimeUnit.SECONDS);
 }

 @When("^user provides provides account transfer data as in \"(.*?)\"$")
 public void user_provides_provides_account_transfer_data_as_in(String excelDataRow) throws Throwable{

 //access the first hashmap in the List
 int dataRow = Integer.parseInt(excelDataRow)-1;
 t = new POMTreasuryDBPage(sunViewDriver);
 ct = new POMTransferCenterPage(sunViewDriver);

 t.clickOnTransfers_SingleTransfer();
 ct.createSingleTransfer(dataSet.get(dataRow).get("FromAccount"), dataSet.get(dataRow).get("ToAccount"),dataSet.get(dataRow).get("Amount"), dataSet.get(dataRow).get("Date"), dataSet.get(dataRow).get("Frequency"), dataSet.get(dataRow).get("RecurringSchedule"), dataSet.get(dataRow).get("NumberOfPaymentsOption"), dataSet.get(dataRow).get("SendTotalTransfers"), dataSet.get(dataRow).get("EndOnThisDate"), dataSet.get(dataRow).get("Options"), dataSet.get(dataRow).get("Memo"));

 }

 @When("^Submits the transfer$")
 public void submits_the_transfer() throws Throwable {
 ct.PreviewTransfer();

 }

 @Then("^That Transfer should be successful$")
 public void that_Transfer_should_be_successful() throws Throwable {

 ct.validateTransfer();
 ct.searchTransferToVerifySuccessfullSubmit();
 t.clickOnTreasuryDashboard();
 t.logoutOfSunView();
 }
}
 

 

So as you can see in the above code, I have created a List variable that holds hashmaps in it. Then  i am calling a excel reading function by passing it the file location and sheet name as parameters, which is nothing but the location where i’ve saved my Test data excel fie. The List that the function returns is saved in my local List variable.

So now, lets get into the details of excel Reading function and how it is implemented.

In the Data Helper package i’ve a class file in which i have the excel reading function. Step by step details of how it is working given below:

  1. Declared a new List Object that holds a collection of HashMaps
  2. Using the Apache POI functions, I am picking the excel file, navigating to the required sheet
  3. Declared a Variable of type Row called HeaderRow and hardcoded it to point to row#0, i.e the first row of my excel that has header details aka column names
  4. Enter the for loop to iterate the rows
  5. Now, i declared a HashMap object which holds Key and its values in String format
  6. Why declare HashMap object inside the For loop? Because i want every row of excel data to be saved in a unique HashMap objects
  7. Enter the for loop to iterate the column
  8. notice that the “KEY” part of the hashmap always refers to the header row and picks the corresponding column’s cell value
  9. notice that the “VALUE” part of the hashmap refers the current Row- current column (current as in for loop’s iteration)
  10. Exit the Column-Iterating for loop
  11. Add the hashmap into the List object bucket
  12. Repeat the step4 to 11 as many # of times as the # of rows are there in excel file
  13. Exit the Row for loop
  14. Finally, Return the List object

Below is the code:

public class DataHelper {
public static HashMap<String,String> storeValues = new HashMap<String, String>();
public static List<HashMap<String,String>> readExcelDatafromFile(String filePath, String sheetName){

//create Java List to store Hashmaps
List <HashMap<String,String>>excelData = new ArrayList<>();

try{
FileInputStream fs = new FileInputStream(filePath);
XSSFWorkbook wb = new XSSFWorkbook(fs);
XSSFSheet sheet = wb.getSheet("Sheet1");

//catch header row, so that you can use it as Key for your hashmap
Row HeaderRow = sheet.getRow(0);

for(int r = 1; r<=sheet.getPhysicalNumberOfRows();r++){
Row CurrentRow = sheet.getRow(r);
//each row of data is stored in new hashmap
HashMap<String,String> currentRowMap = new HashMap<String,String>();

for(int c=0;c<CurrentRow.getPhysicalNumberOfCells();c++){
Cell CurrentCell = CurrentRow.getCell(c);
System.out.print(CurrentCell.getStringCellValue() + "\t");
currentRowMap.put(HeaderRow.getCell(c).getStringCellValue(),CurrentCell.getStringCellValue());
// i.e hashmap<key, value> = <row(0)column(c), row(1)column(c)>
}
excelData.add(currentRowMap);
}
wb.close();
fs.close();
}
catch(Exception e){
e.printStackTrace();
}

return excelData;

}
}

 

Let me show you pictorially what this hashmaps look like

HASHMAP

And this is how the List Object excelData looks like

HashMap2

So in the below code(extracted from StepDefinition package), I’m essentially using the dataRow variable to access the hashmap#1, 2 etc… And then, .get(“key”) function access the Keys like customerID, UserID etc and fetches its values

@Given("^Login to SunView as \"(.*?)\" customer$")
public void login_to_SunView_as_customer(String excelDataRow) throws Throwable {

//access the first hashmap in the List
int dataRow = Integer.parseInt(excelDataRow)-1;
l = new POMSunViewLoginPage(sunViewDriver);
//Make sure that they key name matches with column name you provided on header row in Excel
l.loginToSunView(dataSet.get(dataRow).get("customerID"), dataSet.get(dataRow).get("userID5x"), 

 

Finally the TestRunner class. I’m not going in detail here. There is hardly any change to this class file. It is a standard one

package testConfig;

import org.junit.runner.RunWith;

import cucumber.api.CucumberOptions;
import cucumber.api.junit.Cucumber;

@RunWith (Cucumber.class)
@CucumberOptions (
features = "src/test/java/Features",
glue = "stepDefinition",
plugin = {
"pretty",
"html:target/cucmber",
}
)
public class AccountTransferTest {

}