Wednesday, August 28, 2019

How to Create POM framework for Mobile Automation using Appium | Page Object Model Framework for Appium




In this post, I’m going to explain how to create POM framework for mobile automation. Basically, POM framework means, it separates locators and test scripts.

In our project we will be having many objects, if any changes to page element, we need to go to all the pages and need to update the locator in all the pages, that will consume lot of effort. Think if changes happened frequently most of the effort will go in fixing the element locators.

 If you use POM pattern, for each page we create one page for maintaining and storing elements and respective methods for that page separately, by doing this whenever changes happened we just need to go to respective page update the changes instead of going for all the scripts and updating.

And it will be easy to know from where and which page this locator is referring if we use POM model.


Lets start,

Prerequisites:

1. Appium setup should be completed. In case you are new , please follow these steps to do "Appium setup"

Steps:

1. Create maven project. In case you are new to maven project creation follow this post How to create maven project for automation

2. Post maven project creation, project structure should like below:








3. Open the “pom.xml” file add the below maven dependencies:

Appium & TestNg dependency:
 <dependencies>
               
                         <dependency>
                                    <groupId>io.appium</groupId>
                                    <artifactId>java-client</artifactId>
                                    <version>7.0.0</version>
                        </dependency>

                         <dependency>
                                    <groupId>org.testng</groupId>
                                    <artifactId>testng</artifactId>
                                    <version>6.9.13.6</version>
                        </dependency>
            </dependencies>
              


4. Now POM looks like below:


<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>Appium</groupId>
  <artifactId>POMframework</artifactId>
  <version>0.0.1-SNAPSHOT</version>
 
           <dependencies>
                       <dependency>
                                    <groupId>io.appium</groupId>
                                    <artifactId>java-client</artifactId>
                                    <version>7.0.0</version>
                        </dependency>

                        <dependency>
                                    <groupId>org.testng</groupId>
                                    <artifactId>testng</artifactId>
                                    <version>6.9.13.6</version>
                        </dependency>
            </dependencies>
 
</project>


5. Create “baseClass” package: right click on your project and select NewPackage and give name as “baseClass” and click on finish.


6. Then right click on “baseClass” package and select New -> Class and name as “BaseClass.java” .


7. After this step project structure should look like below:







8. Open “BaseClass.java” and add the below code:



package baseClass;

import java.net.MalformedURLException;
import java.net.URL;
import java.util.concurrent.TimeUnit;

import org.openqa.selenium.remote.DesiredCapabilities;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Parameters;

import io.appium.java_client.AppiumDriver;
import io.appium.java_client.MobileElement;

public class BaseClass {

            public static AppiumDriver<MobileElement> driver;
            @BeforeTest
            @Parameters({"deviceName","udid", "platformVersion","url"})
            public void setup(String deviceName, String udid,String platformVersion,String url) throws InterruptedException, MalformedURLException
            {
                        DesiredCapabilities cap=new DesiredCapabilities();
                cap.setCapability("deviceName", deviceName);
                cap.setCapability("udid", udid);
                cap.setCapability("appActivity", "com.android.calculator2.Calculator");
                cap.setCapability("appPackage", "com.android.calculator2");
                cap.setCapability("platformName", "Android");
                cap.setCapability("platformVersion", platformVersion);
                driver=new AppiumDriver<MobileElement>(new URL(url), cap);
                driver.manage().timeouts().implicitlyWait(15, TimeUnit.SECONDS);
                Thread.sleep(5000);
              
            }

}

9. Create “pages” package: right click on your project and select NewPackage and give name as “pages” and click on finish.

10. Then right click on “pages” package and select New -> Class and name as “BasePOMpage.java” .

11. After adding above step, project structure should look like below:




12. Open “BasePOMpage.java” and add below code and save it:



package pages;

import org.openqa.selenium.support.PageFactory;

import io.appium.java_client.AppiumDriver;
import io.appium.java_client.MobileElement;
import io.appium.java_client.pagefactory.AppiumFieldDecorator;

public class BasePOMpage {

public AppiumDriver<MobileElement> driver;
   
    public BasePOMpage(AppiumDriver<MobileElement> driver) {
        this.driver = driver;
        PageFactory.initElements(new AppiumFieldDecorator(driver), this);
    }
   
}


13. Then right click on “pages” package and select New -> Class and name as “CalculatorScreen.java” .




14. After this step project structure looks like below:




15. Open “CalculatorScreen.java” and add below code and save it:

