├── README.md ├── nodeconfig_device1.json ├── nodeconfig_device2.json ├── pom.xml ├── src ├── main │ └── java │ │ └── com │ │ └── test │ │ └── App.java └── test │ ├── java │ └── com │ │ └── test │ │ ├── TestAppiumApiDemoApp.java │ │ ├── apidemo │ │ └── app │ │ │ └── screens │ │ │ ├── AbstractScreen.java │ │ │ ├── AppActivityScreen.java │ │ │ ├── AppMenuScreen.java │ │ │ ├── HomeScreen.java │ │ │ └── ScreenOrientationScreen.java │ │ └── utils │ │ └── AppUtils.java │ └── resources │ ├── ApiDemos-debug.apk │ └── config_apidemo_test_app.properties └── testng.xml /README.md: -------------------------------------------------------------------------------- 1 | AppiumTestAutomation 2 | ==================== 3 | 4 | This is implementation of PageFactory framework with Appium for Android device. 5 | 6 | Current framework provide basic implementation of PageFactory frame and demonstrated on native android application. 7 | 8 | 9 | Prerequisite 10 | ===================== 11 | 1. Android SDK 12 | 2. Appium 13 | 3. Maven (For managing dependencies) 14 | 4. Eclipse 15 | 5. Selenium Standalone (http://goo.gl/cvntq5) 16 | 17 | Installation 18 | ===================== 19 | 1. Install from git 20 | 2. Before installation run selenium hub using 21 | 22 | * java -jar selenium-server-standalone-2.XX.0.jar -role hub) 23 | 24 | 3. Run two server instance of appium servers, each pointing to separate android devices 25 | 26 | * Launch appium from comman line (run from source), 27 | node . -p 6001 -p 5001 -U -nodeconfig /nodeconfig_device1.json 28 | node . -p 6002 -p 5002 -U -nodeconfig /nodeconfig_device2.json 29 | 30 | * Launch appium from comman line, 31 | appium -p 6001 -p 5001 -U -nodeconfig /nodeconfig_device1.json 32 | appium -p 6002 -p 5002 -U -nodeconfig /nodeconfig_device2.json 33 | 34 | 4. Run "mvn clean test" from project directory 35 | 36 | Script Description 37 | ===================== 38 | 1. AppiumApiDemoAppTests: 39 | 40 | * apk Name: ApiDemos-debug.apk 41 | * apk Location: /src/test/resources 42 | * Type of Application: Native 43 | * Gesture Simulated: Swipe/Scroll 44 | 45 | 46 | -------------------------------------------------------------------------------- /nodeconfig_device1.json: -------------------------------------------------------------------------------- 1 | { 2 | "capabilities": [ 3 | { 4 | "browserName": "Android", 5 | "version": "7.0", 6 | "maxInstances": 1, 7 | "deviceName": "Device1", 8 | "udid": "HT6A30201415", 9 | "platform": "ANDROID" 10 | } 11 | ], 12 | "configuration": { 13 | "cleanUpCycle": 2000, 14 | "timeout": 30000, 15 | "proxy": "org.openqa.grid.selenium.proxy.DefaultRemoteProxy", 16 | "url": "http://127.0.0.1:6001/wd/hub", 17 | "maxSession": 1, 18 | "port": 6001, 19 | "host": "127.0.0.1", 20 | "register": true, 21 | "registerCycle": 5000, 22 | "hubPort": 4444, 23 | "hubHost": "127.0.0.1" 24 | } 25 | } -------------------------------------------------------------------------------- /nodeconfig_device2.json: -------------------------------------------------------------------------------- 1 | { 2 | "capabilities": [ 3 | { 4 | "browserName": "Android", 5 | "version": "7.0", 6 | "maxInstances": 1, 7 | "deviceName": "Device2", 8 | "udid": "ZY223GDMPT", 9 | "platform": "ANDROID" 10 | } 11 | ], 12 | "configuration": { 13 | "cleanUpCycle": 2000, 14 | "timeout": 30000, 15 | "proxy": "org.openqa.grid.selenium.proxy.DefaultRemoteProxy", 16 | "url": "http://127.0.0.1:6002/wd/hub", 17 | "maxSession": 1, 18 | "port": 6002, 19 | "host": "127.0.0.1", 20 | "register": true, 21 | "registerCycle": 5000, 22 | "hubPort": 4444, 23 | "hubHost": "127.0.0.1" 24 | } 25 | } -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | com.test 5 | AppiumTestAutomation 6 | jar 7 | 1.0-SNAPSHOT 8 | AppiumTestAutomation 9 | http://maven.apache.org 10 | 11 | 12 | org.uncommons 13 | reportng 14 | 1.1.4 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | org.apache.maven.plugins 28 | maven-surefire-plugin 29 | 2.19.1 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | org.testng 38 | testng 39 | 6.10 40 | 41 | 42 | io.appium 43 | java-client 44 | 5.0.0-BETA4 45 | 46 | 47 | 48 | 49 | 50 | 51 | org.apache.maven.plugins 52 | maven-surefire-plugin 53 | 2.19.1 54 | 55 | 56 | testng.xml 57 | 58 | 59 | 60 | usedefaultlisteners 61 | false 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | -------------------------------------------------------------------------------- /src/main/java/com/test/App.java: -------------------------------------------------------------------------------- 1 | package com.test; 2 | 3 | /** 4 | * Hello world! 5 | * 6 | */ 7 | public class App 8 | { 9 | public static void main( String[] args ) 10 | { 11 | System.out.println( "Hello World!" ); 12 | 13 | 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/test/java/com/test/TestAppiumApiDemoApp.java: -------------------------------------------------------------------------------- 1 | package com.test; 2 | 3 | import com.test.apidemo.app.screens.AppActivityScreen; 4 | import com.test.apidemo.app.screens.AppMenuScreen; 5 | import com.test.apidemo.app.screens.HomeScreen; 6 | import com.test.apidemo.app.screens.ScreenOrientationScreen; 7 | import com.test.utils.AppUtils; 8 | import io.appium.java_client.AppiumDriver; 9 | import org.testng.Assert; 10 | import org.testng.annotations.AfterMethod; 11 | import org.testng.annotations.BeforeMethod; 12 | import org.testng.annotations.Parameters; 13 | import org.testng.annotations.Test; 14 | 15 | import java.io.IOException; 16 | 17 | public class TestAppiumApiDemoApp { 18 | private AppiumDriver driver; 19 | private HomeScreen homeScreen; 20 | private AppMenuScreen appMenuPage; 21 | private AppActivityScreen appActivityPage; 22 | private ScreenOrientationScreen screenOrientationPage; 23 | private AppUtils appUtil; 24 | 25 | 26 | @Parameters({"deviceID"}) 27 | @BeforeMethod(alwaysRun = true) 28 | public void startAutomation(String deviceID) throws IOException { 29 | appUtil = new AppUtils(); 30 | appUtil.loadConfigProp(); 31 | appUtil.setCapabilities(deviceID); 32 | driver = appUtil.getDriver(); 33 | } 34 | 35 | @AfterMethod(alwaysRun = true) 36 | public void stopAutomation() { 37 | driver.quit(); 38 | } 39 | 40 | @Test(groups = {"Smoke"}) 41 | public void testAppActivity() { 42 | homeScreen = new HomeScreen(driver); 43 | appMenuPage = homeScreen.getAppMenuPage(); 44 | appActivityPage = appMenuPage.getActivityPage(); 45 | screenOrientationPage = appActivityPage.getScreenOrientationPage(); 46 | Assert.assertEquals(screenOrientationPage.isItValidScreenOrientationPage(), true); 47 | screenOrientationPage.changeScreenOrientation(); 48 | Assert.assertEquals(screenOrientationPage.checkOrientationType(), true); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/test/java/com/test/apidemo/app/screens/AbstractScreen.java: -------------------------------------------------------------------------------- 1 | package com.test.apidemo.app.screens; 2 | 3 | import io.appium.java_client.AppiumDriver; 4 | import io.appium.java_client.pagefactory.AppiumFieldDecorator; 5 | import org.apache.commons.io.FileUtils; 6 | import org.openqa.selenium.By; 7 | import org.openqa.selenium.NoSuchElementException; 8 | import org.openqa.selenium.OutputType; 9 | import org.openqa.selenium.support.PageFactory; 10 | 11 | import java.io.File; 12 | import java.io.IOException; 13 | import java.util.concurrent.TimeUnit; 14 | 15 | public abstract class AbstractScreen { 16 | 17 | protected AppiumDriver driver; 18 | 19 | protected AbstractScreen(AppiumDriver driver) { 20 | // TODO Auto-generated constructor stub 21 | this.driver = driver; 22 | PageFactory.initElements(new AppiumFieldDecorator(driver, 10, TimeUnit.SECONDS), this); 23 | } 24 | 25 | protected boolean isElementPresent(By by) { 26 | try { 27 | driver.findElement(by); 28 | return true; 29 | } catch (NoSuchElementException e) { 30 | return false; 31 | } 32 | } 33 | 34 | protected void takeScreenShot(String fileName) { 35 | // TODO Auto-generated method stub 36 | File file = new File(fileName + ".png"); 37 | File tmpFile = driver 38 | .getScreenshotAs(OutputType.FILE); 39 | try { 40 | FileUtils.copyFile(tmpFile, file); 41 | } catch (IOException e) { 42 | // TODO Auto-generated catch block 43 | e.printStackTrace(); 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/test/java/com/test/apidemo/app/screens/AppActivityScreen.java: -------------------------------------------------------------------------------- 1 | package com.test.apidemo.app.screens; 2 | 3 | import io.appium.java_client.AppiumDriver; 4 | import io.appium.java_client.pagefactory.AndroidFindBy; 5 | import org.openqa.selenium.WebElement; 6 | 7 | import java.util.List; 8 | 9 | public class AppActivityScreen extends AbstractScreen { 10 | 11 | @AndroidFindBy(id = "android:id/text1") 12 | private List activityList; 13 | 14 | public AppActivityScreen(AppiumDriver driver) { 15 | super(driver); 16 | } 17 | 18 | public ScreenOrientationScreen getScreenOrientationPage() { 19 | return new ScreenOrientationScreen(driver); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/test/java/com/test/apidemo/app/screens/AppMenuScreen.java: -------------------------------------------------------------------------------- 1 | package com.test.apidemo.app.screens; 2 | 3 | import io.appium.java_client.AppiumDriver; 4 | import io.appium.java_client.pagefactory.AndroidFindBy; 5 | import org.openqa.selenium.WebElement; 6 | 7 | public class AppMenuScreen extends AbstractScreen { 8 | 9 | @AndroidFindBy(accessibility = "Activity") 10 | private WebElement appActivity; 11 | 12 | public AppMenuScreen(AppiumDriver driver) { 13 | super(driver); 14 | } 15 | 16 | public AppActivityScreen getActivityPage() { 17 | // TODO Auto-generated method stub 18 | appActivity.click(); 19 | return new AppActivityScreen(driver); 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/test/java/com/test/apidemo/app/screens/HomeScreen.java: -------------------------------------------------------------------------------- 1 | package com.test.apidemo.app.screens; 2 | 3 | import io.appium.java_client.AppiumDriver; 4 | import io.appium.java_client.pagefactory.AndroidFindBy; 5 | import org.openqa.selenium.WebElement; 6 | 7 | public class HomeScreen extends AbstractScreen { 8 | 9 | @AndroidFindBy(accessibility = "App") 10 | private WebElement appMenuItem; 11 | 12 | public HomeScreen(AppiumDriver driver) { 13 | super(driver); 14 | } 15 | 16 | public AppMenuScreen getAppMenuPage() { 17 | appMenuItem.click(); 18 | return new AppMenuScreen(driver); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/test/java/com/test/apidemo/app/screens/ScreenOrientationScreen.java: -------------------------------------------------------------------------------- 1 | package com.test.apidemo.app.screens; 2 | 3 | import io.appium.java_client.AppiumDriver; 4 | import io.appium.java_client.TouchAction; 5 | import io.appium.java_client.pagefactory.AndroidFindBy; 6 | import org.openqa.selenium.By; 7 | import org.openqa.selenium.WebElement; 8 | 9 | import java.util.List; 10 | 11 | public class ScreenOrientationScreen extends AbstractScreen { 12 | 13 | private String sensorType; 14 | @AndroidFindBy(id = "io.appium.android.apis:id/orientation") 15 | private WebElement orientationMenu; 16 | 17 | @AndroidFindBy(id = "android:id/text1") 18 | private List orientationList; 19 | 20 | @AndroidFindBy(id = "android:id/action_bar_title") 21 | private WebElement actionBarTitle; 22 | 23 | public ScreenOrientationScreen(AppiumDriver driver) { 24 | super(driver); 25 | } 26 | 27 | public ScreenOrientationScreen changeScreenOrientation() { 28 | this.sensorType = "USER"; 29 | orientationMenu.click(); 30 | if (!isElementPresent(By.name("USER"))) { 31 | TouchAction action = new TouchAction(driver); 32 | action 33 | .press(245, 1637) 34 | .waitAction(300) 35 | .moveTo(245, 615) 36 | .release() 37 | .perform(); 38 | } 39 | for (WebElement el : orientationList) { 40 | if (el.getText().equals("USER")) { 41 | el.click(); 42 | break; 43 | } 44 | } 45 | return this; 46 | } 47 | 48 | public boolean checkOrientationType() { 49 | boolean isPassed = false; 50 | if (orientationList.get(0).getText().equals(this.sensorType)) { 51 | isPassed = true; 52 | } else { 53 | takeScreenShot("InvalidOrientation"); 54 | } 55 | return isPassed; 56 | } 57 | 58 | public boolean isItValidScreenOrientationPage() { 59 | boolean isPassed = false; 60 | if (actionBarTitle.getText().equals("App/Activity/Screen Orientation")) { 61 | isPassed = true; 62 | } else { 63 | takeScreenShot("InvalidSensor"); 64 | } 65 | return isPassed; 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/test/java/com/test/utils/AppUtils.java: -------------------------------------------------------------------------------- 1 | package com.test.utils; 2 | 3 | import io.appium.java_client.AppiumDriver; 4 | import io.appium.java_client.android.AndroidDriver; 5 | import io.appium.java_client.remote.AndroidMobileCapabilityType; 6 | import io.appium.java_client.remote.MobileCapabilityType; 7 | import org.openqa.selenium.remote.DesiredCapabilities; 8 | 9 | import java.io.File; 10 | import java.io.IOException; 11 | import java.net.MalformedURLException; 12 | import java.net.URL; 13 | import java.util.Properties; 14 | import java.util.concurrent.TimeUnit; 15 | 16 | public class AppUtils { 17 | 18 | private Properties prop = new Properties(); 19 | private String APPLICATION_NAME; 20 | private String BASE_PKG; 21 | private String APP_ACTIVITY; 22 | private String APPIUM_PORT; 23 | private String AUTOMATION_INSTRUMENTATION; 24 | private String PLATFORM_NAME; 25 | private String NEW_COMMAND_TIMEOUT; 26 | private String PLATFORM_VERSION; 27 | private String DEVICE_READY_TIMEOUT; 28 | private String DEVICE_NAME; 29 | private DesiredCapabilities capabilities = new DesiredCapabilities(); 30 | 31 | public void loadConfigProp() 32 | throws IOException { 33 | prop.load(ClassLoader.getSystemResource("config_apidemo_test_app.properties").openStream()); 34 | 35 | APPLICATION_NAME = prop.getProperty("application.path"); 36 | BASE_PKG = prop.getProperty("base.pkg"); 37 | APP_ACTIVITY = prop.getProperty("application.activity"); 38 | APPIUM_PORT = prop.getProperty("appium.server.port"); 39 | AUTOMATION_INSTRUMENTATION = prop.getProperty("automation.instumentation"); 40 | DEVICE_NAME = prop.getProperty("device.name"); 41 | PLATFORM_NAME = prop.getProperty("platform.name"); 42 | PLATFORM_VERSION = prop.getProperty("platform.version"); 43 | NEW_COMMAND_TIMEOUT = prop.getProperty("new.command.timeout"); 44 | DEVICE_READY_TIMEOUT = prop.getProperty("device.ready.timeout"); 45 | } 46 | 47 | public void setCapabilities(String deviceID) { 48 | capabilities.setCapability(MobileCapabilityType.PLATFORM_VERSION, 49 | PLATFORM_VERSION); 50 | capabilities.setCapability(MobileCapabilityType.PLATFORM_NAME, 51 | PLATFORM_NAME); 52 | capabilities.setCapability(MobileCapabilityType.DEVICE_NAME, 53 | DEVICE_NAME); 54 | capabilities.setCapability(MobileCapabilityType.AUTOMATION_NAME, 55 | AUTOMATION_INSTRUMENTATION); 56 | capabilities.setCapability(MobileCapabilityType.APP, new File( 57 | ClassLoader.getSystemResource(APPLICATION_NAME) 58 | .getFile()).getAbsolutePath()); 59 | capabilities.setCapability(MobileCapabilityType.NEW_COMMAND_TIMEOUT, 60 | NEW_COMMAND_TIMEOUT); 61 | capabilities.setCapability(AndroidMobileCapabilityType.DEVICE_READY_TIMEOUT, 62 | DEVICE_READY_TIMEOUT); 63 | capabilities.setCapability(AndroidMobileCapabilityType.APP_ACTIVITY, 64 | APP_ACTIVITY); 65 | capabilities.setCapability(AndroidMobileCapabilityType.APP_PACKAGE, 66 | BASE_PKG); 67 | capabilities.setCapability(MobileCapabilityType.UDID, deviceID); 68 | } 69 | 70 | public AppiumDriver getDriver() throws MalformedURLException { 71 | URL serverUrl = new URL("http://localhost:" + APPIUM_PORT + "/wd/hub"); 72 | AppiumDriver driver = new AndroidDriver(serverUrl, capabilities); 73 | driver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS); 74 | return driver; 75 | } 76 | 77 | } 78 | -------------------------------------------------------------------------------- /src/test/resources/ApiDemos-debug.apk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/priyankshah217/AppiumWithGrid/38984c270464a481c31c4deaacdef36d4bff90d5/src/test/resources/ApiDemos-debug.apk -------------------------------------------------------------------------------- /src/test/resources/config_apidemo_test_app.properties: -------------------------------------------------------------------------------- 1 | application.path=ApiDemos-debug.apk 2 | base.pkg=io.appium.android.apis 3 | appium.server.port=4444 4 | application.activity=.ApiDemos 5 | automation.instumentation=UIAutomator2 6 | platform.name=Android 7 | device.name=Android 8 | platform.version=7.0 9 | new.command.timeout=300 10 | device.ready.timeout=300 -------------------------------------------------------------------------------- /testng.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | --------------------------------------------------------------------------------