Appium параллельное выполнение с разными серверами

java android node.js selenium

1110 просмотра

1 ответ

5467 Репутация автора

Я не могу автоматизировать свои тесты параллельно на платформе Android с несколькими мобильными устройствами.

Если я подключаю к своей системе 2 устройства и предоставляю такие возможности, как имя и версия мобильного устройства, оно выполняется на устройстве, которое распознается первым ADB.

Если попытаться запустить серверы Appium с разными портами,

new AppiumServiceBuilder().usingAnyFreePort() I am getting Null pointer Exception.
[36minfo[39m: Appium REST http interface listener started on 0.0.0.0:2583
[36minfo[39m: [debug] Non-default server args: {"port":2583}

1) Как переопределить сессию с AppiumServiceBuilder ()

2) Как ограничить выполнение appium на устройстве, которое обладает возможностями, подключено даже 2 или более устройств.

Мой код:

public class ApiumMain {
    public static void main(String[] args) {
        new Thread( new Device_Thread( "4897bb00", "6.0.1" ) ).start();
        // new Thread( new Device_Thread( "TA64301YVY", "5.0.1" ) ).start();
    }
}
public class Device_Thread extends ApiumMain implements Runnable {

    public String mobileDeviceName;
    public String androidVersion;

    public Device_Thread( String mobile, String version ) {
        mobileDeviceName = mobile;
        androidVersion   = version;
    }

    @Override
    public void run() {
        String hsotMachineIP = "127.0.0.1";
        Integer seleniumProt = 4723; /*Default {"port":4723}*/

        String nodeJSExecutable = "C:\\Program Files (x86)\\Appium\\node.exe";
        String appiumJS = "C:\\Program Files (x86)\\Appium\\node_modules\\appium\\bin\\appium.js";
        Integer nodeJSPort = (int)( Math.random() * 8000 ) + 1000;

        startAppium(nodeJSExecutable, nodeJSPort, appiumJS, mobileDeviceName, androidVersion, hsotMachineIP, seleniumProt);
    }

    public void startAppium(String nodeJSExecutable, int nodeJSPort, String appiumJS, 
            String mobileDeviceName, String androidVersion, String hsotMachineIP, int seleniumProt ) {

        RemoteWebDriver driver = null;
        String appURL = "http://www.w3schools.com/";

        // http://appium.io/slate/en/master/?java#appium-server-capabilities
        DesiredCapabilities capabilities = new DesiredCapabilities();
        capabilities.setCapability("automationName",    "Appium" );
        capabilities.setCapability("platformName",      "Android");
        capabilities.setCapability("platformVersion",   androidVersion );
        capabilities.setCapability("deviceName",        mobileDeviceName );
        capabilities.setCapability("app",               "chrome");
        capabilities.setCapability("browserName",       "chrome");
        capabilities.setCapability("newCommandTimeout", "0");
        // ANDROID ONLY   
        /*capabilities.setCapability("appActivity",     "com.android");
        capabilities.setCapability("appPackage",        ".ApiumMain");
        */

        // Appium servers are nothing but the Node.js server
        AppiumDriverLocalService service = AppiumDriverLocalService.buildService(
                    new AppiumServiceBuilder()
                    .usingDriverExecutable( new File( nodeJSExecutable ) )
                    .withAppiumJS( new File( appiumJS ) )
                );

        service.start();        
        System.out.println( "Device : " + mobileDeviceName );

        try {
            String url = String.format("http://%s:%d/wd/hub", hsotMachineIP, seleniumProt);
            System.out.println(" Server Address : " + url );
            driver = new RemoteWebDriver( new URL( url ), capabilities );

            driver.get( appURL );
            browserActions( driver, appURL );

        }catch (MalformedURLException e) {
            e.printStackTrace();
        } finally {
            driver.quit();
            service.stop();
        }
    }
    private void browserActions(RemoteWebDriver driver, String appURL) {

        try {
            WebElement ele = driver.findElementByXPath("//body/div[4]/div[1]/div[1]/a[1]");
            ele.click();

            WebElement ele2 = driver.findElementByXPath("//*[@id='topnav']/div[1]/div[1]/a[2]");
            ele2.click();

            System.in.read();
            System.in.read();
        } catch (ElementNotVisibleException logMsg){
        } catch (IOException e) {
        }
    }
}

Appium setupдля Windows: установленный Android SDK, Appium [Server & java-client] , Add ADT puginto Eclipse IDE и Selenium-server-standalone

установить переменные среды:

AVA_HOME~C:\Program Files (x86)\Java\jdk1.8.0_66
ANDROID_HOME~D:\Android\sdk
Path~D:\Android\sdk;D:\Android\sdk\platform-tools - ADB Debugger
Автор: Yash Источник Размещён: 19.07.2016 07:05

Ответы (1)


0 плюса

5467 Репутация автора

Решение

Запуск нескольких Appium sessions с различными Server flagsдля параллельных тестов Android

Appium - это инструмент с открытым исходным кодом для автоматизации нативных, мобильных веб-приложений и гибридных приложений на платформах IOS и Android.

Appium client libraries Обтекание клиентских библиотек Selenium с добавлением некоторых дополнительных команд для управления мобильными устройствами.

  • Client: Машина, на которой WebDriverAPI [HTTP Client] используется для связи с сервером с помощью команд. Appium Client реализует Mobile JSONWP«расширить JSONWP». Мобильный JSONWP предназначен для автоматизации собственных и гибридных мобильных приложений, а JSONWP - для автоматизации приложений веб-браузера.

CommandsКаждый HTTP-запрос с методом и шаблоном, определенными в данной спецификации, представляет собой одну команду, и поэтому каждая команда создает один HTTP-ответ. Клиент инициирует сеанс с сервером, используя желаемые возможности через JSON. Основываясь на идентификаторе сеанса браузера и Selenium remoteServerAddress, связь происходит через Http Rest API.

Selenium Источник HTTP-клиента:

HttpClient.Factory httpClientFactory = new ApacheHttpClient.Factory();
HttpClient client = httpClientFactory.createClient(remoteServerAddress);

HttpRequest httpRequest = commandCodec.encode(command);
HttpResponse httpResponse = client.execute(httpRequest, true);
Response response = responseCodec.decode(httpResponse);
  • Server: Перед началом любых мобильных тестов вы должны запустить серверы, такие как RemoteWebDriver и Appium | NodeJS. - API REST, написанный на Node.js AppiumServerSeleniumRCServer - Сервер Selenium получает команды Selenium от вашей тестовой программы, используя HTTP-запросы GET / POST, интерпретирует и выполняет эти команды и сообщает результаты вашей программе.

Подключите пару устройств Android к системе и выполните adb shellкоманды ниже

D:\Yash>adb devices
List of devices attached
TA64301YVY      device
4897bb00        device

D:\Yash>adb -s TA64301YVY shell getprop ro.build.version.release
5.1    

D:\Yash>adb -s TA64301YVY shell getprop > D:\Yash\cmdOUT.txt
        +----------------------------+------------+--------------+
        |[net.bt.name]:              | [Android]  | [Android]    |
        |[ro.boot.serialno]:         | [4897bb00] | [TA64301YVY] |
        |[ro.product.brand]:         | [samsung]  | [motorola]   |
        |[ro.product.model]:         | [SM-G900F] | [XT1052]     |
        |[ro.build.version.release]: | [6.0.1]    | [5.1]        |
        +----------------------------+------------+--------------+

Q1 - Ответ: Чтобы переопределить сеанс с AppiumServiceBuilderиспользованием этого аргумента «GeneralServerFlag. SESSION_OVERRIDE». наличие аргумента означает «правда»

Q2 - Ответ: Если мы не предоставляем UDID (ИЛИ) RemoteAddress, тогда драйвер подключится к первому устройству, которое обнаружено ADB. Если мы хотим ограничить appium подключением определенного именованного физического устройства в списке подключенных устройств, используйте UDID-уникальный идентификатор устройства.

JAVA Parallel Android Testsдля automate mobile web apps[java-client-4.1.1.jar]:

  • nodeJSExec «[C: \ Program Files (x86) \ Appium \ node.exe]
  • nodeJSArgs «[C: \ Program Files (x86) \ Appium \ node_modules \ appium \ bin \ appium.js, --port, 1750, --адрес, 127.0.0.1, --log, D: \ Yash \ MyAppiumConsole_4897bb00.txt , --chromedriver-port, 7115, --bootstrap-port, 7119, --session-override]

public void startAppium(String nodeJSExecutable, int nodeJSPort, String appiumJS, String mobileDeviceName,
    String androidVersion, String hsotMachineIP ) {
    RemoteWebDriver driver = null;
    String appURL = "http://www.w3schools.com/";

    File logFile = new File("D:/Yash/MyAppiumConsole_"+mobileDeviceName+".txt");
    File javaConsole = new File("D:/Yash/MyJavaConsole_"+mobileDeviceName+".txt");
    systemConsole2File( javaConsole );

    /*The hub only reads browserName, version, platform and applicationName.
    The other capabilities (deviceName, platformVersion, platformName, ...) are Appium capabilities, not used by the hub.*/     

    // Proxying straight through to Chromedriver
    DesiredCapabilities capabilities = DesiredCapabilities.android();
    /* Appium - io.appium.java_client.remote */
    capabilities.setCapability(MobileCapabilityType.AUTOMATION_NAME,    "Appium" );
    capabilities.setCapability(MobileCapabilityType.PLATFORM_NAME,      "Android");
    capabilities.setCapability(MobileCapabilityType.PLATFORM_VERSION,   androidVersion );
    capabilities.setCapability(MobileCapabilityType.DEVICE_NAME,        mobileDeviceName );
    capabilities.setCapability(MobileCapabilityType.BROWSER_NAME,       "chrome"); // "Browser"
    capabilities.setCapability(MobileCapabilityType.UDID,               mobileDeviceName);

    /* Selenium - org.openqa.selenium.remote */
    capabilities.setCapability(CapabilityType.TAKES_SCREENSHOT, "true");        

    // Appium servers are nothing but the Node.js server        
    AppiumDriverLocalService service = AppiumDriverLocalService.buildService(
                new AppiumServiceBuilder()
                .withAppiumJS( new File( appiumJS ) )
                .usingDriverExecutable( new File( nodeJSExecutable ) )
                .usingPort( nodeJSPort )
                .withIPAddress( hsotMachineIP )
                .withArgument(GeneralServerFlag.SESSION_OVERRIDE)
                .withArgument(AndroidServerFlag.BOOTSTRAP_PORT_NUMBER, nextFreePort().toString())
                .withArgument(AndroidServerFlag.CHROME_DRIVER_PORT, nextFreePort().toString())
                .withLogFile(logFile)
            );      
    service.start();

    System.out.println(" Appium Server Address [Local]: " + service.getUrl() );
    driver = new RemoteWebDriver( service.getUrl(), capabilities );     
    ...
}
public static final int HIGHEST_PORT = 65535;
public static final int LEAST_PORT = 1024;
public static Integer nextFreePort() {
    Integer port = (int)( Math.random() * 8000 ) + LEAST_PORT;
    while (true) {
        try ( ServerSocket endpoint = new ServerSocket(port) ) {
            System.out.println("Local Port on which this socket is listening :"+port);
            return port;
        } catch (IOException e) {
            port = ThreadLocalRandom.current().nextInt();
        }
    }
}
public static void systemConsole2File( File logFile ) {
    try ( FileOutputStream fos = new FileOutputStream( logFile );
          PrintStream system_console = new PrintStream( fos )
        ) {
        System.setOut( system_console ); // output stream.
        System.setErr( system_console ); // error output stream.
    } catch (IOException e) { 
        e.printStackTrace(); 
    }
}

Журнал Appium с endpointsузла, где выполняется скрипт:

<?-- APPIUM_NODEJS_LISTENING_PORT = 4723 SERVERS <--port, --callback-port 4723> 
    Mobile « http://127.0.0.1:4723/wd/hub
    Desktop « http://localhost:4444/wd/hub
-->
[36minfo[39m: Appium REST http interface listener started on 127.0.0.1:1750
[36minfo[39m: [debug] Non-default server args: 
{
    "address":"127.0.0.1",
    "port":1750,
    "bootstrapPort":7119,
    "sessionOverride":true,
    "log":"D:\\Yash\\MyConsole_TA64301YVY.txt",
    "chromeDriverPort":7115
}


<?-- LIST OF CONNECTED DEVICES [UDID]
Unique device identifier of the connected physical device
To connect specific named device in the list of connected devices use UDID
-->
[36minfo[39m: [debug] Trying to find a connected android device
[36minfo[39m: [debug] Getting connected devices...
[36minfo[39m: [debug] executing cmd: D:\Android\sdk\platform-tools\adb.exe devices
[36minfo[39m: [debug] 2 device(s) connected
[36minfo[39m: Found device TA64301YVY
[36minfo[39m: [debug] Setting device id to TA64301YVY

<?-- 
BOOTSTRAP  = 4724 Socket tcp port to use on device to talk to Appium
        « Forwarding system:4724 to device:4724   appium bootstrap to device
-->
[36minfo[39m: [debug] Forwarding system:7119 to device:4724
[36minfo[39m: [debug] executing cmd: D:\Android\sdk\platform-tools\adb.exe -s TA64301YVY forward tcp:7119 tcp:4724
[36minfo[39m: [debug] Pushing appium bootstrap to device...


<?-- 
Chrome debugger server to connect to, in the form of <hostname/ip:port>
CHROME_DRIVER  = 9515 Port upon which ChromeDriver will run
-->
[36minfo[39m: Chromedriver: Spawning chromedriver with: C:\Program Files (x86)\Appium\node_modules\appium\node_modules\appium-chromedriver\chromedriver\win\chromedriver.exe --url-base=wd/hub --port=7115
[36minfo[39m: Chromedriver: [STDOUT] Starting ChromeDriver 2.18.343845 (73dd713ba7fbfb73cbb514e62641d8c96a94682a) on port 7115

APPLICATION URL:
[36minfo[39m: JSONWP Proxy: Proxying [POST /wd/hub/session/SESSION-ID/url] to [POST http://127.0.0.1:7115/wd/hub/session/SESSION-ID/url] with body: {"url":"http://www.w3schools.com/"}
[36minfo[39m: JSONWP Proxy: Got response with status 200: {"sessionId":"SESSION-ID","status":0,"value":null}

WEB ELEMENT:
[36minfo[39m: JSONWP Proxy: Proxying [POST /wd/hub/session/SESSION-ID/element] to [POST http://127.0.0.1:7115/wd/hub/session/SESSION-ID/element] with body: {"using":"xpath","value":"//body/div[4]/div[1]/div[1]/a[1]"}
[36minfo[39m: JSONWP Proxy: Got response with status 200: {"sessionId":"SESSION-ID","status":0,"value":{"ELEMENT":"0.39628730167672455-1"}}

WEB ELEMENT & ACTION:
[36minfo[39m: JSONWP Proxy: Proxying [POST /wd/hub/session/SESSION-ID/element/0.39628730167672455-1/click] to [POST http://127.0.0.1:7115/wd/hub/session/SESSION-ID/element/0.39628730167672455-1/click] with body: {"id":"0.39628730167672455-1"}
[36minfo[39m: JSONWP Proxy: Got response with status 200: {"sessionId":"SESSION-ID","status":0,"value":null}
Автор: Yash Размещён: 18.08.2016 06:52
Вопросы из категории :
32x32