Search This Blog

Showing posts with label Testing Framework. Show all posts
Showing posts with label Testing Framework. Show all posts

Thursday, May 12, 2022

Appium Architecture - Core Concepts

What is Appium?

It’s a NodeJS based open-source tool for automating mobile applications. It supports native, mobile web, and hybrid applications on iOS mobile, Android mobile, and Windows desktop platforms.

Using Appium, you can run automated tests on physical devices or emulators, or both.



Let’s understand the above Appium architecture diagram.

  • Appium is a client-server architecture. The Appium server communicates with the client through the HTTP JSONWire Protocol using JSON objects.
  • Once it receives the request, it creates a session and returns the session ID, which will be used for communication so that all automation actions will be performed in the context of the created session.
  • Appium uses the UIAutomator test framework to execute commands on Android devices and emulators.
  • Appium uses the XCUITest test framework to execute commands on Apple mobile devices and simulators.
  • Appium uses WinAppDriver to execute commands for Windows Desktop apps. It is bundled with Appium and does not need to be installed separately.

Appium - Android visual interaction flow

Let’s understand the interaction flow between the code and the Android device via the Appium server.

  • The client sends the request to the Appium server through the HTTP JSONWire Protocol using JSON objects.
  • Appium sends the request to UIAutomator2.
  • UIAutomator2 communicates to a real device/simulator using bootstrap.jar which acts as a TCP server.
  • bootstrap.jar executes the command on the device and sends the response back.
  • Appium server sends back the command execution response to the client.

Appium - iOS visual interaction flow

Let’s understand the interaction flow between the code and the iOS device via the Appium server.

  • The client sends the request to the Appium server through the HTTP JSONWire Protocol using JSON objects.
  • Appium sends the request to XCUITest.
  • XCUITest communicates to a real device/simulator using bootstrap.js which acts as a TCP server.
  • bootstrap.js executes the command on the device and sends the response back.
  • The Appium server sends the command execution response to the client.

Whiteboard Sessions
  • IOS flow architecture

  • Android flow architecture

  • Drivers which appium supports
    • UI Automator2 (Android)
    • Espresso (Android)
    • WinApp (Windows)
    • MAC Driver (Mac OS)
    • XCUITest (IOS above 9.3 version)
    • UI Automation (IOS below 9.3 version)
    • Tizen (for samsung)


Happy Learning :) 

Thursday, October 17, 2019

Framework Evaluation & Selection

Framework Evaluation Criteria

  1. Support automation integration testing for UI (real/headless browser/device), API,  performance in cross platforms.

    • For the integration test, we don’t test the front-end or back-end individually. We need to verify the data with the integration between system, front-end & back-end. So the framework needs to be able to support all testing type and especially crossing browser, device & system.
  2. Support CI integration with parallel execution.

    • The testing framework needs to be able to integrate with our current CI/CD. Parallel execution will help reduce the build time, so we will be able to deploy quickly and have faster turnaround times for bugs and features.
  3. Supports the concept of executable documentation for BDD (behavior-driven development)& DDT (data-driven testing) in modularization, maintainable and understandable test suites.

    • BDD will help the test case & test suite easy to maintaining and understanding. It also helps communication between business and development is extremely focused as a result of common language.
    • One of the most important concepts for effective test automation is modularization, it will help to create a sequence of test case only one and reuse as often as required in test script without rewriting the test all the time.

BDD Testing Framework Selection


GaugeCucumber
LanguageMarkdownGherkin
IDE & plugin supportYesYes
Easy to integrate with CI/CDYesYes
Easy to use, quick to learnNoNo
Reusable, easy to maintainYesYes
Parallel executionBuilt-in3rd party plugin
Customize reportingYesYes
PriceOpen source & free Open source & free 

Winner - Gauge:

  • An open source lightweight cross-platform test automation tool with the ability to author test cases in the business language and have built-in parallel execution feature.
  • Support BDD (Behavior-Driven Development) & CI(Continuous Integration) & report customization.

API Testing Framework Selection


REST AssuredPostman
Support BDDYes3rd third party
Support DDTYesLimit
Easy to integrate with CI/CDYesYes
Easy to use, quick to learnNoYes
Reusable, easy to maintainYesNo
Customize reportingCan be used with any customized/open source reporting tool.No
PriceOpen source & free 8-21$ per user/month for professional collaboration  & advanced features
  

Winner - REST Assured:

  • An open source Java-based Domain-Specific Language (DSL) that allows writing powerful, readable, and maintainable automated tests for RESTful APIs. 
  • Support testing and validating REST services in BDD (Behavior-Driven Development) / Gherkin format.

