SN | Automation Training by Rahul Shetty (Udemy Course) | |||||
1 | Appium | is open source mobile automation tool for testing Apps (Android, iOS) and mobile browsers | ||||
It uses Android Driver or IOS Driver to test Apps as Selenium uses Webdriver Interface for Desktop Browsers | ||||||
It is only Cross Platform testing tool and supports Web driver API from Selenium Family (means support all Web Driver Interface Capabilities + have Capabilities for Mobile App too) | ||||||
Write the code in any language supported by Web Driver: Java, C#, Python, Ruby | ||||||
2 | Appium Framework | uses technologies: Maven, Java, Selenium, Page Objects, TestNG, Extent Reports, CI/CD Jenkins, Simulator/Real Device/Cloud Environment | ||||
3 | IDE | Eclipse/IntelliJ, Android Studio, Xcode | ||||
4 | Apps | Native Apps – built for specific operating system only like Android or iOS | ||||
Non Native Apps – These are web apps and utilizing web browsers like Safari, Chrome etc. These applications are generally written in a browser-friendly language such as JavaScript, CSS, and HTML for universal use across multiple browsers. | ||||||
Hybrid Apps – are the combination of Native & Non Native apps like it run on specific OS and have inbuilt browser too | ||||||
5 | Apps making Tools | React Native is framework by Facebook using JS language to build Apps for crossplatform OS like for Android & iOS both | ||||
Xcode is the tool by Apple using Swift language to built App for iOS only | ||||||
Android Studio is the tool by Google & using Kotlin to build App for Android Only | ||||||
6 | Automation Architecture | Client Library Code (in IDE) coverted to JSON by JSON Wire Protocol ==>> JSON (as input to the Appium Server) ==>> | ||||
Appium Server (need to download on local m/c, used Port 4723) redirect code to Port 4723, Understand by ==>> | ||||||
UIAutomator2 Framework ==> to automate Android Apps OR XCUITest Framework ==>> to automate iOS Apps | ||||||
As the code travels to application and in same format it comes back to Appium to give response’s | ||||||
7 | Required Softwares | Download Java (JDK 8 / Open JDK), Set System Path (Environment Variables: JAVA_HOME [copy jdk folder Path]) | Open Jdk Corretto 1.8 or JDK 8 is more usefull, can use JDK 11 | |||
Download Maven, Set System Path (Environment Variables: MAVEN_HOME) | ||||||
Download Eclipse | ||||||
Download Android Studio. By Android Studio we get Android SDK. Open Android Studio on each operating system to install it completely & after opening Android Studio Set Android SDK Path as mentioned below. | ||||||
Download Node from node.js (this is required to install Appium Server as it is written in Node Platform). For Windows install .msi file & for Mac install .pkg [Dont need to set System Path in Mac as while setting Java Path, PATH for Node was already given] | npm (Node Packge Manager) gets with node installation. Not get nvm (Node Version Manager). Both these are important tools which required to manage Node.js, Check Node requirment first from appium website before installation as it may difficult to update / uninstall node. | |||||
Install Appium as mentioned below | ||||||
8 | Set Windows Path’s | 1) Set Android Path :- This PC > Properties > Advanced System Settings > Envronment Variables > New | ANDROID_HOME >> C:\Users\CS\AppData\Local\Android\Sdk | How to make visible “Tools” Folder in sdk Folder in Mac & Windows :- Open Android Sdk > Empty Project > Let the Project download all files > Tools Menu > Sdk Manager > Android SDK > SDK Tools > Uncheck Hide Obsolete Package > Check Android SDK tools (Obsolete) > Apply & OK | ||
2) Set Path for Android Bin Folder :- Environment Variables > Path > Edit > New > | C:\Users\CS\AppData\Local\Android\Sdk\tools\bin | |||||
3) Set Path for Android Bin Folder :- Environment Variables > Path > Edit > New > | C:\Users\CS\AppData\Local\Android\Sdk\tools | |||||
4) Set Path for Platform-tools Folder :- Environment Variables > Path > Edit > New > | C:\Users\CS\AppData\Local\Android\Sdk\platform-tools | |||||
5) Set Path for Node Folder :- Environment Variables > New > | C:\Program Files\nodejs | |||||
6) Set Path for npm bin Folder :- Environment Variables > Path > Edit > New > | C:\Program Files\nodejs\node_modules\npm\bin | |||||
9 | Set MacOS Path’s in bash file (for intel Processor) | 1) Open Terminal > vi ~/.bash_profile AND to Quit from this esc:wq OR to write in bash profile press I AND to save bash profile after quit : source ~/.bash_profile AND Command to check Path :- echo $JAVA_HOME or echo $PATH | Bash Profile is the file where environment variables written. Here JAVA_HOME & PATH are environmental variables | |||
2) open /usr/libexec (This is just to see where the executables files are placed in Mac OS or to open the File Location) | ||||||
3) Set Java Path in Mac OS :- | export JAVA_HOME=$(/usr/libexec/java_home) AND export PATH=$PATH:/usr/local/bin | Later this Java path (JAVA_HOME) need to change to complete path of open Jdk corretto 1.8 or to jdk 8 which mentioned in “zshenv” section in this document > /Library/Java/JavaVirtualMachines/amazon-corretto-8.jdk/Contents/Home & PATH variable remans the same | ||||
4) Set Android Path in Mac OS :- | export ANDROID_HOME=/Users/kamaljhinjer/Library/Android/sdk export PATH=$PATH:$ANDROID_HOME/platform-tools export PATH=$PATH:$ANDROID_HOME/build-tools export PATH=$PATH:$ANDROID_HOME/tools export PATH=$PATH:$ANDROID_HOME/tools/bin export PATH=$PATH:$ANDROID_HOME/emulator | also add one more variable :- export PATH=$PATH:$ANDROID_HOME/platform-tools & [before to add variables, first open the Android studio > Empty Project > to install it completely. Check Red coloured text under Set Windows paths] | Check Imp Pics in Folder | |||
10 | Set MacOS Path’s in zshenv file (for M1 Chip) | 1) check which shell OS is using: echo $SHELL | .zshenv file load everytime then .zprofile or .zshrc so it is useful to provide environment variables in it | |||
2) to check std path of Java: which java | ||||||
3) returns full path where java/jdk installed: usr/libexec/java_home | ||||||
4) open zsh profile: nano ~/.zshenv | ||||||
5) export JAVA_HOME=/Library/Java/JavaVirtualMachines/amazon-corretto-8.jdk/Contents/Home | ||||||
6) Contrl+X | ||||||
7) return | ||||||
8) source ~/.zshenv | ||||||
9) Similarly set ANDROID_HOME (as the path mentioned above) & MAVEN_HOME | Maven Home path is like in “Documents” where maven folder placed | |||||
11 | Configure Emulator (AVD) | Open Android Studio > Basic Activity > Tools > AVD Manager or Device Manager > Create Virtual device > Select Device (say Pixel 2 XL or other) > Select Android Version (Download specific if required) > Give name to Emulator (Go to Advanced Settings to increase RAM if required) > Start Emulator from play button | For Android it is Emulator and for iOS it is Simulator. Once device is open, close the AVD Window to increase performace. If required edit the device settings and increase RAM. If close Android studio, AVD still keep running unless closed | |||
12 | Install Appium Server via Node | Open the npmjs.com > search for appium and you can see it is listed there. So here are the Terminal commands :- | ||||
1) sudo npm install -g appium –chromedriver-skip-install | Install appium globally by skipping chrome driver OR sudo npm install -g appium@1.22.3 –chromedriver-skip-install | Install specific version if required, may be less than Version 2 | ||||
2) appium | Run the appium Server | |||||
13 | Create Maven Project | Eclipse > New Maven Project > Create Simple Project > | Group ID: com.KJiTechCorp | Artifact ID: AndroidAutomateTrain > Finish | ||
pom.xml file > | <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 https://maven.apache.org/xsd/maven-4.0.0.xsd”> <modelVersion>4.0.0</modelVersion> <groupId>com.KJiTechCorp</groupId> <artifactId>AndroidAutomateTrain</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>AndroidAutomation</name> <url>http://www.example.com</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> <!– Environment Variables to be pass from Terminal command –> <env>QA</env> </properties> | Updated Latest dependencies to run project | ||||
<dependencies> <!– this dependency for selenium to interect with driver–> <dependency> <groupId>org.seleniumhq.selenium</groupId> <artifactId>selenium-java</artifactId> <version>3.141.59</version> </dependency> <!– this dependency for testNG to manipulate test cases–> <dependency> <groupId>org.testng</groupId> <artifactId>testng</artifactId> <version>7.3.0</version> </dependency> <!– Next two dependencies are required to start the server–> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> <version>3.9</version> </dependency> <dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.6</version> </dependency> | JRE at least of JavaSE 1.8 Version | |||||
<!– this dependency for appium server–> <dependency> <groupId>io.appium</groupId> <artifactId>java-client</artifactId> <version>7.3.0</version> </dependency> <!– Next three dependencies are required to start the server–> <dependency> <groupId>commons-validator</groupId> <artifactId>commons-validator</artifactId> <version>1.6</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-simple</artifactId> <version>1.7.26</version> <scope>test</scope> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>1.7.26</version> </dependency> | JRE at least of 1.7 Version | |||||
<!– this dependency for Extent Report–> <dependency> <groupId>com.aventstack</groupId> <artifactId>extentreports</artifactId> <version>4.0.0</version> </dependency> </dependencies> <build> <!– Code realated to Maven Sure Fire Plugin which refer to classes in Resources package like Listener class etc–> <resources> <resource> <directory>src/main/java/Resources</directory> <filtering>true</filtering> </resource> </resources> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <version>3.0.0-M5</version> | 7.4 version can also be used From the Mvn Repositery for TestNG 7.4.0 | |||||
<!– Code realated to Maven Sure Fire Plugin giving knowledge of testng.xml file–> <configuration> <suiteXmlFiles> <suiteXmlFile>testng.xml</suiteXmlFile> </suiteXmlFiles> </configuration> </plugin> </plugins> </build> </project> | ||||||
14 | Project Design Pattern | Follow Page Object Model | Web Elements declare in one package under folder src/main/java | use one Class per Web Page | ||
Base & Utilities Classes declare in one package under folder src/main/java | Package Name like BasePost | |||||
Reports & Listeners Classes declare in “Resources” package under folder src/resources/java | This Resources package linked via code written in pom.xml file | |||||
All the Test case classes declare in package under folder src/test/java | Package Name like BetaTests | |||||
Any other related stuff to be kept under src folder | ||||||
Create desired Classes under packages mentioned above | Also unhide Developer Options for Android Phone mentioned under “Connecting Real Device” section below | |||||
Create a Base Class under BasePost Package & Set Capabilities there | ||||||
Create global.properties file under BasePost Package and give App Name there | ||||||
Add Application under src/Application Folder | ||||||
Add chromer driver under src/BrowserDriver Folder | ||||||
Create Utilities Class under BasePost Package to scroll or swipe | ||||||
Add Web Elements as samplePage under Page Objects Package | ||||||
Add sampleTestCase under src/test/java | ||||||
Run Test Case by adding environment varaibles under Run Configurations | ANDROID_HOME=/Users/kamaljhinjer/Library/Android/sdk JAVA_HOME=/Library/Java/JavaVirtualMachines/amazon-corretto-8.jdk/Contents/Home PATH=/Users/kamaljhinjer/Library/Android/sdk/tools:/usr/local/bin | |||||
Code Text : | File appDir = new File(“src”); | Download .apk Demo file from [https://github.com/appium/appium/blob/master/sample-code/apps/ApiDemos-debug.apk] and copy it and paste it in Java project src folder. File extension for ios is .app | ||||
File app = new File(appDir, “ApiDemos-debug.apk”); | In agruments, provide src folder object and file name | |||||
DesiredCapabilities cap = new DesiredCapabilities(); | make object of capabilities library | |||||
cap.setCapability(MobileCapabilityType.DEVICE_NAME, “Pixel 2 XL API 31”); | set capabilities for Emulator | |||||
cap.setCapability(MobileCapabilityType.APP, app.getAbsolutePath()); | set capabilities for App Path | |||||
cap.setCapability(MobileCapabilityType.AUTOMATION_NAME, “uiautomator2”); | set capabilities for Android Automator | |||||
AndroidDriver<AndroidElement> driver = new AndroidDriver<>(new URL(“http://127.0.0.1:4723/wd/hub”),cap); | In agruments, provide Port Detail for Appium Server where Android Driver sent directions and pass capabilities object | |||||
Right click on method name, run as Java Application, this launch app in the emulator | ||||||
UI Automator Viewer | In Terminal Just type uiautomatorviewer | For this to run JAVA_HOME path to update in vi ~/.bash_ profile such that : JAVA_HOME=/Users/kamaljhinjer/Library/Java/JavaVirtualMachines/corretto-1.8.0_292/Contents/Home | ||||
To make the UI automator viewer responsive, following steps to do :- | Yes, Installing Jdk8 is important & Set default jdk by terminal command : export JAVA_HOME=`/usr/libexec/java_home -v 1.8` | |||||
1) Download 4.20 Binary Patch for Eclipse from : https://www.eclipse.org/downloads/download.php?file=/eclipse/downloads/drops4/R-4.20-202106111600/swt-4.20-cocoa-macosx-x86_64.zip | Multiple jdk can be installed in one computer | |||||
2) Unzip it and change the name of swat.jar to swat2.jar and copy it | ||||||
3) Paste it in following two folders : /Users/kamaljhinjer/library/android/sdk/tools/lib/x86 as well as x86_64. If required maxmize uiautomatorviewer window and then downsize it. it will work | ||||||
Object Locators as like Selenium :- | xpath, id, className, androidUIautomator Like in uiautomatorviewer :- index, text,resource-id, class, package | |||||
//tagName[@attribute=’value’] :- driver.findElementByXPath(“//android.widget.TextView[@text=’Preference’]”).click(); | class name can serve as tagName | |||||
After running the code, appium server need to stop by ctrl c so that UI automator can work properly | ||||||
driver.findElementByXPath(“//*[@attribute=’value’]”); | * use here if to avoid specific tag name and search directly for mentioned attribute | |||||
driver.findElementByXPath(“//android.widget.TextView[@text=’Preference’]”).click(); | ||||||
driver.findElementByXPath(“//android.widget.TextView[@text=’3. Preference dependencies’]”).click(); | ||||||
driver.findElementById(“android:id/checkbox”).click(); | find by id | |||||
driver.findElementByXPath(“(//android.widget.RelativeLayout)[2]”).click(); | index given like “(//…)[]” | |||||
driver.findElementByClassName(“android.widget.EditText”).sendKeys(“hello”); | Send Keys | |||||
driver.findElementsByClassName(“android.widget.Button”).get(1).click(); | class name used with index | |||||
Locator by UIAutomator :- | driver.findElementByAndroidUIAutomator(“attribute(“value”)”) :- below | Java does not accept double quote inside another doubw quote so provide special character like \ | ||||
driver.findElementByAndroidUIAutomator(“UiSelector().text(\”Views\”)”).click(); OR driver.findElementByAndroidUIAutomator(“text(\”Views\”)”).click(); | find element by android uiautomator | |||||
System.out.print(driver.findElementByAndroidUIAutomator(“new UiSelector().Property(value)”) :- below | ||||||
System.out.print(driver.findElementByAndroidUIAutomator(“new UiSelector().clickable(true)”).getSize()); | Size not get properly by this | |||||
Touch Actions Locators :- | TouchAction t = new TouchAction(driver); | For Touch or Tap on screen | ||||
WebElement expandlist = driver.findElementByXPath(“//android.widget.TextView[@text=’Expandable Lists’]”); | ||||||
t.tap(tapOptions().withElement(element(expandlist))).perform(); | for this to work, additional files to import in class : import static io.appium.java_client.touch.TapOptions.tapOptions; import static io.appium.java_client.touch.offset.ElementOption.element; | |||||
WebElement pn = driver.findElementByXPath(“//android.widget.TextView[@text=’People Names’]”); t.longPress(longPressOptions().withElement(element(pn)).withDuration(ofSeconds(2))).release().perform(); | Code for Longpress and following library to import for this :- import static io.appium.java_client.touch.LongPressOptions.longPressOptions; import static io.appium.java_client.touch.offset.ElementOption.element; import static java.time.Duration.ofSeconds; | |||||
System.out.println(driver.findElementById(“android:id/title’]”).isDisplayed()); | Give True False result that id appear or not | |||||
Implicity Wait code :- | driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS); | Implicity wait > wait to appear the element on page for that much of max time which was given and if element appear before to mentioned time, then code move ahead at same time | ||||
Swipe Action Locator :- | If class have $ in its text then locator is not work properly so you cant use it as a tag name | |||||
driver.findElementByXPath(“//*[@content-desc=’9′]”).click(); | xpath with any tag name but that specific attribute | |||||
TouchAction t = new TouchAction(driver); WebElement first = driver.findElementByXPath(“//*[@content-desc=’15’]”); WebElement second = driver.findElementByXPath(“//*[@content-desc=’45’]”); t.longPress(longPressOptions().withElement(element(first)).withDuration(ofSeconds(2))).moveTo(element(second)).release().perform(); | following files need to import manually :- import static io.appium.java_client.touch.LongPressOptions.longPressOptions; import static io.appium.java_client.touch.offset.ElementOption.element; import static java.time.Duration.ofSeconds; | |||||
t.longPress(longPressOptions().withElement(element(first)).withDuration(ofSeconds(2))).waitAction(2000).moveTo(element(second)).release().perform(); | .waitAction can also be used if required | |||||
Scroll Action Locator :- | driver.findElementByAndroidUIAutomator(“new UiScrollable(new UiSelector()).scrollIntoView(text(\”WebView\”));”); | |||||
Drag & Drop Action Locator :- | TouchAction t = new TouchAction(driver); WebElement source = driver.findElementsByClassName(“android.view.View”).get(0); WebElement destination = driver.findElementsByClassName(“android.view.View”).get(1); t.longPress(longPressOptions().withElement(element(source))).moveTo(element(destination)).release().perform(); | Files to import :- import static io.appium.java_client.touch.LongPressOptions.longPressOptions; import static io.appium.java_client.touch.offset.ElementOption.element; | ||||
Connecting Real Device :- | Search for this link :- https://developer.chrome.com/docs/devtools/remote-debugging/ | Required connecting wire and android version is 4 and more and chrome browser to automate in app browser | ||||
See the instructions from there (For Android) :- | ||||||
>> unhide developer option and see that from another thread/link or google it :- | ||||||
1. Go to settings > More > about device > tap 7 times on Build number and then popup come that developer options enabled | ||||||
2. Open Devleoper options > On USB Debugging | Select usb mode as charging only. If required click on pip and then again on charging only | |||||
3. Type adb devices in terminal or command prompt to check list of devices attached >> | Install usb drivers if device not detected in your system | |||||
OR can see detail of attched devices in chrome browser at url :- chrome://inspect/#devices | ||||||
4. In eclipse change in code where emulator name given to code like this :- //cap.setCapability(MobileCapabilityType.DEVICE_NAME, “Pixel 2 XL API 31”); cap.setCapability(MobileCapabilityType.DEVICE_NAME, “Android Device”); | ||||||
Code to Start Emulator vs Real device :- | public static AndroidDriver<AndroidElement> capabilities(String device) throws MalformedURLException { // TODO Auto-generated method stub File appDir = new File(“src”); File app = new File(appDir, “ApiDemos-debug.apk”); DesiredCapabilities cap = new DesiredCapabilities(); if(device.equals(“emulator”)) { cap.setCapability(MobileCapabilityType.DEVICE_NAME, “Pixel 2 XL API 31”); } else if(device.equals(“real”)) { cap.setCapability(MobileCapabilityType.DEVICE_NAME, “Android Device”); } cap.setCapability(MobileCapabilityType.APP, app.getAbsolutePath()); cap.setCapability(MobileCapabilityType.AUTOMATION_NAME, “uiautomator2”); AndroidDriver<AndroidElement> driver = new AndroidDriver<>(new URL(“http://127.0.0.1:4723/wd/hub”),cap); return driver; | real or emulator to pass in the capabilities function like capabilities(“real”) in that class which test to run | ||||
Code to Start Browser on Real device :- | import java.io.File; import java.net.MalformedURLException; import java.net.URL; import java.util.concurrent.TimeUnit; import org.openqa.selenium.remote.DesiredCapabilities; import io.appium.java_client.android.AndroidDriver; import io.appium.java_client.android.AndroidElement; import io.appium.java_client.remote.MobileCapabilityType; public class BrowserBase { public static AndroidDriver<AndroidElement> capabilities() throws MalformedURLException { // TODO Auto-generated method stub AndroidDriver<AndroidElement> driver; DesiredCapabilities capabilities = new DesiredCapabilities(); capabilities.setCapability(“chromedriverExecutable”, “/Users/kamaljhinjer/Downloads/chromedriver”); capabilities.setCapability(MobileCapabilityType.DEVICE_NAME, “Android Device”); capabilities.setCapability(MobileCapabilityType.BROWSER_NAME,”Chrome”); driver = new AndroidDriver<>(new URL(“http://127.0.0.1:4723/wd/hub”), capabilities); return driver; } } | import java.net.MalformedURLException; import io.appium.java_client.android.AndroidDriver; import io.appium.java_client.android.AndroidElement; public class Browser extends BrowserBase { public static void main(String[] args) throws MalformedURLException { // TODO Auto-generated method stub AndroidDriver<AndroidElement> driver = capabilities(); driver.get(“http://facebook.com”); driver.findElementByXPath(“//*[@id=’u_0_1′]/div[1]/div/input”).sendKeys(“qwerty”); driver.findElementByName(“pass”).sendKeys(“12345”); driver.findElementByXPath(“//button[@value=’Log In’]”).click(); } } | ||||
If required, download chrome driver and give its path | ||||||
Install App in Emulator :- | 1. In terminal open folder under Android sdk upto platform-tools (if already set the path for this folder then drirectly give the command as ahead) | |||||
2. adb install /Users/kamaljhinjer/Downloads/General-Store.apk | which is the file path name and open the emulator first | |||||
Other Syntax :- | Hide Keyboard :- driver.hideKeyboard(); | |||||
2nd Option of code for Scroll :- // driver.findElement(MobileBy.AndroidUIAutomator(“new UiScrollable(new UiSelector().scrollable(true).instance(0)).scrollIntoView(new UiSelector().textMatches(\”” + containedText + “\”).instance(0))”)); | provide text upto which scroll in place of contained text | |||||
3rd Option of code for Scroll :- driver.findElement(MobileBy.AndroidUIAutomator(“new UiScrollable(new UiSelector().resourceId(\”com.androidsample.generalstore:id/rvProductList\”)).scrollIntoView(new UiSelector().textMatches(\”Jordan 6 Rings\”).instance(0))”)); | ||||||
System.out.println(driver.findElementsById(“com.androidsample.generalstore:id/productName”).size()); | this will print the number of items seen on screen | |||||
Verify Toast Message :- | It is difficult to capture the screenshot of Toast message so usually developer using following code for toast message :- | class = android.widget.Toast[1], Index 1 to give to choose first message toast messages and text of message given in name attribute | ||||
driver.findElementById(“com.androidsample.generalstore:id/btnLetsShop”).click(); String toastMessage = driver.findElementByXPath(“//android.widget.Toast[1]”).getAttribute(“name”); System.out.println(toastMessage); | ||||||
Add to Product in Cart :- | driver.findElement(MobileBy.AndroidUIAutomator(“new UiScrollable(new UiSelector().resourceId(\”com.androidsample.generalstore:id/rvProductList\”)).scrollIntoView(new UiSelector().textMatches(\”Jordan 6 Rings\”).instance(0))”)); int count = driver.findElementsById(“com.androidsample.generalstore:id/productName”).size(); for (int i=0; i<=count; i++) { String text = driver.findElementsById(“com.androidsample.generalstore:id/productName”).get(i).getText(); if(text.equalsIgnoreCase(“Jordan 6 Rings”)) { driver.findElementsById(“com.androidsample.generalstore:id/productAddCart”).get(i).click(); break; } } //This is Cart Button click driver.findElementById(“com.androidsample.generalstore:id/appbar_btn_cart”).click(); | |||||
Validate Items on Checkout Page :- | String checkoutText = driver.findElementById(“com.androidsample.generalstore:id/productName”).getText(); Assert.assertEquals(“Jordan 6 Rings”, checkoutText); | |||||
Validate Sum of Cart :- | driver.findElementsByXPath(“//*[@text=’ADD TO CART’]”).get(0).click(); driver.findElementsByXPath(“//*[@text=’ADD TO CART’]”).get(0).click();// as text changed to ADDED TO CART for first Item //This is Cart Button click driver.findElementById(“com.androidsample.generalstore:id/appbar_btn_cart”).click(); Thread.sleep(4000); String amount1 = driver.findElementsById(“com.androidsample.generalstore:id/productPrice”).get(0).getText(); System.out.println(amount1); amount1 = amount1.substring(1); // this remove dollar sign from string text double amt1 = Double.parseDouble(amount1); //this convert string to float/double value System.out.println(amt1); String amount2 = driver.findElementsById(“com.androidsample.generalstore:id/productPrice”).get(1).getText(); amount2 = amount2.substring(1); // this remove dollar sign from string text double amt2 = Double.parseDouble(amount2); //this convert string to float/double value double sumamt = amt1+amt2; System.out.println(sumamt); String ttlamt = driver.findElementById(“com.androidsample.generalstore:id/totalAmountLbl”).getText(); ttlamt = ttlamt.substring(1); double ttlamtvalue = Double.parseDouble(ttlamt); System.out.println(ttlamtvalue); Assert.assertEquals(sumamt, ttlamtvalue); | 280.97 | ||||
Optimization of Validate Sum of Cart Code :- | Function should written outside the publid static void main function :- | |||||
AndroidDriver<AndroidElement> driver = capabilities(); driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS); driver.findElementById(“com.androidsample.generalstore:id/nameField”).sendKeys(“Hello”); driver.hideKeyboard(); driver.findElementByXPath(“//android.widget.RadioButton[@text=’Female’]”).click(); driver.findElementById(“android:id/text1”).click(); driver.findElementByAndroidUIAutomator(“new UiScrollable(new UiSelector()).scrollIntoView(text(\”Argentina\”));”); driver.findElementByXPath(“//*[@text=’Argentina’]”).click(); driver.findElementById(“com.androidsample.generalstore:id/btnLetsShop”).click(); driver.findElementsByXPath(“//*[@text=’ADD TO CART’]”).get(0).click(); driver.findElementsByXPath(“//*[@text=’ADD TO CART’]”).get(0).click();// as text changed to ADDED TO CART for first Item //This is Cart Button click driver.findElementById(“com.androidsample.generalstore:id/appbar_btn_cart”).click(); Thread.sleep(4000); int count = driver.findElementsById(“com.androidsample.generalstore:id/productPrice”).size(); double sum = 0; for(int i=0; i<count; i++) { String amount = driver.findElementsById(“com.androidsample.generalstore:id/productPrice”).get(i).getText(); double amtvalue=getAmount(amount); sum = sum+amtvalue; } //String amount1 = driver.findElementsById(“com.androidsample.generalstore:id/productPrice”).get(0).getText(); //double amt1value=getAmount(amount1); //String amount2 = driver.findElementsById(“com.androidsample.generalstore:id/productPrice”).get(1).getText(); //double amt2value=getAmount(amount2); String ttlamt = driver.findElementById(“com.androidsample.generalstore:id/totalAmountLbl”).getText(); double ttlamtvalue = getAmount(ttlamt); System.out.println(ttlamtvalue); Assert.assertEquals(sum, ttlamtvalue); } public static double getAmount(String value) { value = value.substring(1); double amtvalue = Double.parseDouble(value); return amtvalue; } | ||||||
Validate Mobile Gestures for Links (Long Press) and navigate to Web View :- | Already covered gestures so it is same | |||||
WebView Practical :- | driver.findElementById(“com.androidsample.generalstore:id/appbar_btn_cart”).click(); Thread.sleep(4000); WebElement checkbox = driver.findElementByClassName(“android.widget.CheckBox”); TouchAction t = new TouchAction(driver); t.tap(tapOptions().withElement(element(checkbox))).perform(); driver.findElementById(“com.androidsample.generalstore:id/btnProceed”).click(); Thread.sleep(4000); Set<String> contexts = driver.getContextHandles(); for(String contextName : contexts) { System.out.println(contextName); } Thread.sleep(3000); driver.context(“WEBVIEW_com.androidsample.generalstore”); //this let the code know which view it has to consider Thread.sleep(3000); System.out.println(driver.getContext()); driver.get(“https://www.yahoo.com”); Thread.sleep(2000); driver.findElementByXPath(“//*[@name=’p’]”).sendKeys(“Hello I am web driver”); | For Web view, if driver not works then download the required chromedriver and replace the file given in folder somewhere inside npm>modules and so on… or use code as mentioned in notes above like this :- capabilities.setCapability(“chromedriverExecutable”, “/Users/kamaljhinjer/Downloads/chromedriver”); | ||||
ProfileMenuPage pmp = new ProfileMenuPage(driver); pmp.PrivacyPolicy().click(); Thread.sleep(7000); Set<String> contexts = driver.getContextHandles(); for(String contextName : contexts) { System.out.println(contextName); } driver.context(“WEBVIEW_chrome”); String changedContextName = driver.getContext(); System.out.println(changedContextName); Thread.sleep(5000); String verifyText = driver.findElement(By.xpath(“/html/body/div/section[2]/div/div/div/div/div/h1”)).getText(); System.out.println(verifyText); Assert.assertEquals(verifyText, “Privacy Policy”); | ||||||
Perform Operation on Web View and Navigate back to Native App :- | driver.findElementById(“com.androidsample.generalstore:id/btnProceed”).click(); Thread.sleep(7000); Set<String> contexts = driver.getContextHandles(); for(String contextName : contexts) { System.out.println(contextName); } Thread.sleep(3000); driver.context(“WEBVIEW_com.androidsample.generalstore”); //this let the code know which view it has to consider Thread.sleep(3000); System.out.println(driver.getContext()); driver.get(“https://www.yahoo.com”); Thread.sleep(1000); driver.findElementByXPath(“//*[@name=’p’]”).sendKeys(“Hello I am web driver”); //Comeback to Native App after WebView driver.pressKey(new KeyEvent(AndroidKey.BACK)); Thread.sleep(6000); driver.context(“NATIVE_APP”); System.out.println(driver.getContext()); sp.getNameField().sendKeys(“Came back to NATIVE APP”); | |||||
Mobile Browser (Solo Mode) Practical :- | public class baseChrome { public static AndroidDriver<AndroidElement> capabilities() throws MalformedURLException { // TODO Auto-generated method stub AndroidDriver<AndroidElement> driver; DesiredCapabilities cap = new DesiredCapabilities(); cap.setCapability(MobileCapabilityType.DEVICE_NAME, “Pixel 2 XL API 31”); cap.setCapability(MobileCapabilityType.AUTOMATION_NAME, “uiautomator2”); cap.setCapability(MobileCapabilityType.BROWSER_NAME, “Chrome”); cap.setCapability(“chromedriverExecutable”, “/Users/kamaljhinjer/Downloads/chromedriverEmulatoruse/chromedriver”); driver = new AndroidDriver<>(new URL(“http://127.0.0.1:4723/wd/hub”),cap); return driver; } | This is capabilities code for solo mode. If combined mode like Mobile & webapp, then donr give BROESER_NAME, rest is ok | ||||
public class browse extends baseChrome { public static void main(String[] args) throws MalformedURLException { // TODO Auto-generated method stub AndroidDriver<AndroidElement> driver = capabilities(); driver.get(“https://rahulshettyacademy.com/angularAppdemo/”); driver.findElementByCssSelector(“.navbar-toggler”).click(); driver.findElementByCssSelector(“a[href*=’products’]”).click(); JavascriptExecutor js = (JavascriptExecutor)driver; js.executeScript(“window.scrollBy(0,1000)”, “”); String text = driver.findElementByXPath(“(//li[@class=’list-group-item’])[3]/div/div/a”).getText(); Assert.assertEquals(text, “Devops”); } | This is test code | |||||
iOS & iPadOS :- | ||||||
Download Appium Server GUI :- | Search for Download Appium Server and go to offcial wwebsite and from there install .dmg file, install it | It is required to run ios app even if appium installed via node that could work for android only. Certain commands required to run it before to open the file which are follows and mentioned on git hub website too [https://github.com/appium/appium-desktop#installing-on-macos] :- 1) xattr -cr “/Applications/Appium Server GUI.app” 2) codesign –deep –sign – /Applications/Appium\ Server\ GUI.app 3) Start the application by click on icon | codesign –deep –force –verbose –sign – /Applications/Appium\ Server\ GUI.app | < If Gui not get open, this is terminal command | ||
Open it, Simple Tab > Hoast is 0.0.0.0 AND Port is 4723 and start server | ||||||
Download Appium Inspector (work for ios & android) :- | Search for Download Appium Inspector, go to github offcial website and from there install .dmg file, install it | Certain commands required to run it before to open the file which are follows and mentioned on git hub website too [https://github.com/appium/appium-inspector] :- 1) xattr -cr “/Applications/Appium Inspector.app” 2) codesign –deep –sign – /Applications/Appium\ Inspector.app 3) Start the application by click on icon | ||||
Give host address as 127.0.0.1 , Port 4723 , Path address /wd/hub (if the appium version below 2 and using .bash_profile) and Given JSON request as :- { “platformName”: “iOS”, “appium:platformVersion”: “15.5”, “appium:deviceName”: “iPhone 13 Pro”, “appium:automationName”: “XCUITest”, “appium:app”: “/Users/kamaljhinjer/Documents/Mac_Coding/IOSAutomation/src/Application/UIKitCatalog.app” } | Then Start Session but before to it, start Appium Server too from GUI | { “platformName”: “iOS”, “appium:platformVersion”: “15.5”, “appium:deviceName”: “iPhone 12 mini”, “appium:automationName”: “XCUITest”, “appium:udid”: “00008101-000808921AB8001E”, “appium:bundleId”: “dog.fa.so.app”, “appium:xcodeOrgId”: “CGYHFCCU8D”, “appium:xcodeSigningId”: “iPhone Developer”, “appium:app”: “/Users/kamaljhinjer/Documents/Z-IOS-Memberse-Builds/Memberse-34.ipa” } | { “platformName”: “iOS”, “appium:platformVersion”: “18.3.1”, “appium:deviceName”: “iPhone 12 mini”, “appium:automationName”: “XCUITest”, “appium:udid”: “00008101-000808921AB8001E”, “appium:bundleId”: “io.appium.KjiTech.WebDriver.AgentRunner”, “appium:xcodeOrgId”: “RPCKHTRSDD”, “appium:xcodeSigningId”: “iPhone Developer”, “appium:app”: “/Users/kamaljhinjer/Documents/Mobile_Applications/Test iOS Apps/Compiled Apps/Real Device 12 mini signature KjiTech OrgId RPCKHTRSDD/UIKitCatalog.app” } | <= Real device Capabilties | ||
Dowload & Install test app :- | 1. Search for uicatalog app > Go to github website > Code Button > Download Zip File | |||||
2. Unzip it > ios-uicatalog (app Name) > UIKitCatalog > UIKitCatalog.xcodeproj (It open the file in xcode) | If to run app in version ios 10 & Before then choose xcode file in the folder UICatalog and for other latest version choose the folder UIKitCatalog | |||||
Install Xcode :- | 1. Get it from App Store | This compile the app into suitable compatibility according to each iphone / ipad. Sometime xcode path is not set properly then use this command in terminal (this issue reported in ecliopse and in appium logs) :- sudo xcode-select –switch /Applications/Xcode.app | ||||
2. When file opens in xcode then in the products folder there is file with extension .app | Need to copy at location from where path to give Appium Inspector | |||||
3. Select from dropdown at top the type of device for which code is to compile and to open simulator | Select the desired one | |||||
4. Compile the code and open the simulator by click on play button | or on Real Device. But before to this, WebDriverAgent Runner Need to run on that device where this app to install like on Real device or on Simulator | |||||
iOS Automation Project :- | 1. Create Maven Project | |||||
2. Put dependencies like search for appium java client > github > and there repositeries given :- | ||||||
<repositories> <repository> <id>jitpack.io</id> <url>https://jitpack.io</url> </repository> </repositories> | This is for information of appium jars , put after version tag and out of dependencies tag | |||||
<dependency> <groupId>com.github.appium</groupId> <artifactId>java-client</artifactId> <version>7.4.1</version> </dependency> | Put this under <dependencies> tag and provide the latest version number as already provided. Tick Build automatically from top Menu :- Project > build automatically | |||||
3) under src/test/java > create a new class… | ||||||
DesiredCapabilities cap = new DesiredCapabilities(); cap.setCapability(MobileCapabilityType.PLATFORM_VERSION, “14.2”); cap.setCapability(MobileCapabilityType.DEVICE_NAME, “iPhone 12 Pro”); cap.setCapability(MobileCapabilityType.AUTOMATION_NAME, AutomationName.IOS_XCUI_TEST); cap.setCapability(IOSMobileCapabilityType.LAUNCH_TIMEOUT, 500000); // 50 secs cap.setCapability(“commandTimeouts”, 12000); // this is for give times for scrolling & other things cap.setCapability(MobileCapabilityType.APP, “Users/Kamal Jhinjer/Downloads/UIKitCatalog.app”); // First complie the app from xcode, copy it from project to any location IOSDriver driver = new IOSDriver<>(new URL(“http://localhoast:4723/wd/hub”), cap); | App which opens in xcode, compile it first (run THAT FILE FOR THAT PARTICULAR SIMULATOR), copy it by from Projects folder > Right click on mame and open file location, copy it and paste it at desired location for which you can give path in capabilities. For new IOSDriver ==> Choose the option to interchange jre 1.7 like so | |||||
Associated Terminal work :- | 1) brew install carthage | This is required to install app in ios. this package is must have in mac os AND to install Brew, this is the command :- /bin/bash -c “$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)” OR alternate command to install bew is [This is the old version] :- /usr/bin/ruby -e “$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)“ | This is related to xcode CLI. Also can use :- brew update. For M1 Mac, Homebrew install on different location then intel Mac and some commands need to run after installation to take homebrew new path into ennvironment variables | |||
2) instruments -s devices | This tell you all simulators available in xcode with ios versions.This command not work for xcode 13 | |||||
Eclipse Base class to launch app :- | import java.net.MalformedURLException; import java.net.URL; import org.openqa.selenium.remote.DesiredCapabilities; import io.appium.java_client.ios.IOSDriver; import io.appium.java_client.remote.AutomationName; import io.appium.java_client.remote.IOSMobileCapabilityType; import io.appium.java_client.remote.MobileCapabilityType; public class BaseIOSTest { public class BaseIOSTest { //static used to use method w/o creating object of that class public static IOSDriver Capabilities() throws MalformedURLException { DesiredCapabilities cap = new DesiredCapabilities(); cap.setCapability(MobileCapabilityType.PLATFORM_VERSION, “15.4”); cap.setCapability(MobileCapabilityType.DEVICE_NAME, “iPhone 12 Pro”); cap.setCapability(MobileCapabilityType.AUTOMATION_NAME, AutomationName.IOS_XCUI_TEST); cap.setCapability(IOSMobileCapabilityType.LAUNCH_TIMEOUT, 300000); // 30 secs cap.setCapability(“commandTimeouts”, 12000); // this is for give times for scrolling & other things cap.setCapability(MobileCapabilityType.APP, “/Users/kamaljhinjer/Downloads/Appium_Automation/UIKitCatalog.app”); // First complie the app from xcode, copy it from project to any location IOSDriver driver = new IOSDriver<>(new URL(“http://localhost:4723/wd/hub”), cap); return driver; } } | This is final | ||||
Click in iOS :- | public class AppiumClickTest extends BaseIOSTest{ public static void main(String[] args) throws MalformedURLException { // TODO Auto-generated method stub IOSDriver driver = Capabilities(); driver.findElementByAccessibilityId(“Alert Views”).click(); driver.findElementByXPath(“//XCUIElementTypeStaticText[@name=’Text Entry’]”).click(); driver.findElementByXPath(“//XCUIElementTypeCell”).sendKeys(“Hello”); driver.findElementByAccessibilityId(“OK”).click(); driver.findElementByAccessibilityId(“Confirm / Cancel”).click(); System.out.println(driver.findElementByXPath(“//*[contains(@name, ‘message’)]”).getText()); // get all text where word written/contains message driver.findElementByAccessibilityId(“Confirm”).click(); } } | |||||
Scroll in iOS :- | IOSDriver driver = Capabilities(); HashMap<String,Object> scrollObject = new HashMap<>(); scrollObject.put(“direction”, “down”); scrollObject.put(“name”, “Web View”); driver.executeScript(“mobile:scroll”, scrollObject); driver.findElementByAccessibilityId(“Web View”).click(); | |||||
Dropdown Selection / Picker View in iOS :- | driver.findElementByAccessibilityId(“Picker View”).click(); driver.findElementByAccessibilityId(“Red color component value”).sendKeys(“80”); driver.findElementByAccessibilityId(“Green color component value”).sendKeys(“220”); driver.findElementByAccessibilityId(“Blue color component value”).sendKeys(“105”); System.out.println(driver.findElementByAccessibilityId(“Blue color component value”).getText()); | |||||
Sliders in iOS :- | IOSDriver driver = Capabilities(); driver.findElementByAccessibilityId(“Sliders”).click(); IOSElement slider = (IOSElement)driver.findElementByXPath(“//XCUIElementTypeSlider”); slider.setValue(“0%”); //0% slider.setValue(“0.50%”); // 50% slider.setValue(“1%”); // 100% Assert.assertEquals(“100%”, slider.getAttribute(“value”)); // put testng code in pom.xml file for this | |||||
Longpress in iOS :- | IOSDriver driver = Capabilities(); MobileElement me = (MobileElement)driver.findElementByName(“Long tap”); IOSTouchAction touch = new IOSTouchAction(driver); touch.longPress(longPressOptions().withElement(element(me)).withDuration(ofSeconds(2))).release().perform(); | Libraryies to import :- import static io.appium.java_client.touch.LongPressOptions.longPressOptions; import static io.appium.java_client.touch.offset.ElementOption.element; import static java.time.Duration.ofSeconds; import static io.appium.java_client.touch.TapOptions.tapOptions; | ||||
Tap on Switch in iOS (gestures) :- | MobileElement tape = (MobileElement)driver.findElementByXPath(“//XCUIElementTypeSwitch[1]”);// index provided touch.tap(tapOptions().withElement(element(me))).perform(); | Libraryies to import :- import static io.appium.java_client.touch.LongPressOptions.longPressOptions; import static io.appium.java_client.touch.offset.ElementOption.element; import static java.time.Duration.ofSeconds; import static io.appium.java_client.touch.TapOptions.tapOptions; | ||||
Automation on Real iOS Device :- | 1) Install Brew by :- | This is required to install app in ios. this package is must have in mac os AND to install Brew, this is the command :- /bin/bash -c “$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)” OR alternate command to install bew is [This is the old version] :- /usr/bin/ruby -e “$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)“ | ||||
2) brew install libimobiledevice | ||||||
3) brew install ios-deploy | ||||||
4) cap.setCapability(“xcodeOrgId”, “____”); // Provide Here Team ID which get by subscribing developer a/c or from team cap.setCapability(“xcodeSigningId”, “iPhone Developer”); // static cap.setCapability(“udid”, “____”); // By click on iphone name or serial number, this will show up when iphone connected to Mac via cable cap.setCapability(“updateWDABundlId”, “____”); //Provide this by creating provision profile from xcode or ask from team | required capabilities. | |||||
Creating a provisioning profile via xcode & install app on iphone:- | 1) xcode > File > New > Project > ios > App > next > Product Name : WebDriverAgentRunner > Team : Login to your Developer A/c ID [I provided Name_Personal] > Organization Name : any > Organization Identifier : io.appium.KJQA > Next > Save it in location where you want > create | Use sofadog id like kamal@so.fa.dog and its has its own password and connected to 9872559019 | ||||
2) By click on Project name from Left side pane, Under Signing Tab > Sign in to your account and its creating provisioning profile automatically but actually its required developer a/c subscription | ||||||
3) Now the Bundle Identifier ID is ready : io.appium.KJQA.WebDriverAgentRunner | ||||||
4) Run the Code and that will install the apps on iphone. These 3 erros might come which need to resolve as follows :- | ||||||
4.1) Verify Developer App Certificate is trusted on your device : for this, on iphone go to settings > General > PRofiles & Device Management > select developer app certificate to trust | OR go to VPN section | |||||
4.2) Untrusted developer : for this, on iphone > General > Device Management > Trust the app/Developer which shown there | ||||||
4.3) Might have to do this step as well : for this, on iphone > Settings > Developer App > Enable UI Automation | ||||||
5) Open the project in xcode, compile the app by click on App button by selecting connect device, provide required necessary setting as above (personal in case of no team credentials for Team and Bundle Identifier). This will install app in mobile | ||||||
6) for Automation, copy the .app file from folder of this project like project folder and place it somewhere and gives its path in eclipse capability to automate it | ||||||
Real Device iOS Capabilities Code :- | import java.net.MalformedURLException; import java.net.URL; import org.openqa.selenium.remote.DesiredCapabilities; import io.appium.java_client.ios.IOSDriver; import io.appium.java_client.remote.AutomationName; import io.appium.java_client.remote.IOSMobileCapabilityType; import io.appium.java_client.remote.MobileCapabilityType; public class RealDeviceBase { //static used to use method w/o creating object of that class public static IOSDriver Capabilities() throws MalformedURLException { DesiredCapabilities cap = new DesiredCapabilities(); cap.setCapability(MobileCapabilityType.PLATFORM_NAME, “IOS”); cap.setCapability(MobileCapabilityType.DEVICE_NAME, “iPhone”); cap.setCapability(MobileCapabilityType.AUTOMATION_NAME, AutomationName.IOS_XCUI_TEST); cap.setCapability(“xcodeOrgId”, “Kamalpreet Singh (Personal Team)”); // Provide Here Team ID which get by subscribing developer a/c or from team cap.setCapability(“xcodeSigningId”, “iPhone Developer”); // static cap.setCapability(“udid”, “00008101-000808921AB8001E”); // By click on iphone name or serial number, this will show up when iphone connected to Mac via cable cap.setCapability(“updateWDABundlId”, “io.appium.KJQA.WebDriverAgentRunner”); //Provide this by creating provision profile from xcode or ask from team cap.setCapability(IOSMobileCapabilityType.LAUNCH_TIMEOUT, 300000); // 30 secs cap.setCapability(“commandTimeouts”, 12000); // this is for give times for scrolling & other things cap.setCapability(MobileCapabilityType.APP, “/Users/kamaljhinjer/Downloads/Appium_Automation/iOSappRealDeviceVersion/UIKitCatalog.app”); // First complie the app from xcode, copy it from project to any location IOSDriver driver = new IOSDriver<>(new URL(“http://localhost:4723/wd/hub”), cap); return driver; } } | https://github.com/appium/appium-xcuitest-driver/blob/master/docs/real-device-config.md | ||||
FrameWork:- | TestNG – Unit Testing Framework | |||||
Maven – Build Management Tool | ||||||
Jenkins – Contineous Integration Tool | ||||||
Page Factory / Objects – Design Pattern in writting automated tests | ||||||
Structure ==>> | For Ios, use ios Capabilities and Object of Ios Library in Page Object + change app AND for Android, user for android library | |||||
1) Create Maven Project | ||||||
2) Build Appium Tests into the Project | ||||||
3) Global Properties for Appium Desired Capabilities | ||||||
4) Make the tests for TestNG | ||||||
5) Develop Page Object Design Pattern | ||||||
6) Develop appium custom utilities to avoid duplicate code | ||||||
7) Build utilities to start & stop appium server programmatically | ||||||
8) Framework to Invoke Emulator | ||||||
9) Build TestNG Listeners to capture screenshot on Test Failures | ||||||
10) Generate Client – Side Reports with Graphs | ||||||
11) Implement Data Driven & Parameterization mechanism to drive test externally into tests | ||||||
12) Integrate framework repo into Jenkins CI Tool | ||||||
13) Parametrize the jenkin build so that user have option to select mobile device which needed to run tests for that specific build | ||||||
14) Push your changes into git repo | ||||||
TestNG :- | 1) TestNG plug to install eclipse so that it available for every project | |||||
2) public static void main function is the java compiler and when use TestNG then it is not required as TestNG act as compiler (act as fx which compiles by giving @Annotations). Use Run as TestNG for TestNG and for Java class use as Run as Java Application | ||||||
TestNG XML File :- (explained in Selenium Automation Notes) | 1) Create xml file > R.click on project name >TestNg > Convert to TestNG > Next & Finish | |||||
2) Architecture :- Suite > Test (Shell / Test Folders) > Classes (Test Cases related to that Test Folder / Java File) | ||||||
3) Run all class file test by r.click on TestNG XML file and runs as TestNG | ||||||
TestNG Annotations (explained in Selenium automation Notes ) :- | These are annotations given above the syntax of method. | |||||
Multiple xml files can be create under one project and run it by r.click and run as TestNG | ||||||
Maven :- | Software Management Tool & Build Management Tool | |||||
All test cases should go under test folder. Test Data, Utilities like reusable methods, Page Objects can be given under Main Folder | ||||||
Maven Terminology :- | GroupId = Defines the code in Repositery like it is main ID for Selenium Framework, Uniquely identify the project | |||||
ArtifactId = It is sub ID of GroupId, this is name to jar’s, serve as sub id which grouped to main id framework | ||||||
archetype = genrate new project from an archetype | ||||||
Proper Maven Project :- | 1) Start New Maven Project | |||||
2) Use Default WorkSpace | ||||||
3) Catalog : All Catalogs & Template to choose : maven-archetype-quickstart 1.1 | ||||||
4) GroupID is Whole Umberella : cssoftsolutions, Artifact ID : MavenProjectName & Package Name : groupID.ArtifactID > finish | ||||||
5) that provided certain dependicies too in xml file | ||||||
6) Start writing the test cases in the test folder | ||||||
7) Put the dependencies for Selenium, TestNG, RESTAssured & Appium> Java Client | ||||||
8) Copy the Maven Sure Fire Plugin code by search in goolge and open website > usage and copy the code :- Paste it in pom.xml above the <dependencies tag. It help in executing test cases present in test folder of project | <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> | |||||
9) Maven Terminal Commands :- (provide these commands in project folder directory likely where pom.xml is) | ||||||
9.1) mnv clean : delete all temporary build and files what all current project have | ||||||
9.2) mnv compile : this check of syntax error’s | ||||||
9.3) mnv test : run the code by clean and compile and run | ||||||
10) Maven will pick file whose name ends with “Test” from test folder of project due to algorithm set in maven. If comment @Test Anotations then too that method not consider for Test | ||||||
11) Running test from testNG XML File, that would be create by right click on Project Name > TestNG > convert to TestNG. this available at project level and not the test package level mvn test. Place a code (<configuration Tag)inside sure fire plugin such that its :- | <build> <pluginManagement> <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> </plugins> </pluginManagement> </build> | |||||
12) If to run the just one specific java file from all files then following command used :- mvn -Dtest=AppiumTest test | AppiumTest is the java file name | |||||
13) Executing from 2nd xml file :- like diff. files for smoke and regression testing :- Place the sure file plugin code in <profiles tag as like this :- Run the test with following command :- mvn test -PRegression Where P is profile and Regression is the profile id | <profiles> <profile> <id>Regression</id> <build> <pluginManagement> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <version>3.0.0-M6</version> <configuration> <suiteXmlFiles> <suiteXmlFile>testng2.xml</suiteXmlFile> // give the desired file name here </suiteXmlFiles> </configuration> </plugin> </plugins> </pluginManagement> </build> </profile> <profile> <id>Smoke</id> <build> <pluginManagement> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <version>3.0.0-M6</version> <configuration> <suiteXmlFiles> <suiteXmlFile>testng1.xml</suiteXmlFile> // give the desired file name here </suiteXmlFiles> </configuration> </plugin> </plugins> </pluginManagement> </build> </profile> </profiles> | |||||
JENKINS :- | Schedule a job to run | |||||
Jenkins have its own environment, common environment to run the test and see the results | ||||||
It is to be install on server for a project | ||||||
Installation :- | Download the Generic Java .war files by search for Jenkins download | |||||
Open the terminal and switch to path of folder where jenkins installed | ||||||
Commands for terminal :- java -jar jenkins.war -httpPort=8080 or for other port 9090 | ||||||
open the link in browser like localhost:8080 and hit enter | ||||||
Setup :- | 1) Set the password for first time login | |||||
2) On left side Menu > click manage jenkins > Global Tool Configuration > Jdk Installations > Copy the name & path of JAVA_HOME there > Click on Maven Installation and provide name & path for MAVEN_HOME > provide git information for source code if required > Save | ||||||
Running :- | 3) New Item > Project Name > Freestyle Project > (provide git detail there) | |||||
4) To run from local :- click on Advanced > Tick custom workspace | ||||||
5) Provide path as follows :- ${JENKINS_HOME}/Mavenjava where Mavenjava is the project name. Before to this step copy project by click on its name in eclipse and paste it in .Jenkins Folder in Users/KamalJhnjer/.Jenkins | ||||||
6) Tick furthur settings like Build Periodically to run the test at specified time and tick to delete workspace to clean the files which comes to jenkins while running the tests // Optional | ||||||
7) Under Build > click on top level maven targets > select maven version and give maven comman in goal like :- test -PRegression > save | ||||||
8) Click on build now > | ||||||
9) Check the results by click on detail shown just below on page > Console output | ||||||
Page Object Framework :- | Widely used and get most support. Easy to maintain, East readability of scripts, reduce duplicacy, code can reuse abd reliable | |||||
Keyword driven (depends on excel), hybrid framework (depends on excel, scripts also drive from excel) are outdated | ||||||
All the Objects belong to one page should be one java class | ||||||
driver to call in test case class from there it called to class whose object is to access in test class. So it is like capabilities to testclass and testclass to object class and back to test class | ||||||
Practical tips :- | ||||||
Test Class ==>> | public class basics2 extends Hybridbase { public static void main(String[] args) throws MalformedURLException { // TODO Auto-generated method stub AndroidDriver<AndroidElement> driver =capabilities(“real”); // for POM structure, this is Test Class // Object of other class be called in this by giving the name of that class, it might be in another package // constructor of that class called if provided otherwise default constructor called HomePage h = new HomePage(driver); h.Prefrences.click(); // called method via object PreferencesPage p = new PreferencesPage(driver); p.Dependencies.click(); driver.findElementById(“android:id/checkbox”).click(); driver.findElementByXPath(“(//android.widget.RelativeLayout)[2]”).click(); driver.findElementByClassName(“android.widget.EditText”).sendKeys(“hello”); driver.findElementsByClassName(“android.widget.Button”).get(1).click(); } } | |||||
Page Object Class // Any Page of App Class ==>> | import org.openqa.selenium.WebElement; import org.openqa.selenium.support.PageFactory; import io.appium.java_client.AppiumDriver; import io.appium.java_client.pagefactory.AndroidFindBy; import io.appium.java_client.pagefactory.AppiumFieldDecorator; public class HomePage { // this calling driver object from test case class to Page object class public HomePage(AppiumDriver driver) //this is constructor which is called in class where this class object created. driver to pass { PageFactory.initElements(new AppiumFieldDecorator(driver), this); // Initial Elements via driver for this class. new Appi…decorator only required for mobile automation for ios /android } @AndroidFindBy(xpath=”//android.widget.TextView[@text=’Preference’]”) //IOSFindBy for ios public WebElement Prefrences; // this is variable taking above variable } | |||||
To Handle findElementsByXPath, then do following change | @AndroidFindBy(xpath=”//android.widget.TextView[@text=’Preference’]”) public List <WebElement> Prefrences; | |||||
Framework Practical from Scratch :- | 1) Create Maven Project | |||||
2) In the Pom.xml, put dependencies and create Base Class | appium, selenium, testng / Remove JUnit | |||||
create Emulator, start it, start appium, copy apk file as mentioned in step no.5, create global properties file, convert to testng format and create base class | ||||||
3) Create Test Class file under Test Folder/java of Project | public class ecommerce_tc_4_1 extends base { public static void main(String[] args) throws InterruptedException, IOException { AndroidDriver<AndroidElement> driver = capabilities(“GeneralStoreApp”); driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS); driver.findElementById(“com.androidsample.generalstore:id/nameField”).sendKeys(“Hello”); driver.hideKeyboard(); driver.findElementByXPath(“//android.widget.RadioButton[@text=’Female’]”).click(); driver.findElementById(“android:id/text1”).click(); driver.findElementByAndroidUIAutomator(“new UiScrollable(new UiSelector()).scrollIntoView(text(\”Argentina\”));”); driver.findElementByXPath(“//*[@text=’Argentina’]”).click(); driver.findElementById(“com.androidsample.generalstore:id/btnLetsShop”).click(); driver.findElementsByXPath(“//*[@text=’ADD TO CART’]”).get(0).click(); driver.findElementsByXPath(“//*[@text=’ADD TO CART’]”).get(0).click();// as text changed to ADDED TO CART for first Item //This is Cart Button click driver.findElementById(“com.androidsample.generalstore:id/appbar_btn_cart”).click(); Thread.sleep(4000); int count = driver.findElementsById(“com.androidsample.generalstore:id/productPrice”).size(); double sum = 0; for(int i=0; i<count; i++) { String amount = driver.findElementsById(“com.androidsample.generalstore:id/productPrice”).get(i).getText(); double amtvalue=getAmount(amount); sum = sum+amtvalue; } String ttlamt = driver.findElementById(“com.androidsample.generalstore:id/totalAmountLbl”).getText(); double ttlamtvalue = getAmount(ttlamt); System.out.println(ttlamtvalue); Assert.assertEquals(sum, ttlamtvalue); WebElement checkbox = driver.findElementByClassName(“android.widget.CheckBox”); TouchAction t = new TouchAction(driver); t.tap(tapOptions().withElement(element(checkbox))).perform(); WebElement tc = driver.findElementByXPath(“//*[@text=’Please read our terms of conditions’]”); t.longPress(longPressOptions().withElement(element(tc)).withDuration(ofSeconds(2))).release().perform(); driver.findElementById(“android:id/button1”).click(); Thread.sleep(4000); driver.findElementById(“com.androidsample.generalstore:id/btnProceed”).click(); } public static double getAmount(String value) { value = value.substring(1); double amtvalue = Double.parseDouble(value); return amtvalue; } } | |||||
4) Create Base file under Main/java folder of Project | public class base { public static AndroidDriver<AndroidElement> capabilities(String appName) throws IOException { FileInputStream fis = new FileInputStream(System.getProperty(“user.dir”)+”/src/main/java/practise/AppiumFramework/global.properties”); Properties prop = new Properties(); prop.load(fis); File appDir = new File(“src”); File app = new File(appDir, (String) prop.get(appName)); DesiredCapabilities cap = new DesiredCapabilities(); String deviceName = (String) prop.get(“device”); cap.setCapability(MobileCapabilityType.DEVICE_NAME, “deviceName”); cap.setCapability(MobileCapabilityType.APP, app.getAbsolutePath()); cap.setCapability(MobileCapabilityType.AUTOMATION_NAME, “uiautomator2”); cap.setCapability(MobileCapabilityType.NEW_COMMAND_TIMEOUT, 14); AndroidDriver<AndroidElement> driver = new AndroidDriver<>(new URL(“http://127.0.0.1:4723/wd/hub”),cap); return driver; } } | |||||
5) Copy .apk file in src folder of Project | ||||||
6) Create Global file like New > File > global.properties in main/java folder | GeneralStoreApp=General-Store.apk device=Pixel 2 XL API 31 | |||||
7) Apply TestNG format Like @Test Annotations & R.click on project name > TestNg > convert to TestNG | ||||||
8) Bring in Page Object Model Structure ==>> Can make one more package of PageObjects and put classes in it | public class FormPage { public FormPage(AppiumDriver<AndroidElement> driver) { PageFactory.initElements(new AppiumFieldDecorator(driver), this); } @AndroidFindBy(id=”com.androidsample.generalstore:id/nameField”) private WebElement nameField; @AndroidFindBy(xpath=”//a*[@text=’Female’]”) public WebElement femaleOption; @AndroidFindBy(id=”android:id/text1″) public WebElement countrySelection; public WebElement getNameField(){ // for best practice, make the variable private and access the same in other class with public method return nameField; } | |||||
9) Call the Private Variable in Test Class via public methods in Object Page Class | public class Ecommerce_tc_4_1 extends base { @Test public void totalValidation() throws InterruptedException, IOException { AndroidDriver<AndroidElement> driver = capabilities(“GeneralStoreApp”); driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS); FormPage fp = new FormPage(driver); //fp.nameField.sendKeys(“Hello”); OR fp.getNameField().sendKeys(“Hello”); driver.hideKeyboard(); //driver.findElementByXPath(“//android.widget.RadioButton[@text=’Female’]”).click(); fp.femaleOption.click(); //driver.findElementById(“android:id/text1”).click(); fp.countrySelection.click(); | |||||
AppiumDriver or AndroidDriver<AndroidElement> driver :- are same thing | 10) Create Utilities class in main/java folder for scrolling and reusable code :- | public class Utilities { AndroidDriver<AndroidElement> localdriver; public Utilities(AndroidDriver<AndroidElement> driver) { this.localdriver=driver; } public void ScrollToText(String text) { localdriver.findElementByAndroidUIAutomator(“new UiScrollable(new UiSelector()).scrollIntoView(text(\””+text+”\”));”); } } | ||||
10.1 ) Its relevant code in Test Class :- //driver.findElementByAndroidUIAutomator(“new UiScrollable(new UiSelector()).scrollIntoView(text(\”Argentina\”));”); Utilities u = new Utilities(driver); u.ScrollToText(“Argentina”); | ||||||
11) Start & Stop Appium Server Programatically :- (do not install ADT – Andoird Development Kit, Give Environment varial for testngxml or in each test class for JAVA_HOME, ANDROID_HOME & PATH for both) | Code in base class ==>> public class base { public static AppiumDriverLocalService service; public AppiumDriverLocalService startServer() { boolean flag = checkIfServerIsRunning(4723); if(!flag) // this mean true of nagation i.e. if true is expecting and false come then it enter to loop. { service = AppiumDriverLocalService.buildDefaultService(); service.start(); } return service; } public static boolean checkIfServerIsRunning(int port) { boolean isServerRunning = false; ServerSocket serverSocket; try { serverSocket = new ServerSocket(port); serverSocket.close(); } catch (IOException e) { isServerRunning = true; } finally { serverSocket = null; } return isServerRunning; } public static AndroidDriver<AndroidElement> capabilities(String appName) throws IOException { FileInputStream fis = new F | Corresponding code in Test class ==>> public class Ecommerce_tc_4_1 extends base { @Test public void totalValidation() throws InterruptedException, IOException { service = startServer(); AndroidDriver<AndroidElement> driver = capabilities(“GeneralStoreApp”); driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS); ////… and in the end of test code ….. service.stop(); | Dependencies to put in pom.xml for this code to work in dependencies tag for from maven repository ==>> SLF4J-Simple, slf4j-api, commons-lan3, commons-io, commons-validator . Suprizingle these not given in POM of SoFADOG but still the server start and stop | IF get error that port in use and give following command in terminal :- taskkill /F /IM node.exe . Might need to download android developer tools in eclipse at Help > Install New software > https://dl-ssl.google.com/android/eclipse/ > enter > select development tools and install. set the android sdk path in eclipse>prefrerences > android and give path | Eclipse Environment Varialbles for each file & testng.xml file :- ANDROID_HOME=/Users/kamaljhinjer/Library/Android/sdk JAVA_HOME=/Users/kamaljhinjer/Library/Java/JavaVirtualMachines/corretto-1.8.0_292/Contents/Home PATH=/Users/kamaljhinjer/Library/Android/sdk/tools:/usr/local/bin | |
Or can use these lines of code as well :- service = AppiumDriverLocalService.buildService(new AppiumServiceBuilder() // .usingDriverExecutable(new File(“/usr/local/bin/node”)) // .withAppiumJS(new File(“/usr/local/lib/node_modules/appium/build/lib/main.js”)).withEnvironment(System.getenv()) // .withIPAddress(“127.0.0.1”).usingPort(4723)); | ||||||
OR :- /*service = AppiumDriverLocalService.buildService(new AppiumServiceBuilder() .withIPAddress(“127.0.0.1”).usingPort(4723) .usingDriverExecutable(new File(Appium_Node_Path)).withAppiumJS(new File(Appium_JS_Path)) .withArgument(GeneralServerFlag.RELAXED_SECURITY) .withArgument(GeneralServerFlag.SESSION_OVERRIDE) .withArgument(GeneralServerFlag.LOG_LEVEL, “error”));*/ | ||||||
12) Starting Emulator Programatically :- | Command to open Emulator, First change to its directory like (/Users/kamaljhinjer/Library/Android/sdk/emulator) and then :- emulator -avd Pixel_2_XL_API_31_Kamal_QA_ -netdelay none -netspeed full | |||||
Create a batch file in windows and its equivalent in mac as .sh by writing terminal commands in script editor, save it as script file and then rename it as .sh | ||||||
Placed that file in project> src> main> java folder and create resources new folder and placed in it | ||||||
Double click .sh file and remove extra code and just keep these line and save it :- cd /Users/kamaljhinjer/Library/Android/sdk/emulator) AND emulator -avd Pixel_2_XL_API_31_Kamal_QA_ -netdelay none -netspeed full | >> to avoid that, direct code to written in Eclipse on mac :- //Set Path for Emulator public static void startEmulator() throws IOException, InterruptedException { Runtime.getRuntime().exec(“/Users/kamaljhinjer/Library/Android/sdk/emulator/emulator -avd Emulator_Pixel3XL -netdelay none -netspeed full”); Thread.sleep(10000); } | |||||
code to start Emulator is :- | ||||||
public static void startEmultor() throws IOException, InterruptedException { Runtime.getRuntime().exec(System.getProperty(“user.dir”)+”/src/main/java/resources/startEmulator.sh”); Thread.sleep(6000); } public static AndroidDriver<AndroidElement> capabilities(String appName) throws IOException, InterruptedException { FileInputStream fis = new FileInputStream(System.getProperty(“user.dir”)+”/src/main/java/practise/AppiumFramework/global.properties”); Properties prop = new Properties(); prop.load(fis); File appDir = new File(“src”); File app = new File(appDir, (String) prop.get(appName)); DesiredCapabilities cap = new DesiredCapabilities(); String deviceName = (String) prop.get(“device”); if(deviceName.contains(“PIXEL”)) // this is to start Emulator vs real device { startEmultor(); } | ||||||
13) Code Debugging like if server is already running :- | @BeforeTest public void killAllNodes() throws IOException, InterruptedException { Runtime.getRuntime().exec(“taskkill /F /IM node”); // it is not running in mac Thread.sleep(3000); } | |||||
14) Capture screesnhot for test failure :- | 1) create Listeners class under resources folder | |||||
2) Create a code in Base class :- public static void getScreenhot(String s) throws IOException { File scrfile = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE); FileUtils.copyFile(scrfile, new File(System.getProperty(“user.dir”)+”//”+s+”.png”)); } | ||||||
3 ) Listener class code :- | ||||||
package resources; import org.testng.ITestListener; import java.io.IOException; import org.testng.ITestContext; import org.testng.ITestResult; import practise.AppiumFramework.base; public class Listeners implements ITestListener{ @Override public void onTestStart(ITestResult result) { } @Override public void onTestSuccess(ITestResult result) { } @Override public void onTestFailure(ITestResult result) { String s = result.getName(); try { base.getScreenhot(s); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } @Override public void onTestFailedButWithinSuccessPercentage(ITestResult result) { } @Override public void onStart(ITestContext context) { } @Override public void onFinish(ITestContext context) { } } | ||||||
4) Changes in xml file under tag <suit :- | ||||||
<suite name=”Suite”> <listeners> <listener class-name=”resouces.Listeners”/> </listeners> <test thread-count=”5″ name=”Test”> | ||||||
15) Generation of Reports :- (do not install ADT – Andoird Development Kit, Give Environment varial for testngxml or in each test class for JAVA_HOME, ANDROID_HOME & PATH for both) | 1) Put the extent report dependency in pom.xml file from extentreports.com > docs > version > java | |||||
2) create a class file in resources folder and code for the same is :- | ||||||
public class ExtentReporterNG implements IReporter{ private ExtentReports extent; ExtentHtmlReporter htmlReporter; public void generateReports(List<XmlSuite> xmlSuites, List<ISuite> suites, String outputDirectory) { htmlReporter = new ExtentHtmlReporter(System.getProperty(“user.dir”)+”/Reports/htmlreport.html”); extent = new ExtentReports(); extent.attachReporter(htmlReporter); for (ISuite suite : suites) { Map<String, ISuiteResult> result = suite.getResults(); for(ISuiteResult r : result.values()) { ITestContext context = r.getTestContext(); buildTestNodes(context.getPassedTests(), Status.PASS); buildTestNodes(context.getFailedTests(), Status.FAIL); buildTestNodes(context.getSkippedTests(), Status.SKIP); } } extent.flush(); } private void buildTestNodes(IResultMap tests, Status status) { ExtentTest test; if (tests.size() > 0) { for (ITestResult result : tests.getAllResults()) { test = extent.createTest(result.getMethod().getMethodName()); /*test.getTest(). = getTime(result.getStartMillis()); test.getTest().endedTime = getTime(result.getEndMillis());*/ for (String group : result.getMethod().getGroups()) test.assignCategory(group); String message = “Test ” + status.toString().toLowerCase() + “ed”; if (result.getThrowable() != null) message = result.getThrowable().getMessage(); test.log(status, message); // extent.endTest(test); } } } private Date getTime(long millis) { Calendar calendar = Calendar.getInstance(); calendar.setTimeInMillis(millis); return calendar.getTime(); } } | ||||||
3) Do changes in xml file | ||||||
<suite name=”Suite”> <listeners> <listener class-name=”resources.Listeners”/> <listener class-name=”resources.ExtentReporterNG”/> </listeners> <test thread-count=”5″ name=”Test”> | ||||||
16) Parameterizing Test Data & Implement Data Driven By DataProvider Annottaions :- | 1) Create a class in main/java :- // THIS is to provide Test data to test from outside test class and test run as many time according to array given in data provider class | package practise.AppiumFramework; import org.testng.annotations.DataProvider; public class TestData { @DataProvider(name=”InputData”) public Object[][] getDataforEditField() { //2 sets of data, “hello” , “!@#$$” Object[][] obj=new Object[][] { {“hello”}, {“@#$%”} // this is array }; return obj; } } | ||||
2) Changes in Test Class | public class ApiDemoTest extends base { @Test(dataProvider=”InputData”,dataProviderClass=TestData.class) public void apiDemo(String input) throws IOException, InterruptedException { //service = startServer(); AndroidDriver<AndroidElement> driver =capabilities(“apiDemo”); HomePage h = new HomePage(driver); h.Prefrences.click(); PreferencesPage p = new PreferencesPage(driver); p.Dependencies.click(); driver.findElementById(“android:id/checkbox”).click(); driver.findElementByXPath(“(//android.widget.RelativeLayout)[2]”).click(); driver.findElementByClassName(“android.widget.EditText”).sendKeys(input); driver.findElementsByClassName(“android.widget.Button”).get(1).click(); //service.stop(); } } | |||||
17) Modification in pom.xml to run project by Maven commands :- | 1) Put Maven sure fire plugin in pom.xml file with <configuration tag :- | <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <version>3.0.0-M5</version> <configuration> <suiteXmlFiles> <suiteXmlFile>testng.xml</suiteXmlFile> </suiteXmlFiles> </configuration> </plugin> </plugins> </build> </project> | ||||
2) search for maven resources plugin > eamples > filtering :- and placed that code inside build tag which directs to listener class in resorces tab & Remove the <scope tag from testng dependencies | <build> <resources> <resource> <directory>src/main/java/resources</directory> <filtering>true</filtering> </resource> </resources> <plugins> <plugin> | |||||
3) Go to terminal :- change to project folder path and run mvn test command | ||||||
18) Run Test on multiple devices by switching those throught code :- | 1) Terminal Command :- mvn test -DdeviceName=Pixel 2 XL API 31 // is the device name defined in global properties file | |||||
2) Subsequently change in code in base file :- DesiredCapabilities cap = new DesiredCapabilities(); //String deviceName = (String) prop.get(“device”); String device = System.getProperty((“deviceName”)); | ||||||
3) Terminal Command :- mvn test -DdeviceName=Android Device // is the code for real device | ||||||
4) To run single test file via mvn command :- mvn test -Dtest=aLoginWithEmailTest -Denv=INT | ||||||
19) Jenkins Integration with Maven :- | 0) Go to the folder where Jenkins war file present and open that folder in terminal | |||||
Give command to run it java -jar jenkins.war -httpPort=8080 and then go to browser and type localhost:8080 | ||||||
1) Open Jenkins in Browser | ||||||
2) New Item | ||||||
3) Give Name : AppiumFramework | ||||||
4) Click on advance > used custom work space > under Directory, give the path of Project folder | ||||||
5) Use Git section if to run project from there | ||||||
6) Other steps are same which were explained in jenkins section | ||||||
7) under maven section > Goal – give following command :- test -DdeviceName=Pixel | ||||||
….. | ||||||
8) to run test on different device, click on This project is parameterized under line 4 | ||||||
9) Add Parameter > choice parameter > Name: deviceType and under choices write following :- | ||||||
Pixel … | ||||||
Nexus | ||||||
Real Device | ||||||
IOS | ||||||
10) Give the description > Save | ||||||
11) Under Maven Section, change code for Goal :- test -DdeviceName=’$deviceType’ > Save | ||||||
12) then on screen come choose Build with Parameters > choose device type and build | ||||||
13) Open build and see console output | ||||||
14) See the reports from its folder path and from there open those in browser or try top open it in browser | ||||||
20) Git :- | 1) Download Git from Internet | |||||
2) Use Git from Windows Command Prompt | ||||||
3) Go to GitHub website and signup there | ||||||
4) After Login, create new repositery from button | ||||||
5) Create New Repisitery > Give name and create | ||||||
6) Give your name :- git config –global user.name “Kamal” | ||||||
7) Give your email :- git config –global user.email “kpsj84@gmail.com” | ||||||
8) Create folder on local machine and copy files in it to push the code to git hub | ||||||
9) On terminal, go to that folder path and give command :- git init | ||||||
10) Structure is Local to Stash by Add Command and then by commit it goes at Commit and by merge its goes to git hub | ||||||
11) Add files by :- git add * (command to add all files are git add –all) | ||||||
12) to check the status of files which are add :- git status | ||||||
13) To commit :- git commit -m “message” | ||||||
14) Connect to git hub in remote location :- git remote add origin https://github.com/kpsj84/GitDemo.git | ||||||
15) to merge : git push origin master | ||||||
16) provide user name and access token in place of password which created at git hub website from a/c seetings > Developer options | ||||||
—- | ||||||
17) Clone the existing repo to local machine :- | ||||||
18) git clone https://github.com/kpsj84/GitDemo.git | clone existing repo into workspace – project folder will be download in it, git status and create develop branch and all set | |||||
19) Import project in eclipse | ||||||
20) Then again same cycle start from no. 4 | ||||||
21) Pull the latest code from repo :- git pull origin master | ||||||
22) for creating new branch :- git checkout -b develop | ||||||
23) git branch : show the branch you are on | ||||||
24) git add * = add the files to develop branch | ||||||
25) git commit -m “architect 1 commit” in develop branch only | ||||||
26) git push origin develop : this pushes the branch with code to git hub repo | ||||||
27) Pull the code from develop branch by other developer :- git pull origin develop | ||||||
28) Change the branch : git checkout develop | ||||||
29) To merge develop code with master branch then switch to master branch : git checkout master | ||||||
30) Git pull origin master // pull the latest code from master branch | ||||||
31) git merge develop // merge develop branch to master branch | ||||||
32 git push origin master // to push the master branch code to git hub master branch | ||||||
33) git remote rename origin upstream and then git remote add origin https://github.com/kpsj84/QAMemberseAndroid.git | If code push to upstream / fork or intermidiate clone of main repo, its then need to add fork to main repo from git hub | |||||
34) rm -rf .git | If git to delete from code folder | |||||
35) git remote -v | tells about the remote repo and upstream connected to project | |||||
36) git remote set-url origin https://git-repo/new-repository.git | Change the Origin to new Repo for existing project | |||||
37) git remote rm upstream | Removing upstream | |||||
38) git reset –soft HEAD~1 | command to undo last registered commit | |||||
39) git reset –soft HEAD~2 | command to undo last 2 registered commit in one step | |||||
Practical Issues Solutions :- | Error Message: The session identified by 25030467-b3ad-4f74-a6ce-10f8ffab97c3 is not known | What you need to do is to uninstall uiautomator apps. Go to Android settings -> Apps. Then search for uiautomator, 2 apps will pop up. Uninstall those and you’ll be good to go. This error occurs when the sessions crash over and over again so change your code in such a way that if it causes some error, it automatically quits the driver. | ||||
NoSuchDriverError: A session is either terminated or not started | Increase the time to 15 or 20 seconds for time out under capabilities method in base class | |||||
UIautomatorviewer Error > | Error while obtaining UI hierarchy XML file: com.android.ddmlib.SyncException: Remote object doesn’t exist! | In Terminal at any location :- adb reconnect (This will reconnect the device to uiautomatorviewer) | ||||
If adb connected devices issue > | (1 step) In terminal > adb start-server (2 step) adb kill-server (3 step) adb start-server | This started the server again | ||||
then check for connected devices > adb devices | ||||||
changing from Native to Webview :- | Set<String> contexts = driver.getContextHandles(); for(String contextName : contexts) { System.out.println(contextName); } System.out.println(“Printed context Name”); Thread.sleep(12000); driver.context(“WEBVIEW_dog.fa.so.app”); //this let the code know which view it has to consider by taking the detail from package attribute, add WEBVIEW_ before the package name driver.findElementById(“email”); driver.findElementById(“cardNumber”); | |||||
Jenkins can be run as a Cloud | Yes, via placing that m/c outside firewall | |||||
Run Tests on cloud | 1) Open Browerstack.com | |||||
2) Select APP Automate | ||||||
3) Register or Login | ||||||
4) Upload a App to automate | ||||||
Connect adb device wirelessly | 1) Type is terminal following commands :- adb tcpip 555 | |||||
2) adb shell ip addr show wlan0 | Copy the ip address after “inet” upto before “/” | |||||
3) adb connect 192.168.2.5:5555 | ||||||
disconnect wire now | ||||||
Running Test Parrallel on two devices with different apps | 1) Make two saparate <test> tags with all sub tags in xml file | Test name inside test tag should be different for earch wrapper | ||||
2) <suite name=”any or otherwsie Parallel Test Suite” parallel= “tests” | Test execute on two different devices by taking test from one <test wrapper on 1 device> | |||||
3) capabilities for both the apps set with if end else conditions such that both the app or single app can be execute at same time with different environment | ||||||
Push & Pull File | //Push a file driver.pushFile(“/sdcard/Download/SampleVideo_2MB.mp4”, new File(System.getProperty(“user.dir”)+”/src/uploadfiles/SampleVideo_2MB.mp4″)); Thread.sleep(5000); //Pull file //byte[] fileBase64 = (driver.pullFile(“/sdcard/Download/SampleVideo_2MB.mp4”)); | |||||
Jenkins Extent Report CSS Code: | Jenkins Terminal command for Extent Report but seems not work: java -Dhudson.model.DirectoryBrowserSupport.CSP=”” -jar jenkins.war -httpPort=8080 | |||||
Jenkins script file code for extent Report: System.setProperty(“hudson.model.DirectoryBrowserSupport.CSP”, “”) | ||||||
Open Simulator from Terminal Commands :- | 1) xcrun simctl list | show the list of all devices present | ||||
2) Copy the UDID for the Device shown under step | ||||||
3) open -a Simulator –args -CurrentDeviceUDID CD48D4E0-0240-4E1D-97EC-DDDD05BB0052 | This opens the Simulator with Current Ios which ever available with xCode | |||||
4) open -a Xcode | Xcode need to open to compile the app and to run install WebDriverAgent to Simulator | |||||
Can be use :- xcrun simctl install <YOUR-DEVICE-ID> <PATH-TO-APPLICATION-BUNDLE> xcrun simctl launch <YOUR-DEVICE-ID> <BUNDLE-ID-OF-APP-BUNDLE> | ||||||
Convertion of .app file to .ipa File :- | Placed the .app file which complied thru xcode with the valid signing certificate (either from Paid developer a/c or from Personal a/c) into the folder “Payload” and compress it. | |||||
Rename that folder with any_name.ipa | ||||||
Use that file to upload on browser stack | ||||||
DTD Failure Error by Running TestNG from Test Class :- | -ea -Dtestng.dtd.http=true | This code is to given in VM Options which inside the Run configurations > Arguments | ||||
More capabilities for IOS Base class if Web Driver Agent takes time to start on Simulator | cap.setCapability(“waitForQuiescence”, false); cap.setCapability(“wdaEventloopIdleDelay”, 3); cap.setCapability(“eventLoopIdleDelaySec”, 1); //cap.setCapability(“useNewWDA”, false); | |||||
Real/simulator device Ios App Facts :- | 1) .app file is work on simulator that may be compiled for any type of device but need specific ios version but .ipa file (which may or may not compressed manually from .app file to .ipa) can only work if it is specifically compiled for that device | Right | ||||
2) .app and .ipa both files are installed in real iphone device. App to run on real device then it should be compiled for that device only | Right | |||||
3) only .ipa file is getting upload on browserstack | Right | |||||
Very. Important :- File compiled for 13 Pro Simulator can work in 12 mini simulator & vice Versa | Right | |||||
Very. Important :- File compiled for 12 mini Real device cannot work in 12 mini simulator | Error is Architecture is not Supported | |||||
Very. Important :- File compiled for 12 mini simulator cannot work in 12 mini real device | Error is Architecture is not Supported | |||||
if build compiled for any arm64, then it does not open in Simulator. To run in simulator, it is specifically to compile for that simulator | ||||||
UDID need to add to test the app on real device or may be on simulator too before the lauch to public | ||||||
Conclusion is like : Required Developer A/c Develop Team ID and Bundle Id for App to test and additional app for WebDriverAgentRunner to be present on Real device with diff. Bundle id or same Bundle Id and also the udid need to add in developer a/c | ||||||
Appium 2.0 => | It is in Beta phase and soon to be release publically | |||||
Install by Terminal :- | 1) sudo npm install -g appium@next | |||||
Maven Project Arche Type | Quickstart 1.4 | |||||
Dependencies :- | 1) Appium Java Client version 8.0.0 or 8.1.1 | |||||
2) TestNG Version 7.6.0 | ||||||
Test NG Plugin :- | Eclipse > Help > Market Place > TestNG for Eclipse | |||||
If Java 11 installed then use TestNG version 7 and above & for Java 8, user latest version from 6 series | ||||||
Appium :- | appium driver list | Terminal command to see list of installed driver but seems not working | ||||
appium driver install uiautomator2 | ||||||
Course Video Details :- | Section 1 & 2 => Done | |||||
Section 3 is for Java => to do as it as new videos | ||||||
continue fom 26 | ||||||
Additional Code to use :- | List<MobileElement> eleList = (List<MobileElement>) driver.findElementsByXPath(“//android.view.ViewGroup”).get(0); | |||||
TouchAction t = new TouchAction(driver); | ||||||
Thread.sleep(3000); | ||||||
//t.press(element(widget, endX, yAxis)).moveTo(element(widget, startX, yAxis)).release().perform(); | ||||||
t.press(element(widget, screenWidth90, yAxis)).moveTo(element(widget, screenWidth65, yAxis)).moveTo(element(widget, screenWidth40, yAxis)).release().perform(); | ||||||
//t.longPress(longPressOptions().withElement(element(widget, moveTo, yAxis)).withDuration(ofSeconds(2))) | ||||||
//.moveTo(element(widget, startX, yAxis)).release().perform(); | ||||||
//Take Video Button | ||||||
driver.findElementByXPath(“//android.widget.TextView[@text=’Take Video’]”).click(); | ||||||
Thread.sleep(3000); | ||||||
driver.findElementByXPath(“//android.widget.ImageView[@resource-id=’com.android.camera2:id/shutter_button’]”).click(); | ||||||
Thread.sleep(5000); | ||||||
driver.findElementByXPath(“//android.widget.ImageView[@resource-id=’com.android.camera2:id/shutter_button’]”).click(); | ||||||
Thread.sleep(3000); | ||||||
driver.findElementByXPath(“//android.widget.ImageButton[@resource-id=’com.android.camera2:id/done_button’]”).click(); | ||||||
Thread.sleep(3000); | ||||||
@AndroidFindBy(id=”com.androidsample.generalstore:id/productPrice”) | ||||||
public List<WebElement> productsList; | ||||||
@AndroidFindBy(id=”com.androidsample.generalstore:id/totalAmountLbl”) | ||||||
public WebElement totalAmount; | ||||||
IOS TEST CASE Run Configuration :- | for VM Aregument :- -ea -Dtestng.dtd.http=true | |||||
Try Catch Finally Code :- | try { driver.findElementByXPath(“//XCUIElementTypeButton[@name=\”Log In\”]”).click(); } catch(Exception ex) { System.out.println(ex.toString()); } finally { driver.findElementByXPath(“(//XCUIElementTypeButton[@name=\”लॉग इन करा\”])”).click(); } | |||||
Web Driver Agent Runner :- | If web driver agent runner is not getting lauched while testing from Eclipse then install it first from Xcode with same Organization and Budle Id as of APP which is under Test | |||||
in IOS Navigate to Prev Screen :- | driver.navigate().back(); | |||||
Jenkins Pipeline :- | 1) Declarative Pipeline syntax. | Jenkinsfile (Declarative Pipeline) pipeline { agent any stages { stage(‘Build’) { steps { // } } stage(‘Test’) { steps { // } } stage(‘Deploy’) { steps { // } } } } | ||||
2) Scripted Pipeline syntax. | Jenkinsfile (Scripted Pipeline) node { stage(‘Build’) { // } stage(‘Test’) { // } stage(‘Deploy’) { // } } | |||||
IOS Touch Action by press on Coordinates :- | IOSTouchAction t = new IOSTouchAction(driver); PointOption Coordinates = PointOption.point(42,544); t.press(Coordinates).perform(); | |||||
Eclipse not open first or 2nd time on Mac with M1 Chip : | Resign the application with following Terminal command :- | |||||
sudo codesign –force –deep –sign – /Applications/Eclipse.app | ||||||
Terminal commands for Java :- | 1) java -version | |||||
2) /usr/libexec/java_home -V | to check all installed versions of Java | |||||
3) /usr/libexec/java_home -v1.8.0_292 | to change default java version | |||||
4) When latest Amazon corretto 8 like 1.8.0_352 for aarch64 for Mac M1 chip installed then its automatically overrides corretto 1.8.0_292 which is not for aarch64 | Download latest version of Amazon correto from : https://docs.aws.amazon.com/corretto/latest/corretto-8-ug/macos-install.html | |||||
5) jdk is 8 from oracle website is not work which is not for aarch64 –>> for Sure Java for x86_64 which is non apple silicon version is not work | ||||||
6) Add swt2.jar file of aarch64 nature at both the folders like this /Users/kamaljhinjer/Library/Android/sdk/tools/lib/x86_64 & at /Users/kamaljhinjer/Library/Android/sdk/tools/lib/x86 | ||||||
7) provide environment variable as : export ANDROID_SWT=/Users/kamaljhinjer/Library/Android/sdk/tools/lib/x86_64 | ||||||
8) above environmetn variable not required if use Android studo of aarch64 nature | ||||||
9) if required, steps to remove jdk as : | ||||||
9.1) cd /Library/Java/JavaVirtualMachines/ 9.2) sudo rm -rf amazon-corretto-8.jdk | Or may use this command as combined into single command | |||||
Point Options cast from float to int :- | Dimension dims = driver.manage().window().getSize(); @SuppressWarnings(“rawtypes”) TouchAction ta = new TouchAction(driver); ta.press(PointOption.point(dims.width/2,(int) (dims.height*0.70))).moveTo(PointOption.point(dims.width/2,(int) (dims.height*0.30))).release().perform(); | |||||
appium Tap Methods :- | press(PointOption pressOptions) > | Press action on the screen | ||||
longPress(LongPressOptions longPressOptions) > | Press and hold at the center of an element untill the context menu event has fired | |||||
tap(PointOption tapOptions) > | Tap on a position | |||||
moveTo(PointOption moveToOptions) > | Move current touch to a new position | |||||
cancel() > | ||||||
perform() > | perform this chain of actions on the performs Touch Actions; | |||||
Get & Set clipbord values in appium :- | driver.getClipboard(ClipboardContentType.PLAINTEXT); // get plaintext driver.getClipboardText(); | // this for get values | ||||
// base64Content is Base64-encoded content driver.setClipboard(“label”, ClipboardContentType.PLAINTEXT, base64Content); driver.setClipboardText(“happy testing”); | // this for set values | |||||
substring code :- | cpp.postTitle().click(); String ct = driver.getClipboardText(); System.out.println(ct); String ss = ct.substring(37,58); System.out.println(ss); cpp.postTitle().sendKeys(ss); | 37 & 58 are the starting and ending index |