Design Selenium Framework with C# – Part 2

After learning the basics of the interface design pattern, lets look at actual implementation in step by step manner.

Lets first discuss about how to set up the required nuget packages for the selenium.

Open visual studio and create a unit test project by selecting the project type unit testing.

Once the project is created, lets install the required Nuget packages. This Nuget package is similar to maven repository in Java. It contains all binaries required for the purpose.

NuGet

We will download and map to the current project just enough to create some simple selenium tests.

The Nuget packages can be downloaded from different sources, lets download packages from default location https://www.nuget.org/

We need following packages for the purpose of creating the selenium tests.

Nuget required packages for selenium

Once we download and attach it to the project we need to do download another set of install-able files meaning that driver exes to steer the web browsers.

  • IEDriverServer
  • ChromeDriver
  • geckodriver (firefox dirver)

Now our project setup is ready for creating the Framework and implementing the simple selenium tests.

Before we dive into creating classes, lets create folder structure so that we can partition our classes into different directories like below. Will discuss one by one while we go through each of the items. Lets create following folders in the solution.

  • DriverExecutables
    • This will contain the driver executable files we have downloaded
  • IDrivers
    • Contract definitions for creating the WebDrivers
  • WebTesting
    • Actual web driver classes implementing the IDrivers interface.

FolderStructure

As we mentioned in the part one, let us first create the IDrivers interface to make browser object as described below.

IDrivers Interface

In the above Interface, we are defining the objects required fro web driver creation and also using the ‘Driver’ property we are setting and getting the driver back from each implementation.

In this step lets create the configuration class which defines the driver executable locations, timeouts and other browser configuration details we have just defined in the interface.

Configuration

Lets look at each of the web driver class, how it is done. I have kept all the code in git repository for reference.

Lets create filepath property to set and get the file path. Also see how we can set the driver services and desired capabilities/options as class properties.

After creating these properties, next step is to initialize the driver with these options

chrome driver implementation 1

If you look at  below code the folder path is set by config driver exe folder whereas DesiredServices and DesiredCapabilites/Options properties in config class are set by chrome driver class.

chrome driver implementation 2

I will try to explain the logical flow once we complete the entire post.

As of now the summary is, all driver classes (ChromeDriver, FireFox driver class, and IEdriver class)  have all the three methods.

driver classes

The link to the whole repository from git is given below for reference.

selenium framework git repository

It will be much more straight forward if you already well versed with the basic idea of properties, methods, and oops concepts.

Now lets discuss about how to create these browser instances as separate threads so that we can run tests in parallel in next part.

Design Selenium Framework with C# – Part 3

Design Selenium Framework with C# – Part 3

In this section lets look at creating thread safe driver factory and how we can use it in the tests.

As we have seen in part 2, we have created driver classes and each class is having initDriver method which will creates the driver.

Now lets start with an enum with browser types, and in the driverfactory class which we are going create uses the browsertype enum and creates and stores the corresponding driver.

enum

And lets create thread safe object  using ThreadLocal class, thread local class stores the object initiated by the execution thread, so that when we want to use it we can retrieve it. Think of it as a thread id and driver object pair, each driver object has its thread id attached to it and based on the execution thread, ThreadLocal class will provide the corresponding Driver object.

DriverFactory

If you look at the second method, the GetDriver<DriverType> is generic method with DriverType as generic type of the webdriver.

Since we have declared the ThreadLocal type as ‘Object’ instead of standard class, it will not result in any cast errors.

In the init method based in the browser type we can create the browser object.

init

Here if you observe, the DriverStored property is being set in the InitDriver method.

And the DriverStored object is returned using GetDriver<BroweserType> generic method.

Now we have everything ready, and lets create a simple test and look at the where we are going start our driver initiation and how will we set the flow.

For now lets imagine, all page classes contain UI object creation and action methods.

(In the latest selenium 3.14 creating page objects using findsby is getting deprecated, so I am using POM concept but using it as more generic approach rather than using the regular init elements.)

Design Selenium Framework with C# – Part 4

 