API Performance Testing Framework  Selection


Apache JMeterLoadrunner
Support DDTYesYes
Easy to integrate with CI/CDYesYes
Easy to use, quick to learnYesNo
Cross-platformYesWindows, Linux
Reusable, easy to maintainYesNo
Customize reportingYesYes
PriceOpen source & free Free for first 50 virtual User

Winner - Apache JMeter : 

  • Open source performance test runner & management framework may be used to test performance both on static and dynamic resources.
  • Support load test functional behavior and measure performance. It can be used to simulate a heavy load on a server, group of servers, network or object to test its strength or to analyze overall performance under different load types.

Test Runner & Test Suite Management Framework Selection


TestNGJUnit
Support DDTYesYes
Easy to integrate with CI/CDYesYes
Easy to use, quick to learnNoNo
Reusable, easy to maintainYesYes
Parallel executionYesYes
PriceOpen source & free Open source & free 
Annotation supportYesLimit
Suite TestYesYes
Ignore TestYesYes
Exception TestYesYes
TimeoutYesYes
Parameterized TestYesYes
Dependency TestYesNo
Support executing before & after all tests in the suiteYesNo
Support executing  before & after a test runsYesNo
Support executing  before the first & last test method
is invoked that belongs to any of these groups is invoked
YesNo

Winner - TestNG :

  • Open source test runner framework which helps to run your tests in arbitrarily big thread pools with various policies available and flexible test configuration.
  • Support DDT(Data-driven testing) & Test suite management.

Build Tool & Dependency ManagementFramework Selection


Apache MavenGrandle
Easy to integrate with CI/CDYesYes
Easy to use, quick to learnYesNo
Build Script LanguageXMLGroovy
Reusable, easy to maintainYesYes
Dependency ManagementYesYes
Dependency ScopesBuilt-inCustom
IDE & plugin supportManyA little
PriceOpen source & free Open source & free 

Winner - Apache Maven 

  • The leading open source dependency management and build tool. It standardizes the software build process by articulating a project’s constitution.
  • Software project management and comprehension tool in the concept of a project object model (POM), Maven can manage a project's build, reporting, and documentation from a central piece of information.

Monday, April 4, 2016

Passing data to DataProvider from Excel sheet

In this example we will see how to pass the data to Dataproviders by reading the data from excel sheet. DataProvider helps to send multiple sets of data to a test method. But here we need to make sure that the array returned by the dataprovider should match with the test method parameters.
We will write a simple program in which we will validate login screen by taking multiple usernames and passwords. The annotated method must return object[][] where each object[] can be assigned to the test method one as username and the other parameter as password.
Step 1: First create a method to read excel data and return string array.
Step 2: Create before class and after class methods which helps in getting the browser and closing them when done.
Step 3: Create a data provider which actually gets the values by reading the excel.
Step 4: Create a Test which takes two parameters username and password.
Step 5: Add dataprovider name for @Test method to receive data from dataprovider.
package com.pack;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

import org.testng.Assert;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;


import jxl.Sheet;
import jxl.Workbook;
import jxl.read.biff.BiffException;

public class ReadExcelDataProvider {
 public WebDriver driver;
 public WebDriverWait wait;
 String appURL = "https://www.linkedin.com/";
 
 //Locators
 private By byEmail = By.id("session_key-login");
 private By byPassword = By.id("session_password-login");
 private By bySubmit = By.id("signin");
 private By byError = By.id("global-alert-queue");
 
 @BeforeClass
 public void testSetup() {
  driver=new FirefoxDriver();
  driver.manage().window().maximize();
  wait = new WebDriverWait(driver, 5);
 }
 

 @Test(dataProvider="empLogin")
 public void VerifyInvalidLogin(String userName, String password) {
  driver.navigate().to(appURL);
  driver.findElement(byEmail).sendKeys(userName);
  driver.findElement(byPassword).sendKeys(password);
  //wait for element to be visible and perform click
  wait.until(ExpectedConditions.visibilityOfElementLocated(bySubmit));
  driver.findElement(bySubmit).click();
  
  //Check for error message
  wait.until(ExpectedConditions.presenceOfElementLocated(byError));
  String actualErrorDisplayed = driver.findElement(byError).getText();
  String requiredErrorMessage = "Please correct the marked field(s) below.";
  Assert.assertEquals(requiredErrorMessage, actualErrorDisplayed);
  
 }
 
