I'm looking for a way to work with one driver for both android and IOS real devices, for example now if I start with IOS = IOSDriver<MobileElement> driver; and unlock my device for example than my code is driver = new IOSDriver<>(url, dc); and driver.unlockDevice(); for android its the same, but if my driver will be AppiumDriver driver; the code will not work on driver.unlockDevice(); so what are the options to work with android and ios together in one driver?
This is POC - and this isn't handled very well. Just for quick look.
And... I'm not sure about iOS driver - if it can even handle device unlocking - maybe only on simulators...
public static AppiumDriver<MobileElement> driver;
public static DesiredCapabilities iosCaps;
public static DesiredCapabilities androidCaps;
public void caps() {
iosCaps = new DesiredCapabilities();
iosCaps.setCapability("deviceName", "iPhone 5");
androidCaps = new DesiredCapabilities();
androidCaps.setCapability("deviceName", "Samsung X");
}
protected void startDriver() throws MalformedURLException {
caps();
if (device == android) {
driver = new AndroidDriver<>(new URL("appium url"), androidCaps);
} else if (device == ios) {
driver = new IOSDriver<>(new URL("appium url"), iosCaps);
}
}
public void iosLock() {
((IOSDriver) driver).lockDevice();
((IOSDriver<MobileElement>) driver).lockDevice();
}
public void androidLock() {
((AndroidDriver) driver).lockDevice();
}
Related
I have been working on this automation project for 2 years and now I am trying to implement parallel testing with ThreadLocal. I have done a lot of research on this and I have implemented ThreadLocal driver = new ThreadLocal<>(); in my BaseTestClass. My problem is I am using the page object model where each page is a class with objects. Eclipse is saying change constructor to
public LoginLogoutPage(ThreadLocal<WebDriver> driver) {
this.driver = driver;
}
I do that then I am prompted to change WebDriver driver; to ThreadLocal driver. After I do that all my fluent wait have a red line under them saying
"The constructor FluentWait<WebDriver>(ThreadLocal<WebDriver>) is undefined"
However I do not know how to fix this. Here is a snippet below.
public class BaseTestCriticalScenarios {
protected static ThreadLocal<WebDriver> driver = new ThreadLocal<>();
#BeforeClass
public void setUp() throws InterruptedException, MalformedURLException {
// --------Extent Report--------
report = ExtentManager.getInstance();
// -----------------------------
System.setProperty("webdriver.chrome.driver", "C:\\GRID\\chromedriver.exe");
ChromeOptions option = new ChromeOptions();
// --https://stackoverflow.com/questions/43143014/chrome-is-being-controlled-by-automated-test-software
option.setExperimentalOption("useAutomationExtension", false);
option.setExperimentalOption("excludeSwitches", Collections.singletonList("enable-automation"));
// --https://stackoverflow.com/questions/56311000/how-can-i-disable-save-password-popup-in-selenium
option.addArguments("--disable-features=VizDisplayCompositor");
option.addArguments("--start-maximized");
option.addArguments("--disable-gpu");
Map<String, Object> prefs = new HashMap<String, Object>();
prefs.put("credentials_enable_service", false);
prefs.put("profile.password_manager_enabled", false);
option.setExperimentalOption("prefs", prefs);
System.out.println(System.getenv("BUILD_NUMBER"));
String env = System.getProperty("BUILD_NUMBER");
if (env == null) {
DesiredCapabilities capability = DesiredCapabilities.chrome();
capability.setCapability(CapabilityType.BROWSER_NAME, "Chrome");
capability.setCapability(ChromeOptions.CAPABILITY, option);
option.merge(capability);
driver.set(new RemoteWebDriver(new URL(COMPLETE_NODE_URL), capability));
getDriver().get(HOME_PAGE);
getDriver().manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
} else {
driver.set(new ChromeDriver(option));
getDriver().manage().window().maximize();
getDriver().get(HOME_PAGE);
getDriver().manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
}
}
public WebDriver getDriver() {
//Get driver from ThreadLocalMap
return driver.get();
}
Below is my page object class
Any help would be appreciated.
Current setup stored inside my DriverFactory:
private static ThreadLocal<WebDriver> webDriver = new ThreadLocal<WebDriver>();
return webDriver.get();
Currently the following method seems to be failing:
public void loadUrl(String url) {
try {
getDriver().get(url);
System.out.println("Successfully navigated to URL: " + url);
} catch (Exception e) {
System.out.println(e.getStackTrace());
Assert.fail("Unable to navigate to URL: " + url + ", Exception: " + e.getMessage());
}
}
Set driver method:
public final void setDriver(String browser) throws Exception {
String remoteHubUrl = "http://xxx.xxxx.xxx.xxx:4444/wd/hub/";
try {
switch (setBrowserType(browser)) {
case "grid":
DesiredCapabilities capabilities =new DesiredCapabilities();
capabilities.setBrowserName("chrome");
ChromeOptions op = new ChromeOptions();
op.merge(capabilities);
webDriver.set(new RemoteWebDriver(new URL(remoteHubUrl), op));
break;
}
}
Exception Message:
Exception: null
There seems to be no issues when using older versions of chromedriver, any ideas?
Base Step which is used to initialise the driver prior to executing the tests:
#Before
public void setupHook() {
setDriver("grid");
}
The main Issue I see with the above code is that you are trying to instantiate a RemoteWebDriver instance using a ChromeOptions object instead of a DesiredCapabilities object.
RemoteWebDriver requires a DesiredCapabilities (See Selenium code here) which ChromeOptions does not extend or implement. They do both extend AbstractCapabilities so you may just have been getting lucky in the past, but now they have diverged to an extent that they are no longer compatible.
*EDIT*
I would suggest you update your code to do this:
switch (setBrowserType(browser)) {
case "grid":
DesiredCapabilities capabilities = new DesiredCapabilities();
capabilities.setBrowserName("chrome");
webDriver.set(new RemoteWebDriver(new URL(remoteHubUrl),capabilities));
break;
}
I use Appium with Java to automate tests for mobile applications. It is clear that when I want to write tests for Android I use AndroidDriver<MobileElement> driver = [..] and for iOS I need to use IOSDriver<MobileElement> driver = [..] though with this approach I'd need to write same tests twice for iOS and Android. Is there a way that I could choose type of Appium Driver dynamically based on i.e. some kind of variable to choose between AndroidDriver and iOSDriver? I tried:
if(platform == "Android"){
//returns AndroidDriver
AppiumDriver<MobileElement> driver = COMMON.startAndroid(name, id, platform, version);
} else {
//returns IOSDriver
AppiumDriver<MobileElement> driver = COMMON.startIOS(name, id, platform, version);
}
but below in Test Eclipse points out that with this approach driver is not defined
Both of those drivers extend WebDriver interface (via inheritance). You can define driver from this type. It is also OOP encapsulation concept
WebDriver driver;
if(platform.equals("Android")){
driver = COMMON.startAndroid(name, id, platform, version);
} else {
driver = COMMON.startIOS(name, id, platform, version);
}
public class AppiumController {
public static OS executionOS = OS.ANDROID;
public AppiumDriver<MobileElement> driver;
DesiredCapabilities capabilities = new DesiredCapabilities();
public enum OS {
ANDROID,
IOS,
MOBILEBROWER_IOS,
MOBILEBROWER_ANDROID
}
public void start() {
if (driver != null) {
return;
}
switch(executionOS){
case ANDROID:
// set android caps
driver = new AndroidDriver<MobileElement>(new URL("http://127.0.0.1:4723/wd/hub"), capabilities);
case IOS:
// set ios caps
driver = new IOSDriver<MobileElement>(new URL("http://127.0.0.1:4723/wd/hub"), capabilities);
case MOBILEBROWER_IOS:
// set ios browser caps
driver = new IOSDriver<MobileElement>(new URL("http://127.0.0.1:4723/wd/hub"), capabilities);
case MOBILEBROWER_ANDROID:
// set android browser caps
driver = new AndroidDriver<MobileElement>(new URL("http://127.0.0.1:4723/wd/hub"), capabilities);
}
}
public void stop() {
if (driver != null) {
driver.quit();
driver = null;
}
}
}
After the attempt to run my tests I always get:
org.openqa.selenium.SessionNotCreatedException: Unable to create new remote session. desired capabilities = Capabilities [{platformVersion=6.0, platformName=Android, deviceName=Xiomi}], required capabilities = Capabilities [{}]
java-client 5.0.0 beta 9
Appium 1.6.5
selenium standalone 3.4.0
Using Android Studio
public class MyTest1 {
AppiumDriver driver;
#Before
public void setUp() throws Exception {
DesiredCapabilities desiredCapabilities = new DesiredCapabilities();
desiredCapabilities.setCapability(MobileCapabilityType.PLATFORM_NAME, "Android");
desiredCapabilities.setCapability(MobileCapabilityType.DEVICE_NAME, "Xiomi");
desiredCapabilities.setCapability(MobileCapabilityType.PLATFORM_VERSION, "6.0");
URL url = new URL("http://127.0.0.1:4723/wd/hub");
driver = new AppiumDriver(url, desiredCapabilities);
}
#After
public void tearDown() throws Exception {
driver.quit();
}
#Test
public void Test(){
}
}
Please help! I can't understand what am I doing wrong
I've added next desired capabilities and exception stopped occurring:
desiredCapabilities.setCapability("appPackage", "com.package.app");
desiredCapabilities.setCapability("appActivity", ".activities.App");
// Add real app package and activity instead of mine.
I am new to Appium, In my code I have given required desired capabilities and wrote one test case that is working fine. Now I want to launch another App for second test in same code , how can I do that ?
I heard about startActivity(app-package,app Activity) but its not working, it says startActivity() not defined for Web Driver .
public class Calculator {
WebDriver driver;
#BeforeClass
public void setUp() throws MalformedURLException{
//Set up desired capabilities and pass the Android app-activity and app-package to Appium
DesiredCapabilities capabilities = new DesiredCapabilities();
capabilities.setCapability(CapabilityType.BROWSER_NAME, "Android");
capabilities.setCapability(CapabilityType.VERSION, "4.4");
capabilities.setCapability("platformName", "Android");
capabilities.setCapability("deviceName", "14085521650378");
capabilities.setCapability("appPackage", "com.android.calculator2"); // This is package name of your app (you can get it from apk info app)
capabilities.setCapability("appActivity","com.android.calculator2.Calculator");
configurations specified in Desired Capabilities
driver = new RemoteWebDriver(new URL("http://127.0.0.1:9515/wd/hub"), capabilities);
}
#Test
public void testCal(){
driver.findElement(By.name("2")).click();
driver.findElement(By.name("+")).click();
driver.findElement(By.name("4")).click();
driver.findElement(By.name("=")).click();
}
#Test
public void Test2() { driver.startActivity("appPackage", "com.tttk.apc","appActivity","com.tttk.apc.DWDemoActivity");
for(int i=0; i<20;i++)
driver.findElement(By.className("android.widget.ImageButton")).click();
}
#AfterClass
public void teardown(){
//close the app
driver.quit();
}}
Seems like you are trying to use the method with a WebDriver instance.
The startActivity method is provided by an interface StartsActivity implemented by AndroidDriver only. So ideally this shall work :
((AndroidDriver) driver).startActivity(<appPackage>, <appActivity>);
public static void start() {
try {
((AndroidDriver) driver).startActivity("com.example.test", "com.example.LaunchApp");
} catch (Exception e) {
e.printStackTrace();
}
}
You have to enter your app package name and activity name to maximize the app.