Design Selenium Framework with C# – Part 1

In the current Selenium space there are lot of developments are happening. One of the most asked questions in the internet is how to design extensible and most easy frame work that can be suited for different kinds of testing platforms such as desktop, mobile.

Selenium with C# is not that common in the current freeware market era. But its worth knowing about how it can be implemented so that we can future ready. C# is now becoming language for building all kinds of apps including mobile. Having knowledge on C# selenium will bring us more opportunities for a devops engineer.

With that preface, I will try to create a logical flow of learning. Lets look at following areas one by one to achieve our goal of learning.

I typically go with bare minimum requirements to create the framework assuming readers know the basics of any object oriented programming language. So I am starting with concepts familiar but implemented little different in C#.

  • Basics of C# interfaces and setters and getters.
  • Basics of Interface design pattern for framework creation.
  • MS visual studio nuget packages required and drivers required for selenium
  • Driver factory or thread safe driver creation
  • NUnit testing framework bare minimum to Create basic google search test with Nunit

In this blog lets start with first section.

C# provides the important feature of setting and getting the class properties. There are auto properties which are really useful and takes care of the coding.

Setters sets the properties and getter will get you the properties. Following is the example of setters and getters. This is widely used and need to be understood while working with C#

public class test
{
private string _anyproperty;
public string AnyProperty
{
get{return _anyproperty;}
set{ _anyproperty = value;}
}
}

In the above example we can declare private variable and use it to assign and return. This is same as setting auto properties like below in C#.

public class test
{
public string AnyProperty
{
get;set;
}
}

Class properties can be set inside class or out side the class using the class object.
The properties are quite useful in designing the framework. Usually anything we want to set for the entire class such as file path for the excel operations class, file path for the browser driver class etc, this same path can be used in the class methods.

In the next section we will see how interfaces can be used to create portable and readable code.

Interface is generally known as contract agreement. It signs the contract with implementing classes. I.E it enforces the method definitions for implementing class.

The underlying code can differ with different class implementations.

In view of our selenium, let’s take the example of Browser driver, the IWebDriver interface holds the method definitions and all driver classes such as ChromeDriver, FireFoxDriver , IEDriver classes implements the methods in IWebDriver interface.

To understand how we can make use of interfaces to create clean code while designing the C# frame work, lets look at browser object creation.

In C# selenium browser object can be initialized similar to Java. To initialize browser object we need two objects

  • Browser Service
  • Browser Options or Capabilities.
    • IWebDriver ChromeDriver = new ChromeDriver ((ChromeDriverService)service, (ChromeOpions)capabilities, timeout)
    • IWebDriver FireFoxDriver = new FireFox ((FireFoxDriverService)service, (FireFoxOpions)capabilities, timeout)
    • IWebDriver InternetExplorerDriver = new InternetExplorerDriver((InternetExplorerDriverService)service, (InternetExplorerOptions)options, timeout)

If we look at all three initialization, in fact all driver classes implementing IWebDriver have these three parameters two of which are class objects.

It makes sense for us to utilize the interface concept here and create IDriver interface which have two methods (Service object creation and capabilities/option object creation)

This will enforce for all types of driver objects to implement these methods.

Lets end the first part here, and in the next part, will dive deep and create framework using MS visual studio.

Design Selenium Framework with C# – Part 2

 

Conditional testing with ITestAnnotation interface

In TestNG there is provision that we can run tests conditionally, like we can have test case that needed to be executed with flags yes or no and we want to conditionally run these tests.

For this purpose we can make use of ITestAnnotation interface. This provides the interface to override the test annotations during runtime.

TestNG_ItestAnnotation

The above example is listener class that can override the transform method, which dictates the test annotation. We can control the enabled annotation attribute to make test available to pickup by the TestNG framework.

Make sure that you have enabled annotation available for the test. I.E explicitly add this annotation for the test so that, TestNG overrides the Annotation. If this attribute is not there TestNG cannot  override the same.

TestNG_ITestAnnotation_Enabled

And finally add this listener to TestNG XML to make things work.