 @DataProvider(name="empLogin")
 public Object[][] loginData() {
  Object[][] arrayObject = getExcelData("D:/sampledoc.xls","Sheet1");
  return arrayObject;
 }

 /**
  * @param File Name
  * @param Sheet Name
  * @return
  */
 public String[][] getExcelData(String fileName, String sheetName) {
  String[][] arrayExcelData = null;
  try {
   FileInputStream fs = new FileInputStream(fileName);
   Workbook wb = Workbook.getWorkbook(fs);
   Sheet sh = wb.getSheet(sheetName);

   int totalNoOfCols = sh.getColumns();
   int totalNoOfRows = sh.getRows();
   
   arrayExcelData = new String[totalNoOfRows-1][totalNoOfCols];
   
   for (int i= 1 ; i < totalNoOfRows; i++) {

    for (int j=0; j < totalNoOfCols; j++) {
     arrayExcelData[i-1][j] = sh.getCell(j, i).getContents();
    }

   }
  } catch (FileNotFoundException e) {
   e.printStackTrace();
  } catch (IOException e) {
   e.printStackTrace();
   e.printStackTrace();
  } catch (BiffException e) {
   e.printStackTrace();
  }
  return arrayExcelData;
 }

 @Test
 public void tearDown() {
  driver.quit();
 }
}
After clicking on login button, we are using WebdriverWaits to Check for error message and validate.
The output should look like below:
[TestNG] Running:
  C:\Users\easy\AppData\Local\Temp\testng-eclipse-583753747\testng-customsuite.xml

PASSED: VerifyInvalidLogin("testuser1", "testpassword1")
PASSED: VerifyInvalidLogin("testuser2", "testpassword2")
PASSED: VerifyInvalidLogin("testuser3", "testpassword3")
PASSED: VerifyInvalidLogin("testuser4", "testpassword4")
PASSED: VerifyInvalidLogin("testuser5", "testpassword5")

===============================================
    Default test
    Tests run: 5, Failures: 0, Skips: 0
===============================================


===============================================
Default suite
Total tests run: 5, Failures: 0, Skips: 0
===============================================

DataProvider in TestNG

Marks a method as supplying data for a test method. The annotated method must return an Object[][] where each Object[] can be assigned the parameter list of the test method.
The @Test method that wants to receive data from this DataProvider needs to use a dataProvider name equals to the name of this annotation.
The name of this data provider. If it's not supplied, the name of this data provider will automatically be set to the name of the method.
In the below example we will pass the data from getData() method to data provider. We will send 3 rows and 2 columns ie. we will pass three different usernames and passwords.
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;

public class DataProviderExample{
 
 //This test method declares that its data should be supplied by the Data Provider
 // "getdata" is the function name which is passing the data
       // Number of columns should match the number of input parameters
 @Test(dataProvider="getData")
 public void setData(String username, String password)
 {
  System.out.println("you have provided username as::"+username);
  System.out.println("you have provided password as::"+password);
 }

 @DataProvider
 public Object[][] getData()
 {
 //Rows - Number of times your test has to be repeated.
 //Columns - Number of parameters in test data.
 Object[][] data = new Object[3][2];

 // 1st row
 data[0][0] ="sampleuser1";
 data[0][1] = "abcdef";

 // 2nd row
 data[1][0] ="testuser2";
 data[1][1] = "zxcvb";
 
 // 3rd row
 data[2][0] ="guestuser3";
 data[2][1] = "pass123";

 return data;
 }
}
When we execute the above example, we will the get the output as below:
Each data set that we pass will be considered as a test method. As we passed three set of data to the data provider, it will display result as below:
Default suite
Total tests run: 3, Failures: 0, Skips: 0
Output of the Above Program
you have provided username as::sampleuser1
you have provided password as::sampleuser1
you have provided username as::testuser2
you have provided password as::testuser2
you have provided username as::guestuser3
you have provided password as::guestuser3
PASSED: testdata("sampleuser1", "abcdef")
PASSED: testdata("testuser2", "zxcvb")
PASSED: testdata("guestuser3", "password123")

Tuesday, June 30, 2015

Some interesting Java Facts

Creation of an Object:

Following steps are completed while creating a new object of any class :-
1. Bind Constructor parameters.
2. If explicit this(),call recursively and skip to step 5.
3. Call recursively the implicit and explicit super(...),except for their Object class
because it has no parent class.
4. Execute the explicit instance variable initializers. // it refers to initialisation of instance variables at the time of their declaration.
5.  Execute the body of the current constructor.