package pages;

import io.appium.java_client.AppiumDriver;
import io.appium.java_client.MobileElement;
import io.appium.java_client.android.AndroidElement;
import io.appium.java_client.pagefactory.AndroidFindBy;


public class CalculatorScreen  extends BasePOMpage{
           


            @AndroidFindBy(id = "com.android.calculator2:id/digit_1")
    private AndroidElement button1;
   
    @AndroidFindBy(id = "com.android.calculator2:id/digit_2")
    private AndroidElement button2;
   
    @AndroidFindBy(id = "com.android.calculator2:id/digit_3")
    private AndroidElement button3;
   
    @AndroidFindBy(id = "com.android.calculator2:id/digit_4")
    private AndroidElement button4;
   
    @AndroidFindBy(id = "com.android.calculator2:id/digit_5")
    private AndroidElement button5;
   
    @AndroidFindBy(id = "com.android.calculator2:id/digit_6")
    private AndroidElement button6;
   
    @AndroidFindBy(id = "com.android.calculator2:id/digit_7")
    private AndroidElement button7;
   
    @AndroidFindBy(id = "com.android.calculator2:id/digit_8")
    private AndroidElement button8;
    
    @AndroidFindBy(id = "com.android.calculator2:id/digit_9")
    private AndroidElement button9;
   
    @AndroidFindBy(id = "com.android.calculator2:id/digit_0")
    private AndroidElement button0;
   
    @AndroidFindBy(id = "com.android.calculator2:id/op_add")
    private AndroidElement buttonPlus;
   
    @AndroidFindBy(id = "com.android.calculator2:id/eq")
    private AndroidElement buttonEqual;

    public CalculatorScreen(AppiumDriver<MobileElement> driver) {
        super(driver);
    }
   
    public void clickButton_1()
    {
     
            button1.click();
    }
   
    public void clickButton_2()
    {
     
            button2.click();
    }
   
    public void clickPlusButton()
    {
            buttonPlus.click();
    }
}


16. Create “testScripts” package: right click on your project and select NewPackage and give name as testScriptsand click on finish.

17. Then right click on “testScripts” package and select “New -> Class and name as “TestScript1.java” .


18. After this step project structure looks like below:



19. Open “TestScript1.java” and add below code and save it:



package testScripts;

import org.testng.annotations.Test;

import baseClass.BaseClass;
import pages.CalculatorScreen;

public class TestScript1 extends BaseClass {

            @Test
            public void setup() throws InterruptedException {

                        CalculatorScreen cs = new CalculatorScreen(driver);
                        cs.clickButton_1();
                        cs.clickPlusButton();
                        cs.clickButton_2();
                        Thread.sleep(5000);
                       
            }
}

20. Right click on your project and select NewFile and name it as “testing.xml” and click on Finish





21. Add the below code in testing.xml file.



<suite name="parallel">
            <test name="Device-1">
             <parameter name="deviceName" value="emulator-5554" />
             <parameter name="udid" value="emulator-5554" />
             <parameter name="platformVersion" value="9.0" />
             <parameter name="url" value="http://0.0.0.0:4723/wd/hub" />

                        <classes>
                                    <class name="testScripts.TestScript1"/>   
                        </classes>
            </test>
</suite>
22. Now your project structure looks like below:





23. Execution Output:



24. Console output:

[TestNGContentHandler] [WARN] It is strongly recommended to add "<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >" at the top of your file, otherwise TestNG may fail or not work as expected.
[TestNG] Running:
  D:\tutorialsWorkSpace\POMframework\testng.xml

Aug 28, 2019 4:16:42 PM io.appium.java_client.remote.AppiumCommandExecutor$1 lambda$0
INFO: Detected dialect: W3C

===============================================
Total tests run: 1, Failures: 0, Skips: 0
===============================================



25. TestNg output:




26. To Run from pom.xml file add the below plugins into your pom.xml file:


<build>
                        <plugins>
                                    <!-- Compiler plug-in -->
                                    <plugin>
                                                <groupId>org.apache.maven.plugins</groupId>
                                                <artifactId>maven-compiler-plugin</artifactId>
                                                <configuration>
                                                            <source>${jdk.level}</source>
                                                            <target>${jdk.level}</target>
                                                </configuration>
                                    </plugin>
                                    <!-- Below plug-in is used to execute tests -->
                                    <plugin>
                                                <groupId>org.apache.maven.plugins</groupId>
                                                <artifactId>maven-surefire-plugin</artifactId>
                                                <version>2.18.1</version>
                                                <configuration>
                                                            <suiteXmlFiles>
                                                                        <!-- TestNG suite XML files -->
                                                                        <suiteXmlFile>testng.xml</suiteXmlFile>
                                                            </suiteXmlFiles>
                                                </configuration>
                                    </plugin>
                        </plugins>
            </build>