TestNG_XML

LeanFT ApplicationModel project setup and overview on ECLIPS.

Hello, lets look at how to create your first test using application model with LeanFT step by step.

Once you install and configure the LeanFT for eclips ( LeanFT quick setup for ECLIPS IDE) you can create new ApplicationModel project.

  • Select  file -> new -> Project in ECLIPS IDE.
  • Select ApplicationModel Project
  • newProject
  • you can opt out Maven project or you can choose maven depending on your project requirement, I am going ahead without maven since it is just for demo.
  • CAUTION : If you are creating without maven, then you might have to add decencies manually.
  •       MavenProject
  • Give a name to project and give a package name (example com.demo) After click on finish you should see project default structure like below.
  • ProjectDefaults
  • Now if you see the com.demo it is disabled and it contains the application model which is nothing but object structure or object repository in old UFT terms.
  • ApplicationModel
  • As you see you have Hat icon and + icon on the top right side of the Application Model which indicates Inspecting and  Adding the objects to Object Repository.
  • Lets look at test case where we want to open googole site and search for LeanFT.
  • Lets first make sure in the system tray  LeanFT runtime Engine is running. As discussed in earlier post, leanFT runtime engine is responsible for the identifying the objects and running the created tests.
  • SystemTray
  • We must select web engine in the UFTRuntime settings so that objects will be identified as web objects. Right click on the icon in system tray and select Web as option, once you do it Runtime Engine will automatically restarts. If not do it manually and check if all objects are identifying as web objects.
  • DefineENgine.PNG
  • To create test first we need to define UI objects and pages you want to test on.
  • Lets click on Had Icon to identify the objects, and use add icon (+CUBE icon) on the inspect screen to add objects. Add text box object and google search button too.
  • googleTextBox
  • Once you add objects, you should see Application Model as follows.
  • AddedObjects
  • Notice few things here
    • WebPages – Hierarchic objects
    • WebElements – Child elements in the WebPages.
  • In the left hand side, you see name and Code name, Code name is what we use to invoke the object, it is like function that returns this object.
  • LeanFT automatically creates the associated page classes and creates objects in ApplicationModel.java class.
  • Do not modify this class as code gets regenerated everytime you update ApplcationModel.
  • ApplicationModel_Class
  • Now lets look at test case and some of the jar files that are needed to run the test cases.
  • The ApplicationModel.java has all methods that returns the UI objects with code names.
  • TestClass can make use of it and create test cases. Following is the way to generate the test case.
import java.net.URI;
import java.net.URISyntaxException;
import org.junit.Test;
import com.demo.ApplicationModel;
import com.hp.lft.report.Reporter;
import com.hp.lft.sdk.*;
import com.hp.lft.sdk.web.*;
import com.hp.lft.sdk.GeneralLeanFtException;
import com.hp.lft.sdk.web.Browser;
import com.hp.lft.sdk.web.BrowserFactory;
import com.hp.lft.sdk.web.BrowserType;

public class TestClass { 
@Test 
public void test() throws Exception 
{  
Browser browser = BrowserFactory.launch(BrowserType.CHROME); 
browser.navigate("https://google.com"); 
ApplicationModel app = new ApplicationModel(browser); 
app.googlePage().searchEditField().setValue("LeanFT"); 
app.googlePage().googleSearchButton().click(); 
}
}

in the above @Test method, you can see application model app is being created as object.

After creating the “app” object, the first thing model returns is pages, and each page returns all objects in it. You can invoke the object with their code names and perform actions on it.

Going back to import statements , there are are lot of them, along with already loaded jar files. LeanFT requires these jar files to include in the test to avoid sdk loading issues.

additionalJars

After adding you project should look like below.

AllJars

Now you are ready to start the execution of created test.

When you run your tests you might get following exception for loading sdk. Also you might not see view las run results enabled.

SDK Load Issue

to avoid above issues, include loading sdk and generating report part through code. I have got this from micro focus site after running around few hours. Please find below link for detailed explanation. I have added code from same to my test and it worked like charm.