Exceptions

1.finally clause is always executed regardless of the fact that exception is caused or not.
2.only way that finally will not be executed is virtual machine shutdown or execution of "System.exit(0)" method.
3.If return statement is embedded inside the try block then finally clause executes before return.
4. Exception must be thrown in same line where its object is created because it contains line no. information.

Accessing Members of "super base" Class

Suppose class B extends class A and class C further extends class B.
Now Suppose we want to access the members of class A directly through C class.
This can be either accomplished by using super twice once in C and once in B.
Or other way is to use super in Class C and if members with same name are not
present in B then this super will directly refer to member in super base class A.
example of a such a program.

class A
{
 static
 {
  System.out.println("static initializer of A");
 }
 {
  System.out.println("initializer of A");
 }
 A()
 {
  System.out.println("Constructor class A");
 }
 A(int a)
 {
  System.out.println("Constructor class A parameter");
 }
 void hello()
 {
  System.out.println("Hello in c");
 }
 void quality()
 {
  System.out.println("Quality Method Class A");
 }
}
class B extends A
{
 static
 {
  System.out.println("static initializer of B");
 }
 {
  System.out.println("initializer of B");
 }
 B()
 {
  System.out.println("Constructor class B");
 }
 B(int b)
 {
  System.out.println("Constructor class B parameter");
 }
 void show()
 {
  System.out.println("I m in class B");
 }
}
class C extends B
{
 static
 {
  System.out.println("static initializer of C");
 }
 {
  System.out.println("initializer of C");
 }
 C()
 {
  System.out.println("Constructor class C");
 }
 C(int c)
 {
  //super.show();
  System.out.println("Constructor class C parameter");
 }
 void show()
 {
  System.out.println("I m in class C");
 }
 void quality()
 {
  super.quality();
  System.out.println("Quality Method Class C");
 }
}
public class inh
{
 public static void main(String ...args)
 {
  A a=new C(3);
  a.quality();
 }
}

Polymorphic Arguments in Polymorphism

Suppose a method in a class uses reference of some base class as its argument to perform certain calculations. Now it can also intake the object of child class as its argument because child is also a type of base class object. Bu important point is that this method can only access the members of parent class and not child specific features.

Referring members of a base class in Polymorphism

If we create reference of base class then we can access child class methods which are overridden but child class specific methods are not accessible as accomplished by following program:
class base
{
 base()
 {
  System.out.println("base class");
 }
 void show()
 {
  System.out.println("Show method base class");
 }
}
class child extends base
{
 child()
 {
  System.out.println("child class");
 }
 void show()
 {
  System.out.println("Show method child class");
 }
 void specific()
 {
  System.out.println("Specific Method of Child class not present in base");
 }
 public static void main(String args[])
 {
  base b=new child();
  b.specific();//illegal will not compile
  b.show();//child class method executes
 }
}

Encapsulation

Encapsulation is one of the four fundamental OOP concepts. 
Grouping functions and corresponding data into a single capsule is called Encapsulation
Encapsulation is the technique of making the fields in a class private and providing access to the fields via public methods. If a field is declared private, it cannot be accessed by anyone outside the class, thereby hiding the fields within the class. For this reason, encapsulation is also referred to as data hiding.
Encapsulation can be described as a protective barrier that prevents the code and data being randomly accessed by other code defined outside the class. Access to the data and code is tightly controlled by an interface.
The main benefit of encapsulation is the ability to modify our implemented code without breaking the code of others who use our code. With this feature Encapsulation gives maintainability, flexibility and extensibility to our code.

Encapsulation =Datahiding + Abstraction

Example:

Let us look at an example that depicts encapsulation:
/* File name : EncapTest.java */
public class EncapTest{

   private String name;
   private String idNum;
   private int age;

   public int getAge(){
      return age;
   }

   public String getName(){
      return name;
   }

   public String getIdNum(){
      return idNum;
   }

   public void setAge( int newAge){
      age = newAge;
   }

   public void setName(String newName){
      name = newName;
   }

   public void setIdNum( String newId){
      idNum = newId;
   }
}
The public methods are the access points to this class's fields from the outside java world. Normally these methods are referred as getters and setters. Therefore any class that wants to access the variables should access them through these getters and setters.
The variables of the EncapTest class can be access as below::
/* File name : RunEncap.java */
public class RunEncap{