27. Finally your pom.xml file looks like below, it will be good if you replace your pom.xml file with below code in case if you are new to maven:


<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>Appium</groupId>
  <artifactId>POMframework</artifactId>
  <version>0.0.1-SNAPSHOT</version>
 
  <name>POMframework</name>
  <url>http://maven.apache.org</url>

  <properties>
                        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
            </properties>

            <repositories>
                        <repository>
                                    <id>spring-releases</id>
                                    <name>Spring Releases</name>
                                    <url>https://repo.spring.io/libs-release</url>
                        </repository>
            </repositories>
            <pluginRepositories>
                        <pluginRepository>
                                    <id>spring-releases</id>
                                    <name>Spring Releases</name>
                                    <url>https://repo.spring.io/libs-release</url>
                        </pluginRepository>
            </pluginRepositories>
            <dependencies>


                        <dependency>
                                    <groupId>junit</groupId>
                                    <artifactId>junit</artifactId>
                                    <version>3.8.1</version>
                                    <scope>test</scope>
                        </dependency>

                        <dependency>
                                    <groupId>io.appium</groupId>
                                    <artifactId>java-client</artifactId>
                                    <version>7.0.0</version>
                        </dependency>

                        <dependency>
                                    <groupId>org.testng</groupId>
                                    <artifactId>testng</artifactId>
                                    <version>6.9.13.6</version>
                        </dependency>
                        <dependency>
                                    <groupId>org.apache.commons</groupId>
                                    <artifactId>commons-math3</artifactId>
                                    <version>3.2</version>
                        </dependency>

                        <dependency>
                                    <groupId>org.springframework</groupId>
                                    <artifactId>spring-tx</artifactId>
                                    <version>3.2.2.RELEASE</version>
                        </dependency>
                        <dependency>
                                    <groupId>org.springframework</groupId>
                                    <artifactId>spring-orm</artifactId>
                                    <version>3.2.2.RELEASE</version>
                        </dependency>

                        <dependency>
                                    <groupId>commons-lang</groupId>
                                    <artifactId>commons-lang</artifactId>
                                    <version>2.6</version>
                        </dependency>

                        <dependency>
                                    <groupId>org.apache.commons</groupId>
                                    <artifactId>commons-lang3</artifactId>
                                    <version>3.1</version>
                        </dependency>

            </dependencies>

<build>
                        <plugins>
                                    <!-- Compiler plug-in -->
                                    <plugin>
                                                <groupId>org.apache.maven.plugins</groupId>
                                                <artifactId>maven-compiler-plugin</artifactId>
                                                <configuration>
                                                            <source>${jdk.level}</source>
                                                            <target>${jdk.level}</target>
                                                </configuration>
                                    </plugin>
                                    <!-- Below plug-in is used to execute tests -->
                                    <plugin>
                                                <groupId>org.apache.maven.plugins</groupId>
                                                <artifactId>maven-surefire-plugin</artifactId>
                                                <version>2.18.1</version>
                                                <configuration>
                                                            <suiteXmlFiles>
                                                                        <!-- TestNG suite XML files -->
                                                                        <suiteXmlFile>testng.xml</suiteXmlFile>
                                                            </suiteXmlFiles>
                                                </configuration>
                                    </plugin>
                        </plugins>
            </build>

</project>


28. Right click on your “pom.xml” file and go to “Run As” and click on “maven install

29. Console output should like below:


Right click on your “pom.xml” file and go to “Run As” and click on “maven test

30. Test execution output: 
you can see in the below image it clicked, 1 then + then 2 then it clicked = and it showing result at 3.


31. Console output: in console output we can see it shows as “Build Success”, that means your scripts are executed successfully without error. If any issues, there it shows as “Build Failure”.




If you are facing any issues let me know, I can help you guys.

In the next posts I will go deep in this framework, I will add many features like reading data from excel, screenshot taking if any script failed, creating util methods and generic methods. and also I will show how to run these scripts from Jenkins.





2 comments:

  1. very valuable information
    but the test script should be placed under src>test folder as standards.

    ReplyDelete

If any suggestions or issue, please provide