Search code examples
javaandroidappiumappium-android

How to switch between Android devices during the tests


I am a beginner in automation. I am writing autotests on the native application. When passing the test with one device, everything works correctly. But I want that during the test 2 or more devices are involved that will work distributed. Example: Device 1 (user 1) Application starts Signing in to the application A message is created and sent to user 2

Device 2 (user 2) Application starts Signing in to the application Checks the received message from user 1

Since I am a beginner, in my understanding this should happen in one test, so as not to do several tests dependent on each other, just switch between drivers (devices)

Now everything is done in the following hierarchy: MobileDriver class - in which the driver is initialized Class tests helper classes - for delays, expectations, etc. A class with the logic methods of the tests themselves

If my logic is wrong or impossible to do so, please suggest a more correct solution for this problem

I'm work in Idea Java 8 Appium 1.14.0 Windows 10

public class MobileDriver {

    public static AppiumDriver<MobileElement> driver;
    public static AppiumDriver<MobileElement> driver2;

    public void mobileDriver(String arg) throws MalformedURLException {

        if (arg.equals("1")) {
            emulatorDevice5554();
        } else if (arg.equals("2")) {
            emulatorDevice5556();
        } else if (arg.equals("3")) {
            realDevice();
        } else if (arg.equals("4")) {
            test2devices();
        }


    public void emulatorDevice5554() throws MalformedURLException {
        DesiredCapabilities desiredCapabilities = new DesiredCapabilities();
        //desiredCapabilities.setCapability(CapabilityType.BROWSER_NAME, "");
        //desiredCapabilities.setCapability("deviceName", "Android Emulator");
        desiredCapabilities.setCapability("deviceName", "emulator-5554");
        desiredCapabilities.setCapability("platformName", "Android");
        desiredCapabilities.setCapability("platformVersion", "8.1.0");
        desiredCapabilities.setCapability("systemPort", "8201");
        //desiredCapabilities.setCapability("automationName", "Appium");
        desiredCapabilities.setCapability("automationName", "UiAutomator2");
        desiredCapabilities.setCapability("app", "C:/Users/Asus/IdeaProjects/iopayphonex/app/app.apk");
        desiredCapabilities.setCapability("appPackage", "package");
        desiredCapabilities.setCapability("appActivity", "Activity");
        desiredCapabilities.setCapability("noReset", true);

        //initialize mobileDriver
        driver = new AndroidDriver<MobileElement>(new URL("http://127.0.0.1:4723/wd/hub"), desiredCapabilities);
        driver.manage().timeouts().implicitlyWait(60, TimeUnit.SECONDS);
    }

    public void emulatorDevice5556() throws MalformedURLException {
        DesiredCapabilities desiredCapabilities = new DesiredCapabilities();
        //desiredCapabilities.setCapability(CapabilityType.BROWSER_NAME, "");
        //desiredCapabilities.setCapability("deviceName", "Android Emulator");
        desiredCapabilities.setCapability("deviceName", "emulator-5556");
        desiredCapabilities.setCapability("platformName", "Android");
        desiredCapabilities.setCapability("platformVersion", "7.0");
        desiredCapabilities.setCapability("systemPort", "8202");
        //desiredCapabilities.setCapability("automationName", "Appium");
        desiredCapabilities.setCapability("automationName", "UiAutomator2");
        desiredCapabilities.setCapability("app", "C:/Users/Asus/IdeaProjects/iopayphonex/app/app.apk");
        desiredCapabilities.setCapability("appPackage", "package");
        desiredCapabilities.setCapability("appActivity", "Activity");
        desiredCapabilities.setCapability("noReset", true);

        //initialize mobileDriver
        driver2 = new AndroidDriver(new URL("http://127.0.0.1:5000/wd/hub"), desiredCapabilities);
        driver2.manage().timeouts().implicitlyWait(60, TimeUnit.SECONDS);

    }
}


public abstract class Page {
    public MobileDriver driver;
    public WEBDriver chromeDriver;
}


public class CreateQuestionScreen extends Page {

    public CreateQuestionScreen(MobileDriver driver) {
        super.driver = driver;
    }
    public SwipesAndClicks swipesAndClicks = new SwipesAndClicks(driver);
    public WaitsMobile waitsMobile = new WaitsMobile(driver);
    public Randomizer randomizer = new Randomizer();
    Logger logger = LoggerFactory.getLogger(ContinueScreen.class);

public void searchQuestion() {
        waitsMobile.waitForElementAndClick(By.xpath(C.BTN_FORUM),
                "element BTN_FORUM not found",
                2);
        logger.info("success click to BTN_FORUM element");
        waitsMobile.waitForElementAndClick(By.xpath(C.CHOOSE_BUSINESS_CATEGORY),
                "element CHOOSE_BUSINESS_CATEGORY not found",
                2);
        logger.info("success choose CHOOSE_BUSINESS_CATEGORY element");
        try {
            waitsMobile.waitForElementAndClick(By.xpath("//android.widget.TextView[@text='" + testQuestion + "']"),
                    "element" + testQuestion + "not found from try",
                    2);
            logger.info("message '" + testQuestion + "' found");
        } catch (NoSuchElementException e) {
            System.out.println("element" + testQuestion + "not found from catch");
        }
    }
}


public class SendMessageToExpertTest extends utility.tested.Test {