   public static void main(String args[]){
      EncapTest encap = new EncapTest();
      encap.setName("James");
      encap.setAge(20);
      encap.setIdNum("12343ms");

      System.out.print("Name : " + encap.getName()+ 
                             " Age : "+ encap.getAge());
    }
}
This would produce following result:
Name : James Age : 20

Benefits of Encapsulation:

  • The fields of a class can be made read-only or write-only.
  • A class can have total control over what is stored in its fields.
  • The users of a class do not know how the class stores its data. A class can change the data type of a field, and users of the class do not need to change any of their code.

All TestNG annotations with attributes

@BeforeSuite


@AfterSuite


@BeforeTest

@AfterTest


@BeforeGroups


@AfterGroups


@BeforeClass

@AfterClass

@BeforeMethod
@AfterMethod
Configuration information for a TestNG class:

@BeforeSuite: The annotated method will be run before all tests in this suite have run.
@AfterSuite: The annotated method will be run after all tests in this suite have run.
@BeforeTest: The annotated method will be run before any test method belonging to the classes inside the tag is run.
@AfterTest: The annotated method will be run after all the test methods belonging to the classes inside the tag have run.
@BeforeGroups: The list of groups that this configuration method will run before. This method is guaranteed to run shortly before the first test method that belongs to any of these groups is invoked.
@AfterGroups: The list of groups that this configuration method will run after. This method is guaranteed to run shortly after the last test method that belongs to any of these groups is invoked.
@BeforeClass: The annotated method will be run before the first test method in the current class is invoked.
@AfterClass: The annotated method will be run after all the test methods in the current class have been run.
@BeforeMethod: The annotated method will be run before each test method.
@AfterMethod: The annotated method will be run after each test method.

alwaysRun
For before methods (beforeSuite, beforeTest, beforeTestClass and beforeTestMethod, but not beforeGroups): If set to true, this configuration method will be run regardless of what groups it belongs to.
For after methods (afterSuite, afterClass, ...): If set to true, this configuration method will be run even if one or more methods invoked previously failed or was skipped.

dependsOnGroups
The list of groups this method depends on.

dependsOnMethods
The list of methods this method depends on.

enabled
Whether methods on this class/method are enabled.

groups
The list of groups this class/method belongs to.

inheritGroups
If true, this method will belong to groups specified in the @Test annotation at the class level.

@DataProvider
Marks a method as supplying data for a test method. The annotated method must return an Object[][] where each Object[] can be assigned the parameter list of the test method. The @Test method that wants to receive data from this DataProvider needs to use a dataProvider name equals to the name of this annotation.

name
The name of this data provider. If it's not supplied, the name of this data provider will automatically be set to the name of the method.

parallel
If set to true, tests generated using this data provider are run in parallel. Default value is false.

@Factory
Marks a method as a factory that returns objects that will be used by TestNG as Test classes. The method must return Object[].

@Listeners
Defines listeners on a test class.

value
An array of classes that extend org.testng.ITestNGListener.

@Parameters
Describes how to pass parameters to a @Test method.

value
The list of variables used to fill the parameters of this method.

@Test
Marks a class or a method as part of the test.

alwaysRun
If set to true, this test method will always be run even if it depends on a method that failed.

dataProvider
The name of the data provider for this test method.

dataProviderClass
The class where to look for the data provider. If not specified, the data provider will be looked on the class of the current test method or one of its base classes. If this attribute is specified, the data provider method needs to be static on the specified class.

dependsOnGroups
The list of groups this method depends on.

dependsOnMethods
The list of methods this method depends on.

description
The description for this method.

enabled
Whether methods on this class/method are enabled.

expectedExceptions
The list of exceptions that a test method is expected to throw. If no exception or a different than one on this list is thrown, this test will be marked a failure.

groups
The list of groups this class/method belongs to.

invocationCount
The number of times this method should be invoked.

invocationTimeOut
The maximum number of milliseconds this test should take for the cumulated time of all the invocationcounts. This attribute will be ignored if invocationCount is not specified.

priority
The priority for this test method. Lower priorities will be scheduled first.

successPercentage
The percentage of success expected from this method

singleThreaded
If set to true, all the methods on this test class are guaranteed to run in the same thread, even if the tests are currently being run with parallel="methods". This attribute can only be used at the class level and it will be ignored if used at the method level. Note: this attribute used to be called sequential (now deprecated).

timeOut
The maximum number of milliseconds this test should take.

threadPoolSize
The size of the thread pool for this method. The method will be invoked from multiple threads as specified by invocationCount.
Note: this attribute is ignored if invocationCount is not specified

My Profile

My photo
can be reached at 09916017317