load SDK

@Test public void test_modified() throws Exception 

{ 

//code to resolve sdk lodaing issues 
ModifiableSDKConfiguration config = new ModifiableSDKConfiguration(); 
SDK.init(config); 
Reporter.init();   

Browser browser = BrowserFactory.launch(BrowserType.CHROME); 
browser.navigate("https://google.com"); 
ApplicationModel app = new ApplicationModel(browser); 
app.googlePage().searchEditField().setValue("LeanFT");
 app.googlePage().googleSearchButton().click(); 

//Code to generate report and cleanup 
Reporter.generateReport();         
SDK.cleanup();
}

Now the issue got resolved and I got the report link enabled after I run the script. if it is not enabled we can get the latest report from RunResults directory. Sample leanFT report for the above test will look like below.

LeanFTReport

This is how we can quickly setup the project for leanFT and execute the tests for Application model.

Converting eml file to pdf

Hi, one of requirement for my automation task is to read eml file and save as pdf file and this has to be done in batch for several file. This is just hack how to do automate that task. THIS WILL NOT STORE THE ATTACHMENTS. Its just inserting the eml file into doc and converting it to pdf. This code is vbscript code.

wdStory=6
wdMove=0
wdNotSaveWord=0
wdSavePDF=17
Set objWord = CreateObject("Word.Application")
Set objDoc = objWord.Documents.Add()
Set objheaderfooter = objDoc.Sections(1)

objheaderfooter.Headers(1).Range.Font.Italic = True
objheaderfooter.Headers(1).Range.Font.Color = RGB(0,0,255)

objheaderfooter.Footers(1).PageNumbers.Add
objheaderfooter.Borders.Enable = true
Set objSelection = objWord.Selection
objWord.Visible = false

objSelection.EndKey wdStory, wdMove
objSelection.TypeParagraph()

rem insert file code
objSelection.InsertFile("YOUR FILE PATH")
objSelection.EndKey wdStory, wdMove

'Save word to temp folders
timemills = now()
strfilename=replace(timemills,"/","_")
strfilename=replace(strfilename,":","_")
strfilename=replace(strfilename," ","_")
tsname="Sample"
pdfpath=tsname&"_"&strfilename&".pdf"


Set fso = CreateObject("Scripting.FileSystemObject")
foldername = now()
folderdate = split(foldername," ")
current = Replace (folderdate (0),"/","_")

rem folder path to save file
folderpath ="FOLDER PATH TO SAVE FILE"

If fso.folderexists (folderpath) then
msgbox "Folder exists not creating new one"

End if

pdfpath=folderpath&"\"&pdfpath
msgbox pdfpath
objDoc.SaveAs pdfpath,wdSavePDF
objWord.Quit wdNotSaveWord

LeanFT quick setup for ECLIPS IDE

Hello, recent days I have been working with LeanFT and faced some hiccups in installing configuring and setting up for ECLIPS IDE.

LeanFT is plugin for integrated development environments. It supports ECLIPS and MS Visual Studio and ItelliJ.

In this blog, I will quickly discuss about setup for ECLIPS IDE and issues I have faced with step by step instructions.

  1. First of all we have to down load ECLIPS IDE. As per LeanFT documentation ECLIPS Oxygen 32 bit version is most supported. you can view from the same.                Eclips download link
  2. ECLIPS
  3. Now got to micro focus site and download the LeanFT installable.
  4. In the installation follow the instructions carefully to avoid the issues later.
  5. The most important instruction is, you have to select the path of the ECLIPS exe folder.
  6. You might have several ECLIPS installations, but which one you want to use it, carefully keep the same path and use the same ECLIPS exe to see the LeanFT plugin.
  7. After installation, restart the machine.
  8. Boom!! now if you open LeanFT menu will appear in ECLIPS. But, unfortuantely we have few more steps to see the LeanFT plugin.
  9. Download and copy (gson-2.8.1.jar) file to plugins directory in ECLIPS folder, it is mentioned as known sssue in the leanFT instructions manual a, see below.    LeanFT KnownIssues

