Where we learn technology

Day: 11 May 2020

Steps to Configure Maven Profile with Maven Project

Let us see how to configure Maven Profile for a Maven Project.

What is a Maven Profile..??                                                               

It is a feature that can be defined in a pom.xml file which allows developers and testers to configure and customize builds based on requirement. 

What is the advantage of implementing Maven Profile in our Automation Projects..??                                                                 

As shown below, In real time we generally maintain different testng.xml files in frameworks that are designed either for Web Applications, Backend APIs or Mobile Applications like Smoke Suite, Regression Suite, Sanity Suite etc. for executing test cases based on requirement.             

Based on business requirement, we will be required to execute testng.xml files from Eclipse IDE, Command Prompt or from Jenkins etc.

In general, if we do not use Maven Profiling. Each time when we need to execute testng.xml file. We need to go to pom.xml file and change the name of testng.xml inside Maven Surefire Plugin which needs to be executed and that is a very tedious task to do every time.  Now the question is, how can we avoid changing testng.xml file name in pom.xml every time. when we need to execute test suite.

Now let us see configuring Maven Profile with Maven Project.

1. Project should be a Maven Project. 

2. Maven Jar files should be downloaded and path must be set for the same in Environment Variables and ensure that you are able to execute Maven Project from Command Line prompt before implementing Maven Profile. 

Refer below blog with respect to above points to Install Maven Jars and to execute Maven Project from Command Prompt:  http://naveenautomationlabs.com/executing-maven-project-in-windows-from-command-prompt/

Below is Maven Surefire Plugin where we mention which testng.xml file needs to be executed from project.

Code for Maven Surefire Plugin:                                                     

<build>
 <pluginManagement>
 <plugins>
 <plugin>
 <groupId>org.apache.maven.plugins</groupId>
 <artifactId>maven-surefire-plugin</artifactId>
 <version>2.18.1</version>
 <configuration>
 <suiteXmlFiles>
 <suiteXmlFile>src/main/resources/testng_smoke.xml</suiteXmlFile>
 </suiteXmlFiles>
 </configuration>
 </plugin>
 </plugins>
 </pluginManagement>
 </build>

Now, let us see how can we build Maven Profile using Maven Surefire Plugin.

We can build Maven Profile for each testng.xml file in pom.xml as shown below, for each Maven Profile we can give Id/Name as highlighted in below screenshot.

All we need to add is followed tags with Maven Surefire Plugin <profiles> </profiles>, <profile> </profile> and <id> </id>.

All we need to do is that providing Id/Name for each Profile. For example, if we have multiple testng.xml files like Smoke, Sanity and Regression then we can build 3 Maven Profiles.       

One-One Profile for each suite, so that we can avoid changing testng.xml file name inside Maven Surefire Plugin whenever we need to execute test suite.

In my case, I have 2 testng.xml files. One is for Smoke and other one is for Regression.

You can refer below screenshots for giving Maven Profile Names for Test Suites.

Note: Profile Name should always be written inside <id> tag.

Refer below pom.xml to build Maven Profile for each testng.xml file.    https://github.com/PavanReddy77/MavenSurefirePlugin/blob/master/pom.xml

Once Maven Profiles are built for all testng.xml files then we are good to execute from Command Prompt or from Jenkins.

Maven Commands to be followed when executing testng.xml files. 

mvn test –P followed by Maven Profile Id like below:

mvn test –PSmoke     

mvn test –PRegression

Well, we are now good to execute our testng.xml file based on our requirement.

Refer below repository for implementing Maven Surefire Plugin and Maven Profile.  

https://github.com/PavanReddy77/MavenSurefirePlugin

Conclusion: In this blog, we have seen implementing Maven Surefire Plugin and Maven Profile in a Maven Project.

Blog Contributors:

Author:  Pavan K

Pavan, having good knowledge in Selenium Web UI and API Automation frameworks. Also, he is helping QA community with his knowledge along with Naveen AutomationLabs!!

LinkedIn

Reviewer: Naveen Khunteta 

https://www.linkedin.com/in/naveenkhunteta

10. How to create a Mobile automation framework that supports both Android and iOS?

