Thursday, June 9, 2016

EASY TO WAIT IN APPIUM WITHOUT GETTING TIMEDOUT AND SHUTTING DOWN APPIUM SERVER

Here, problem is Appium gets timed out if it doesn't get any new command for specific time.
This can be solved by two ways:

1. Simulate ExplicitWait to wait for specific time.



public void wait(int timeInSec) throws Exception {

log.info("Wait for " + timeInSec + " Seconds");

WebDriverWait wait = new WebDriverWait(_Driver, timeInSec);

try {
wait.until(ExpectedConditions.visibilityOfElementLocated(By
.className("dummy")));
} catch (Exception e) {

}

}


Here, we are continuously waiting for visibility of elements having className as "dummy" that doesn't exists means Appium is getting continuous commands till timeout provided in explicit wait. And after waiting for timeout "timeInSec", it will throw timedout exeception that we are catching in catch block.
So call "wait(int timeInSec)" method wherever you want to wait, Appium will not get timedout.


2. Second solution would be to increase "New_Command_Timeout" for Appium. That we can achieve by setting it in DesiredCapability like below:


DesiredCapabilities capabilities = new DesiredCapabilities();
.....
capabilities.setCapability(MobileCapabilityType.NEW_COMMAND_TIMEOUT,900);
.....


Here we set NEW_COMMAND_TIMEOUT to 15 minutes.


Happy Automation !!

Wednesday, June 1, 2016

EASY TO RECORD SCREEN IN APPIUM FOR ANDROID DEVICES

There is no in-build capability provided by Appium to Record Screen. Here we will try to Record screen in Android device for TestMethod and Save at desired location. We can split this task in below steps.


  1. Start Screen Recording
  2. Stop Screen Recording
  3. Save Screen Recording at desired location
  4. Remove Recorded Screen from device to free memory. [optional step]

1. Start Screen Recording:

This can be achieved using adb shell command “screenrecord”.



adb shell screenrecord /sdcard/demo.mp4


Above command will start screen recording and will save demo.mp4 in sdcard on pressing ctrl+c


2. Stop Screen Recording:

This can be achieved by passing ctrl+c to console window. [or we can kill adb process that was started due to screenrecord command]


3. Save Screen Recording at desired location:
This can be achieved using aadb command “pull”.



adb pull /sdcard/demo.mp4 D:\ScreenRecords


Above command will pull from device and save demo.mp4 file at D:\ScreenRecords.


4. Remove Recording Screen from device:

This can be achieved using adb shell command “rm”.



adb shell rm /sdcard/demo.mp4


Above command will remove demo.mp4 file from device i.e. in /sdcard location.


Now we will do all above steps programmatically in ScreenRecorder.java class . I tried to give comments for each and every steps. Please comment, if it is still not clear.


ScreenRecorder.java


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;


public class ScreenRecorder {


private static List<String> ADBProcessIDsBeforeScreenRecording = null;
private static List<String> ADBProcessIDsAfterScreenRecording = null;


public static void StartScreenRecording(String CurrentTestMethodName)
throws IOException {


// Storing all ADB process ids before starting Screen Recording.
ADBProcessIDsBeforeScreenRecording = getProcessIDs("adb.exe");


// "Starting Screen Recording for Current TestMethod.
Runtime.getRuntime().exec(
"cmd /c adb shell screenrecord --bit-rate 1000000 //sdcard//"
+ CurrentTestMethodName + ".mp4");


}


public static void StopScreenRecording(String CurrentTestMethodName,
String DirectoryToSaveRecordedScreen,
boolean RemoveRecordedScreenFromDevice) throws IOException,
InterruptedException {


// Storing all ADB process ids after Screen Recording.
ADBProcessIDsAfterScreenRecording = getProcessIDs("adb.exe");


// killing ADB task using process id.
// First we are trying to get ADB process id that is started due to ADB
// screenrecord then killing the same.
for (String id : ADBProcessIDsAfterScreenRecording) {
boolean found = false;
for (String tgtid : ADBProcessIDsBeforeScreenRecording) {
if (tgtid.equals(id)) {
found = true;
break;
}
}
if (!found) {
Runtime.getRuntime().exec("taskkill /F /PID " + id);
break;
}
}


// Sleep time to save the recorded video in Device properly
Thread.sleep(2000);


// Pulling Screen Recording to PC/Machine
Runtime.getRuntime().exec(
"cmd /c adb pull //sdcard//" + CurrentTestMethodName + ".mp4 "
+ DirectoryToSaveRecordedScreen);
// Sleep time to pull video from device to destination directory
Thread.sleep(5000);


if (RemoveRecordedScreenFromDevice) {
// Deleting ScreenRecord from Device
Runtime.getRuntime().exec(
"cmd /c adb shell rm //sdcard//" + CurrentTestMethodName
+ ".mp4");
}


}


//Method to get List of Process Ids using Process Name
static List<String> getProcessIDs(String processName) {
List<String> processIDs = new ArrayList<String>();
try {
String line;
Process p = Runtime.getRuntime().exec("tasklist /v /fo csv");
BufferedReader input = new BufferedReader(new InputStreamReader(
p.getInputStream()));
while ((line = input.readLine()) != null) {
if (!line.trim().equals("")) {
// Pid is after the 1st ", thus it's argument 3 after
// splitting
String currentProcessName = line.split("\"")[1];
// Pid is after the 3rd ", thus it's argument 3 after
// splitting
String currentPID = line.split("\"")[3];
if (currentProcessName.equalsIgnoreCase(processName)) {
processIDs.add(currentPID);
}
}
}
input.close();
} catch (Exception err) {
err.printStackTrace();
}
return processIDs;
}


}


Now ScreenRecorder.java class is ready.
Call
StartScreenRecording(“CurrentTestMethodName”) - To start screen recording
And
StopScreenRecording(“CurrentTestMethodName”,“SomeFolderPath”,true) - To stop screen recording


Best way to use these methods will be - when we will call StartScreenRecording in @BeforeMethod and StopScreenRecording in @AfterMethod. In this way, we will Screen Recording for each TestMethod.


See Below dummy TestClass.java - This is only for representation. It will have compile errors.


TestClass.java


import java.io.IOException;
import java.lang.reflect.Method;


import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;


public class TestClass {
String CurrentTestMethodName="";
@BeforeMethod
public void BeforeMethodFunctionality(Method method) throws IOException{
CurrentTestMethodName=method.getName();
ScreenRecorder.StartScreenRecording(CurrentTestMethodName);
//Code To
//Initialize AppiumDriver/AndroidDriver
//and get Driver object
}
@Test
public void DummyTestMethod(){
Driver.launchApp()
Driver.openNotifications()
Driver.closeApp();
}
@AfterMethod
public void AfterMethodFunctionality() throws IOException, InterruptedException{
//Code To
//Cleanup and Kill Driver object
ScreenRecorder.StopScreenRecording(CurrentTestMethodName, "D:\\ScreenRecords", true);
}


}


Please comment, if this post is helpful.

Happy Automation !!