KnownIssues

9. Once everything is done, lets open the ECLIPS exe. There is another .exe file gets generated in the ECLIPS directory, see below.

ECLIPSFolder10.  Use eclipsec.exe to launch the IDE.  You should see below menu in the ECLIPS.

LeanFTMeny

11. You should see leanFT related projects when you click File->New->Project from ECLIPS. See below

newProject

12. LeanFT is UFTPro, if you are worked with UFT its like cake walk for automating anytype of project, if you are UFT guy better to start project as Application Model project.

13. In LeanFT, there is run time engine called LFTRuntime, when you start project LFTRuntime will start on port 5095. This is responsible for detection of objects and running the created tests. Lets see how to kick start project as Application Model project and resolving starting hiccups in next section.

 

 

Extent report logging while parallel testing

Hi As we discussed in the last post Parallel testing and Thread Safe driver for testNG, lets discuss about extent report log synchronization.

We can achieve this by invoking parallel threads for each of the test.  Lets consider we have one html extent report and we want to add several tests together.

We can do extent report as static and we can create tests in different threads,  and at the end we can flush each thread to report. Lets see below code for extReport and extTest classes which does the same.

public class ExtReport {
public static Calendar cal = Calendar.getInstance(TimeZone .getTimeZone("GMT")); 
public static long time = cal.getTimeInMillis();   
    public synchronized static ExtentReports getReport() 
    {          
      ExtentReports Report = ( new ExtentReports(System.getProperty("user.dir")    + "/test-output/ExtentReport_" + time + ".html", true));    
      Report.addSystemInfo("Host Name", "TestMachine") 
         .addSystemInfo("Environment", "Automation Testing")
         .addSystemInfo("User Name", "Tester");
      Report.loadConfig(new File(System.getProperty("user.dir")    + "\\extent-config.xml"));     
      return Report;   
    }                
 }

In the above class we are generating static report and have one method to get the report.

This method, will return the static report object. Lets look at creating test and adding it to the same report.

