Java Appium Automation Framework with TestNG + maven Part 1
There are many frameworks out there, but what's the benefit of using maven in your project?
a) it's a central repository to get dependencies
b) It helps maintain common structure across an organization:
Example a maven project will follow a certain structure and this structure will be consistent across the organization as maven automatically creates this structure for us when we choose to create a maven project.
C) It provides the flexibility in integrating with CI tools.
D) Plugins for test framework execution.
INSTALL MAVEN
Pre-req : You need to have java installed on your machine
For windows just download the zip you don’t need the source. Place the file in a folder example c:/maven etc and extract the folders.
C:\software_downloads\compressed_software\apache-maven-3.8.5-bin\apache-maven-3.8.5
Add this to your environment variable:
let add the bin under path
C:\software_downloads\compressed_software\apache-maven-3.8.5-bin\apache-maven-3.8.5\bin
Now lets test this out with mvn commd. Open up command window and lets type:
mvn — version.. Once you see something like this then you know you are installed and ready to go.
MAVEN TERMINOLOGY
Artifacts: An artifact is a file, usually a Jar file that gets deployed to maven repository
Groupid- Group id is used to identify your project uniquely across all projects.
archetype:generate — Generates a new project from a archetype.
Example
<! — https://mvnrepository.com/artifact/org.seleniumhq.selenium/selenium-java →
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>4.1.4</version>
</dependency>
Create Maven project:
- In Eclipse click new -> project → other → maven
Select default workspace
select maven quick start template
Now enter your group id and artifacts and continue.
now once completed, we will see the basic structure is created for us.
Now Lets start creating our test structure and test cases. For now, we will not implement the real test cases as of yet but will create the structure and test that will be replaced by real test cases.
A) Create three class AppiumTest, seleniumTest, ApiTest under your pacakge.
- Lets start with seleniumTest class and add a method so we can go though step by step what we are doing before we start with the real code.
package KhemlallAutomation.MavenJava;public class SeleniumTest {
@Test
public void BrowserAutomation()
{
}
}@Test annotation will need to add TestNG library ... hover over @Test and you will be able to get the option to add testNG library.
Add the following Dummy method that simply print out a message so we know which method is being called so that we can explain some concepts with TestNG before we dive into building the entire test framework.
APPIUMTEST.JAVA
package KhemlallAutomation.MavenJava;import org.testng.annotations.Test;public class AppiumTest {
@Test
public void NativeAppAndroid()
{
System.out.println("i am executing appium native app android");
}@Test
public void IosApp()
{
System.out.println("i am executing appium IosApp");
}}
restApiTest.java
package KhemlallAutomation.MavenJava;
import org.testng.annotations.Test;public class RestApiTest {@Test
public void PostJira()
{
System.out.println("i am executing api jira");
}
@Test
public void DeleteTwitter()
{
System.out.println("i am executing api twittwer");
}}
seleniumtest.java
package KhemlallAutomation.MavenJava;
import org.testng.annotations.Test;public class SeleniumTest {
@Test
public void BrowserAutomation()
{
System.out.println("i am executing seleniumtest BrowserAutomation");
}
@Test
public void FindElement()
{
System.out.println("i am executing seleniumtest findelement");
}}
Now lets explain some concepts. So now that we have some test cases, how do we run those test cases? First lets examine our POM.xml file. Notice we dont have our test dependencies for selenium and others. So we need to add it.
Go to maven repository (Maven Repository: org) and search for the dependency you are looking for and copy the dependency xml and paste it in your pom.xml under dependency.
Add TestNG
<!-- https://mvnrepository.com/artifact/org.testng/testng -->
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>7.6.0</version>
<scope>test</scope>
</dependency>
RestAssured
<! — https://mvnrepository.com/artifact/io.rest-assured/rest-assured →
<dependency>
<groupId>io.rest-assured</groupId>
<artifactId>rest-assured</artifactId>
<version>5.1.0</version>
<scope>test</scope>
</dependency>
So we have a plugin sure fire plugin that allow us to run our test cases. By default you will not get it with the maven project.
Maven Surefire Plugin
Maven Surefire Plugin — Introduction (apache.org)
Copy the plugin and place in your pom.xml file
maven surefire plugin
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0-M6</version>
</plugin>
</plugins>
</pluginManagement>
</build>
Note if your pom.xml already have plugin, just add your plugin under plugins:
example:
Your test cases can be executed with surefire plugin under your test folder.
NOTE: delete the appTest.java file as it is generated with maven skeleton and not needed.
MAVEN COMMAND
mvn clean — clean the projects
open command window and cd into your project folder:
cd <project folder>
Run Command mvn clean — you should
Next mvn compile — this will compile your code and if you make a mistake it will tell you if there is an issue in the code etc. Compile successful
Next Command — mvn test
Alright. Now lets Add TestNg xml file and execute that file from mvn. That xml file control what test is run etc.
Go to project -> right click -> TestNG-> convert to TestNG
Click finish and you will see the xml file created in your project folder.
How to run testng xml file from mvn.
Using Suite XML Files
Another alternative is to use TestNG suite XML files. This allows flexible configuration of the tests to be run. These files are created in the normal way, and then added to the Surefire Plugin configuration:
in your POM.XML file add this configuration in the your mvn surefire plugin section:
<configuration>
<suiteXmlFiles>
<suiteXmlFile>testng.xml</suiteXmlFile>
</suiteXmlFiles>
</configuration>
Should look something like:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0-M6</version>
<configuration>
<suiteXmlFiles>
<suiteXmlFile>testng.xml</suiteXmlFile>
</suiteXmlFiles>
</configuration>
</plugin>
Now that we included this file in our maven, when we run our test, it will run the suite based on the testng.xml file setup.
Let make a Change in our test to confirm that we are using the testng.xml file for our execution:
Lets disable one of our test with the annotation:
@Test(enabled=false)
This TestNG annotation disables this test.
mvn cleam
mvn test
Notice we now have 5 test executed.
Say you want to run a Single test and not from the xml… you can do so for example:
In our case what if we want to just run the appiumTest we will do something like this:
mvn -Dtest=AppiumTest test
You can learn more here:
Maven Surefire Plugin — Running a Single Test (apache.org)
Lets talk about PROFILES
Before we get into profiles, let setup another testng.xml file for smoke test and lets learn about smoke annotation.
right click copy and paste a new testng.xml file and name it smoke_test.xml.
Example my file:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "https://testng.org/testng-1.0.dtd">
<suite name="Suite">
<test thread-count="5" name="Test">
<groups>
<run>
<include name="smoke"></include>
</run>
</groups>
<classes>
<class name="KhemlallAutomation.MavenJava.RestApiTest"/>
<class name="KhemlallAutomation.MavenJava.SeleniumTest"/>
<class name="KhemlallAutomation.MavenJava.AppiumTest"/>
</classes>
</test> <!-- Test -->
</suite> <!-- Suite -->
Go to each of your java file and just mark one method to be smoke
IMPORTANT NOTE: When you are creating your class name in maven the convention is to end it with Test. As maven will look for those file that has the Test ending and group them as a test or else you run the risk of maven not picking your file for execution.
Example:seleniumclass
package KhemlallAutomation.MavenJava;
import org.testng.annotations.Test;public class SeleniumTest {
@Test(enabled=false)
public void BrowserAutomation()
{
System.out.println("i am executing seleniumtest BrowserAutomation");
}
@Test(groups="smoke")
public void FindElement()
{
System.out.println("i am executing seleniumtest findelement");
}}
Example: AppiumTest
import org.testng.annotations.Test;public class AppiumTest {
@Test
public void NativeAppAndroid()
{
System.out.println("i am executing appium native app android");
}@Test(groups="smoke")
public void IosApp()
{
System.out.println("i am executing appium IosApp");
}}
Example: restapi
package KhemlallAutomation.MavenJava;
import org.testng.annotations.Test;public class RestApiTest {@Test(groups="smoke")
public void PostJira()
{
System.out.println("i am executing api jira");
}
@Test
public void DeleteTwitter()
{
System.out.println("i am executing api twittwer");
}
}
Before we execute this xml through maven, let run it as a testng project.
Right click on the smoke_test.xml file and choose run as testng. When it runs you will see only three test runs
Now lets do this with MAVEN. How do you configure maven to run this test. We don’t want to go to the pom.xml file every time and change when requirement change to execute smoke vs regression test etc. Thats where Profiles comes in.
Lets create profile in your pom.xml
<profiles><profile></profile></profiles>
I will create two profiles regression or smoke test and i dentified by the ID.
<profiles>
<profile>
<id> smoke</id>
<build><pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0-M6</version>
<configuration>
<suiteXmlFiles>
<suiteXmlFile>smoke_test.xml</suiteXmlFile>
</suiteXmlFiles>
</configuration>
</plugin>
<!-- clean lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#clean_Lifecycle -->
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>3.1.0</version>
</plugin>
<!-- default lifecycle, jar packaging: see https://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_jar_packaging -->
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.1</version>
</plugin>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<artifactId>maven-install-plugin</artifactId>
<version>2.5.2</version>
</plugin>
<plugin>
<artifactId>maven-deploy-plugin</artifactId>
<version>2.8.2</version>
</plugin>
<!-- site lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#site_Lifecycle -->
<plugin>
<artifactId>maven-site-plugin</artifactId>
<version>3.7.1</version>
</plugin>
<plugin>
<artifactId>maven-project-info-reports-plugin</artifactId>
<version>3.0.0</version>
</plugin>
</plugins>
</pluginManagement>
</build>
</profile>
<profile>
<id> regression</id>
<build><pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.0.0-M6</version>
<configuration>
<suiteXmlFiles>
<suiteXmlFile>testng.xml</suiteXmlFile>
</suiteXmlFiles>
</configuration>
</plugin>
<!-- clean lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#clean_Lifecycle -->
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>3.1.0</version>
</plugin>
<!-- default lifecycle, jar packaging: see https://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_jar_packaging -->
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.1</version>
</plugin>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<artifactId>maven-install-plugin</artifactId>
<version>2.5.2</version>
</plugin>
<plugin>
<artifactId>maven-deploy-plugin</artifactId>
<version>2.8.2</version>
</plugin>
<!-- site lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#site_Lifecycle -->
<plugin>
<artifactId>maven-site-plugin</artifactId>
<version>3.7.1</version>
</plugin>
<plugin>
<artifactId>maven-project-info-reports-plugin</artifactId>
<version>3.0.0</version>
</plugin>
</plugins>
</pluginManagement>
</build>
</profile>
</profiles>
Now lets run this through maven
mvn test -Psmoke
Notice we got 3 test pass
Simlarly we can now run regression instead.
mvn test -Pregression
Notice that the two test that was marked is executed. Alright next topic i will try to dive into TestNG and how you can organize your test with TestNG annotation based on your scenario. However, lets first integrate this with Continuous Integration tool.. Jenkins.
Install CI Jenkin tool and setup your test to run
Lets go to jenkins.io and download the .war file to run locally on our machine
After download, save the file to a location of your choice. for me i place it in c:/jenkins. Navigate to that location in command prompt and give the following command:
Note you will need to have java 8 or 11 installed which is compatible.
java -jar jenkins.war
Easiest way is to run via docker. If you have docker install on your machine, then you can run jenkins with docker.
Running Jenkins with Docker
The easiest way to run Jenkins on Java 11 is with a Docker image.
To use the latest weekly release of the Java 11-based images, use the jdk11
tag. For other releases, append the -jdk11
tag to the version (for example, 2.284-jdk11
).
For example, this command starts Jenkins on Java 11 using the latest weekly release:
docker pull jenkins/jenkins:jdk11
docker run --rm -ti \
-p 8080:8080 -p 50000:50000 \
-v jenkins-home:/var/jenkins_home \
jenkins/jenkins:jdk11
Running Jenkins with Java
As with Java 8, you can start Jenkins using the java
command:
java -jar jenkins.war
Note: if you have a higher version of java installed you may have an issue as java 8 is compatiable the war file but higher version was given error in regards to compatability.
You can however install version 8 and then navigate to the java8 bin file and execute your jenkins command
C:\Program Files\Java\jdk1.8.0_333>java -jar C:\Users\kheml\jenkins\jenkins.war
You can run with Docker since if you have have it configure on your local machine.
docker run — rm -ti -p 8080:8080 -p 50000:50000 -v jenkins-home:/var/jenkins_home jenkins/jenkins:jdk11
Once its up and running, go to http://localhost:8080
In the command window it will tell you the password and where to find it.
You will then get to this page: select install suggested plugins
It will then proceed to install:
After Jenkins is up and running, we will proceed with the next step of configuring jenkins to run our dummy test in maven. Again the purpose of this is to get a framework setup and working and to get you introduce to maven and testng framework and how to set it up. We will then proceed to creating our actual selenium test etc.
you will be presented with a couple more prompts and then finally
jenkins is now Up!! Let setup our global settings.
Now we need to tell Jenkins what are all the software we need . Need maven and Java. The pom.xml has all the jar and dependencies.
- Click on Manage Jenkins → global test configuration → click on JDK → Provide your java jdk path
- Scroll down and click on Maven and set your maven home path that we set in the system environmental variable as well.
Example:
Click on new item
Enter your job name and click on freestyle project
you will be taking to the configuration screen. You can get your code from git hub or GitLab etc. Currently we have our code on our local machine and for this demo purpose we just want to demonstrate how to hook up our test framework with a cicd pipeline or continuous integration tool like Jenkins to run our code.
Click on advance -> select use custom workspace.
pre:req:
Ensure you go to your .jenkins folder location after this is installed on our local machine and add the path to our environment variable if you or on windows.
C:\Users\kheml\.jenkins
Copy over your project folder to this location
Now lets add {jenkins_home}/MavenJava
Note : you can also directly add location: C:\Users\kheml\jenkins\MavenJava — but use the env varible path. also make sure you restart your pc when ever you make enviroment variable changes.
Next scroll under build and select invoke top level maven targets.
If you had follow instruction to set global variable you should see in the drop down the maven 3.8.5 version… Simply pass in your goals or command or your test. You don’t need to pass in the mvn Command just pass test -Pregression for example.
Notes: try not to have multiple Java version configure as you may run into issue whereby you will get failure stating that your “class file has wrong version 55.0, should be 52.0” when building Alfresco” etc … Simply ensure that both your java version on your environment variable and the one you are using in your eclipse is the same.
It complains that some class files were compiled using Java 11 (which is Java 55.0 and you try to compile the rest with Java 8.
Another TIP:
Ensure that your Java version in your environment variable matches the version compile in your jenkins settings. If you are compiling different version of java then you may have a failure like this:
Ok once you have made all your settings, lets Run our Build. Go to your dashboard and click on job and click build now
As you job is building you can click on the build number and then click console output to view the progress once completed you can see the logs.
Lets talk about Page Object Pattern for our framework design.
a) Easy to maintain, Easy to read and understand, reduce redundancy, re-usability of code and realibility.
Let's Now start with a project and design the framework the way we would for production using General-store.apk file from Rahul shetty’s demo.
Our Utilities etc will be saved in our main class java and our test will be in Main class test
Create a base.java file that will contain our capabilities etc and setup. Test class java should have only our test cases.
example: C:\Users\kheml\Training\appium\MavenJava\src
a) Place your Apk file under Scr folder:
Global.properities
GeneralStoreApp=General-Store.apk
Command to Kill appium server if it gets hang
taskkill /F /M node.exe
to be continue…part 2 — This is a work in progress. Check back soon
Topics:
Passing device name in command — example: mvn test -DdeviceName=Nexus
- Create Maven Project for Framework Structure
- Build Appium Test into Project
- Implement global properiteis for appium desired capabilibties
- make the test TESTNG compatible
- Develop Page Object pattern for the test so that the object should not stay in the test cases
- Develop Appium custom utility class to avoid duplicate code
- build utility to start and stop server
- build testNg listeners
- Generate Excellent report
- Integrate with Jenkins CI tool
- Parameterized the Jenkin build
- Push framework into Git