In previous blog, We created a method in our parent class to declare our driver as “AndroidDriver”. Here comes another scenario, suppose I need to automate both iOS and Android application using the same framework.  

 

Is it possible?, How can I do this ?

Please read the blog carefully, this is little tricky in term of understanding the driver, but very easy to implement

How to create a Mobile automation framework supports both Android and iOS?

Nowadays it is common that, most of the applications are being developed for both Android and iOS. So when creating a test framework we need to think and create a flexible and reliable framework for supporting both the applications.

One good thing is that for most of the applications, user flow/architecture will not change based on the Operating system. For example, if you take any application which supports both Android/iOS like “RedBus” or “Linkedin”, you can see that the screens and UI will be same for both OS. May be the look and feel of UI’s can change depends on the SDK’s like XCode/Android studio.

Quick Tip: I suggest you to take a look of few softwares like Xamrin and ReactNative. These softwares are used to create a unique code which executes in both iOS and Android with the help of inbuild SDK libraries.    

Being said that, screens and UI’s are same for both the apps, Our job is now easy to create class and maintain using POM for each screens. Because we can create a single .java file with elements supporting for both iOS and Android. For example,

By android_login_button = By.id("login");
By ios_login_button = By.id("XCUIlogin");

or
AndroidElement button_Login_android = (AndroidElement) driver.findElement(By.id("Login_button"));

IOSElement button_Login ios = (IOSElement) driver.findElement(By.id("XCUIlogin"));

The above example is just for your understanding. We should not create or initiate any elements like this in framework. Do you know why?

Because, consider a page having 50 elements, so we need to declare 50 variables for android and 50 variables for iOS. In total we declared 100 variables in a single java file. Do you think it is easy to manage like this? Also think about the amount of memory we are consuming because of these variables.

So to create a flexible and easily manageable framework we have lot of existing stuffs to declare our variables. For example we can use @FindBy annotations, for example,

@AndroidFindBy(id = "Login")
@iOSXCUITFindBy(id = "XCUILogin")
MobileElement login_Button;

By using @FindBy we can create a common variable for both OS. Remember, “Login_Button” variable is now common for both Android and IOS,

driver instance will automatically detects the identifier based on OS,

If, driver is an AndroidDriver then it will consider @AndroidFindBy.

If driver is IOSDriver, then it will consider @XCUITFindBy.

Did you notice?, “Login_Button” variable is declared as a type “MobileElement”, so in our code no need to use “driver.findElement” or “By” class to declare/identify the UI.

We can directly perform element operations like .click(), .sendKeys() and all other conditions[same like WebElement], For example,

Boolean visible = login_button.isDisplayed();
login_button.click();
String button_text = login_button.getText();

Always remember, Coding is not only about writing and executing the code, we need to give priority for “Best practices” like code Optimization, Memory optimization, lesser LOC etc…  

 

How to Implement and declare driver in our Class?

Now, we are going to see how to create a method in “TestEngine.java” file that handles condition and supports for both iOS and Android.

As I already said, AppiumDriver<?> is a parent class for  “AndroidDriver” and “iOSDriver”. So to make our driver to support both OS, we need to declare our driver as AppiumDriver.

// Initiating Appium Driver
	public static AppiumDriver<?> driver;

Okay, our driver is now “AppiumDriver”, how to assign the “Android” or “iOS” driver to our Appiumdriver?

//driver As an AndroidDriver
driver = new AndroidDriver<AndroidElement>(new URL("http://127.0.0.1:4723/wd/hub"), capabilities);

//driver As an IOSDriver
driver = new IOSDriver<IOSElement>(new URL("http://127.0.0.1:4723/wd/hub"), capabilities); 

Our driver is now compatible to handle both OS. Still confused? Please find sample code below,

package invoiceapp.base;

import java.net.URL;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.testng.annotations.BeforeMethod;
import io.appium.java_client.AppiumDriver;
import io.appium.java_client.android.AndroidDriver;
import io.appium.java_client.android.AndroidElement;
import io.appium.java_client.ios.IOSDriver;
import io.appium.java_client.ios.IOSElement;
import io.appium.java_client.remote.AutomationName;
import io.appium.java_client.remote.MobileCapabilityType;