public class ExtTest 
{
public class ExtTest
{
   private static ExtentReports extent = ExtReport.getReport(); 
   public static ThreadLocal<ExtentTest>  extentTestThreadSafe = new ThreadLocal<ExtentTest>(); 
   public static synchronized ExtentTest getTest() 
{ 
  return extentTestThreadSafe.get(); 
}
public static void setTest(ExtentTest tst) 
{ 
   extentTestThreadSafe.set(tst); 
}

In the above class we are creating methods to set and get thread safe version of ExtentTest and use the same test in logging all the actions. Lets look at below code how we can make use of above two classes and do the reporting.

We initiate the logger (extent test) from test method and use setTest and getTest methods to set and access the started ExtentTest.

//this is to get the extent report created and declared in test class
public ExtentReports extent = ExtReport.getReport();
@Test 
public void login_Test_Case_01() 
{ 
try 
{ 
 ExtentTest test = extent.startTest(SheetName); 
 st = new start(); 
 ExtTest.setTest(test); 
//your testing code here you can pass the test to other page classes etc.
 } catch (Exception e) 
{ 
  ExtTest.getTest().log(LogStatus.FAIL, "unexpected error " + e.getStackTrace().toString()); e.printStackTrace(); 
} finally
{ 
 extent.flush(); 
} 
}

This way tests that are running parallel can write in parallel to the Extent-report.

Here also, there is one challenge that these tests can flush to report when ever they are done/complete/fail. so the final report might not contain tests in any particular order., but all the steps in each test will not jumble up and you see report steps for each test will be listed in the same test. Below is the example report running tests in parallel.

Report

Parallel testing and Thread Safe driver for testNG

In the recent times cicd is being the buzz word. Keeping this in mind the automation testing has been evolved to support this very need. Since after the build automation test suite need to be executed, the tests run time being the critical for whole build time. Most often because the tests run longer only prioritized tests will run in build generation cycle.

In this context its useful to know about parallel testing to reduce the turn around time. Let’s first look at parallel testing in testNg and selenium.

TestNg gives option to run parallel tests in threads. We can define how many threads we want to kick off simultaneously.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="Suite" parallel="methods" thread-count="2">
 <test name="Test" thread-count="3">
 <classes>
 <class name="com.tests.testcases"/>
 </classes>
 </test> <!-- Test -->
</suite> <!-- Suite -->

<suite name=”Suite” parallel=”methods” thread-count=”2″>

At Suite level the attribute parallel=”methods” added to run tests simultaneously.

The highlighted thread-count attribute determines how many threads testNG framework wants to kick off, these are parallel process running with different thread ids.

<test name=”Test” thread-count=”3″>

At test level also we have thread-count attribute and it is set to 3 in above example.

This means, three tests can run in parallel provided if we have enough threads.

Although you give thread-count is 2 at suite level and 3 at test level only two tests will run simultaneously, the third test will run only when first thread is freed up.

So batches of 2 tests will run until all tests completes.

The most common issue here being creating driver object which is thread-safe

And the other issue is being managing logging, as several threads trying to write to the same report. At the end we want single report for all tests.

Let us look at above mentioned two concepts. In java programming we can create driver which is thread safe with given command.

protected ThreadLocal<WebDriver> wbdriver = new ThreadLocal<WebDriver>();

ThreadLocal class in java is helpful in creating objects which are thread safe. It has get and set methods.  Following is its implementation

//chrome driver (options describe the desired capabilities for chrome driver.)
//you can just use string url instead of getting from properties file
String url = "https://google.com";
wbdriver.set(new ChromeDriver(options));
wbdriver.get().manage().window().maximize(); 
wbdriver.get().get(url);

in the above example, wbdriver holds the driver created, it is protected by ThreadLocal class for thread safety.

This way if you create driver, each test will run by its own thread. The only challenge being, the results will be hard to interpret when lot of concurrent driver processes are doing job simultaneously.

Lets discuss about synchronizing the logs with ExtentReports in next posts.

Extent report logging while parallel testing

 

 

 

Taking screen capture of Automation Element – TestStak.White

Hi There might be need where we want to take screenshot of particular automation element instead of the entire desktop or entire app.

Here is one way, that we can do that. I hare written general routine for getting the screen capture of the automation element.

public static void takeScreenShot(TestStack.White.UIItems.UIItem b)
 {
try
 {
 String path;
 Rect bounds = b.Bounds;

//getting values from Rect
 double h = bounds.Height;
 double w = bounds.Width;
 double x = bounds.X;
 double y = bounds.Y;

 //gettomg ramdom number, can change it to date time or somehting meaningful
 Random rndm = new Random();
 //this will generate randomnumber between 1 to 10,000
 int random = rndm.Next(10000);

//getting current directory
 path = System.AppDomain.CurrentDomain.BaseDirectory;
 //replaceing the bin and debug as BaseDirectory will return this
 path = path.Replace("\\bin\\Debug","");
 //creating path with random integer
 path = path + "results\\Screenshot_" + random + ".jpg";

//logic for creating
 //creating equalent in System.Drawing
 //Source point
 System.Drawing.Point p = new System.Drawing.Point(Convert.ToInt32(x), Convert.ToInt32(y));
 //Destination point
 System.Drawing.Point p2 = new System.Drawing.Point(0, 0);

//Creating Rectangle from Rect
 System.Drawing.Rectangle rect = new Rectangle(p.X, p.Y, Convert.ToInt32(w), Convert.ToInt32(h));

//Creating bitmap with desired height and width
 Bitmap bitmap = new Bitmap(rect.Width, rect.Height);

{
 Graphics g = Graphics.FromImage(bitmap);
 {
 //Coping screen where automation element is present (p) to destnation point on the image (0,0)
 g.CopyFromScreen(p, p2, rect.Size);
 }
 //Saving image
 bitmap.Save(path, ImageFormat.Jpeg);
 }
 }
 catch (Exception e)

{
 Console.WriteLine(e.Message);
 }

}
 }
}