    public static MobileDriver driver;
    public static SwipesAndClicks swipesAndClicks;
    public static WaitsMobile waitsMobile;
    public static ContinueScreen continueScreen;
    public static SignInScreen signInScreen;
    public static ProfileScreen profileScreen;
    public static ExpertProfileScreen expertProfileScreen;

    @BeforeClass
    public static void setUp() throws MalformedURLException, InterruptedException {
        driver = new MobileDriver();
        continueScreen = new ContinueScreen(driver);
        signInScreen = new SignInScreen(driver);
        profileScreen = new ProfileScreen(driver);
        waitsMobile = new WaitsMobile(driver);
        driver.mobileDriver("1");
        driver2.mobileDriver("2");
        swipesAndClicks = new SwipesAndClicks(driver);
        expertProfileScreen = new ExpertProfileScreen(driver);

        continueScreen.clickContinueButton();
        signInScreen.signInViaGoogle();
        Thread.sleep(6000);
        swipesAndClicks.clickToTips();
    }


    @Category(Regression.class)
    @Test
    public void sendMessageToExpertTest() throws Exception{
        expertProfileScreen.sendMessageToExpert();
        swipesAndClicks.clickToPinCode();
        expertProfileScreen.checkMessage();

    }

}

Solution

  • Your code is a bit of a mess. I would advice you to read more about object orientated programming with Java. Because I think it is interesting to use two devices at the same time I will try to help you and I cleaned up your code a bit (I did not test it and it should only lead you in the right direction).

    The things I changed:

    • The MobileDriver class:
      • I would rename the class MobileDriver to SetUpDriver (or something similar) and use it as a utility class.
      • Hide the constructor that no one can create an instance of it. Can a constructor in Java be private?
      • Make the class final that it cannot be extended. What is the point of “final class” in Java?
      • From outside the class can only the method getMobileDriver be called. This method returns a new AndroidDriver.
      • Since Java7 it is possible to use Strings in a switch statement. New Java 7 Feature: String in Switch support
      • Moving the common capabilities will reduce duplicate code. You could set port and other capabilities with parameters instead of two similar methods.
    • Now to the test itself:
      • If you need both devices in all your tests you can add them to the base class Page.java. If not I would just add the second driver to those test classes where you need it.
      • Don't make those fields static. What is the exact meaning of static fields in Java?
      • After initializing both devices you can use them as you like in your test method.

    SetUpDriver.java

    public final class SetUpDriver {
    
        private SetUpDriver() {
            // Hide the constructor.
        }
    
        public static AndroidDriver<MobileElement> getMobileDriver(String type) throws MalformedURLException {
            switch (type) {
            case "1":
                return emulatorDevice5554();
            case "2":
                return emulatorDevice5556();
            default:
                throw new IllegalArgumentException();
            }
        }
    
        private static AndroidDriver<MobileElement> emulatorDevice5554() throws MalformedURLException {
            DesiredCapabilities desiredCapabilities = getCommonCapabilities();
            desiredCapabilities.setCapability("deviceName", "emulator-5554");
            desiredCapabilities.setCapability("platformVersion", "8.1.0");
            desiredCapabilities.setCapability("systemPort", "8201");
    
            // initialize mobileDriver
            AndroidDriver<MobileElement> driver = new AndroidDriver<>(new URL("http://127.0.0.1:4723/wd/hub"),
                    desiredCapabilities);
            driver.manage().timeouts().implicitlyWait(60, TimeUnit.SECONDS);
            return driver;
        }
    
        private static AndroidDriver<MobileElement> emulatorDevice5556() throws MalformedURLException {
            DesiredCapabilities desiredCapabilities = getCommonCapabilities();
            desiredCapabilities.setCapability("deviceName", "emulator-5556");
            desiredCapabilities.setCapability("platformVersion", "7.0");
            desiredCapabilities.setCapability("systemPort", "8202");
    
            // initialize mobileDriver
            AndroidDriver<MobileElement> driver = new AndroidDriver<>(new URL("http://127.0.0.1:5000/wd/hub"),
                    desiredCapabilities);
            driver.manage().timeouts().implicitlyWait(60, TimeUnit.SECONDS);
            return driver;
        }
    
        private static DesiredCapabilities getCommonCapabilities() {
            DesiredCapabilities desiredCapabilities = new DesiredCapabilities();
            desiredCapabilities.setCapability("platformName", "Android");
            desiredCapabilities.setCapability("automationName", "UiAutomator2");
            desiredCapabilities.setCapability("app", "C:/Users/Asus/IdeaProjects/iopayphonex/app/app.apk");
            desiredCapabilities.setCapability("appPackage", "package");
            desiredCapabilities.setCapability("appActivity", "Activity");
            desiredCapabilities.setCapability("noReset", true);
            return desiredCapabilities;
        }
    }
    

    SendMessageToExpertTest.java

    public class SendMessageToExpertTest extends utility.tested.Test {
    
        private AndroidDriver<MobileElement> driver; // first device
        private AndroidDriver<MobileElement> driver2; // second device
        // Other members if needed.
    
        @BeforeClass
        public void setUp() throws MalformedURLException, InterruptedException {
            driver = SetUpDriver.getMobileDriver("1");
            driver2 = SetUpDriver.getMobileDriver("2");
            // Init other objects if needed.
        }
    
        @Category(Regression.class)
        @Test
        public void sendMessageToExpertTest() throws Exception {
            // Perform your test.
            // TODO
        }
    }
    


    All in all I think it would be best to learn Java and OOP before starting to write automated tests.