public class OS {
	public static AppiumDriver<?> driver;
	
	@BeforeMethod
	public static void startTest(String platform) {
		if(platform.equalsIgnoreCase("Android")) {
			driver = startAppium_Android();
		} else {
			driver = startAppium_IOS();
		}
		}
	
	/*
	 * This method is used for initiate the AppiumDriver with caps and connection protocol
	 */
	public static AndroidDriver<?> startAppium_Android() {
		// Initializing the Appium driver
		try {
			DesiredCapabilities cap = new DesiredCapabilities();
			cap.setCapability(MobileCapabilityType.PLATFORM_NAME, "Android");
			cap.setCapability(MobileCapabilityType.PLATFORM_VERSION, "9");
			cap.setCapability(MobileCapabilityType.DEVICE_NAME, "5642c6b9");
			cap.setCapability("appActivity", "com.invoiceapp.InvoiceLaunchScreenAct");
			cap.setCapability("appPackage", "com.invoiceapp");
			cap.setCapability("autoLaunch", false);
			cap.setCapability(MobileCapabilityType.NEW_COMMAND_TIMEOUT, 500);
			cap.setCapability(MobileCapabilityType.AUTOMATION_NAME, AutomationName.ANDROID_UIAUTOMATOR2);
// driver is declared as an AndroidDriver, which supports AndroidElements
			driver = new AndroidDriver<AndroidElement>(new URL("http://127.0.0.1:4723/wd/hub"), cap);
		} catch (Exception e) {
			e.printStackTrace();
		}	
		//Returning the instance of the driver to the parent method
		return (AndroidDriver<?>) driver;
	}
	
	/*
	 * This method is used for initiate the IOSDriver with caps and connection protocol
	 */
	public static IOSDriver<?> startAppium_IOS() {
		// Initializing the Appium driver
		try {
			DesiredCapabilities cap = new DesiredCapabilities();
			cap.setCapability(MobileCapabilityType.PLATFORM_NAME, "iOS");
			cap.setCapability(MobileCapabilityType.PLATFORM_VERSION, "12.0.1");
			cap.setCapability(MobileCapabilityType.DEVICE_NAME, "iPhone 8");
			cap.setCapability(MobileCapabilityType.UDID, "3jtn3j4n3ijn3ji4nrj34inrj34nr34nrk");
			cap.setCapability("bundleId", "com.invoiceapp");
			cap.setCapability("autoLaunch", false);
			cap.setCapability(MobileCapabilityType.AUTOMATION_NAME, AutomationName.IOS_XCUI_TEST);
// driver is declared as an IOSDriver, which supports IOSElements
			driver = new IOSDriver<IOSElement>(new URL("http://127.0.0.1:4723/wd/hub"), cap);
		} catch (Exception e) {
			e.printStackTrace();
		}	
		//Returning the instance of the driver to the parent method
		return (IOSDriver<?>) driver;
	}	
}

Note: This is just an example for understanding how to declare both the drivers in same class. Again, in lot of ways we can declare and initiate the drivers. In upcoming blog’s, I will defiantly let you know how to implement this in our “TestEngine.java” file and pass the “platform” parameter from TestNG xml file.

Points to Remember:

  1. We can run both the drivers under same Host but not under same PROXY. Proxy should be unique for both the drivers.
  2. Executing IOS application using Windows machine is not possible, I will share the code for both the drivers, you can check IOS if you have Mac machine
  3. By getting and using the driver instance, we can run both iOS and Android in parallel. I will share the code in future blogs.

 

I’m very excited to create POM. Hope you too, follow us and stay focused…

 

I will commit the codes discussed here in my Github repo. You can clone it and start modifying as per your idea. 

 

 

https://github.com/Karthickragu/Appium_Blog

 

Cheers!

Naveen AutomationLab

Blog Contributors:

Author:  Ragavendran

Ragav, having 10+ years of testing experience on which 7 years of rich experience in automation using UFT, Selenium (Java/Python). Expertise in Web and Mobile automation testing using Appium.

https://www.linkedin.com/in/Ragavendran-Ragav

Reviewer: Naveen Khunteta 

https://www.linkedin.com/in/naveenkhunteta