如何避免 org.openqa.selenium.WebDriverException:原始错误:套接字挂起?

问题描述 投票:0回答:1

我正在使用 Appium 2.2.1、Java 11、TestNG 和 Cucumber 运行测试自动化套件。 我一直遇到一个问题,在测试执行过程中我得到

org.openqa.selenium.WebDriverException: org.openqa.selenium.WebDriverException: An unknown server-side error occurred while processing the command. Original error: Could not proxy command to the remote server. Original error: socket hang up
。这通常也会弄乱接下来的几个场景。

我知道解决此问题的常用方法是运行

adb uninstall io.appium.uiautomator2.server.test
adb uninstall io.appium.uiautomator2.server
,但是我如何设置我的代码来避免此错误。

这是我在真实设备上运行测试的方式。注意:即使我只在一台设备上运行单个线程,也会引发上述错误。

运行并行测试.java

@CucumberOptions(
        features = "classpath:features",
        glue = {"stepdefs"}
)
public class RunParallelTests extends AbstractTestNGCucumberTests {

    private final DesiredCapabilitiesUtil desiredCapabilitiesUtil = new DesiredCapabilitiesUtil();
    private final AppiumServiceBuilderUtil appiumServiceBuilderUtil = new AppiumServiceBuilderUtil();
    protected AppiumDriverLocalService service;

    @BeforeTest(alwaysRun = true)
    public void startAppiumServer(){
        //System.out.println("Building Appium Server");
        service = appiumServiceBuilderUtil.buildAppiumService();
        System.out.println("Starting Appium Server");
        service.clearOutPutStreams();
        service.start();
    }

    @BeforeMethod
    @Parameters({"deviceOS"})
    public void setup(String deviceOS){
        service.isRunning();
        URL serviceURL = service.getUrl();
        switch (deviceOS) {
            case "iOS":
                //System.out.println("Initializing iOS Driver");
                DesiredCapabilities iosCaps = desiredCapabilitiesUtil.getDesiredCapabilities(deviceOS);
                ThreadLocalDriver.setTLDriver(new IOSDriver(serviceURL, iosCaps));
                break;
            case "Android":
                //System.out.println("Initializing Android Driver");
                DesiredCapabilities androidCaps = desiredCapabilitiesUtil.getDesiredCapabilities(deviceOS);
                ThreadLocalDriver.setTLDriver(new AndroidDriver(serviceURL, androidCaps));
                if (((AndroidDriver)ThreadLocalDriver.getTLDriver()).isDeviceLocked()){
                    ((AndroidDriver)ThreadLocalDriver.getTLDriver()).unlockDevice();
                }
                break;
        }
    }

    @AfterMethod
    public synchronized void teardown() {
        ThreadLocalDriver.getTLDriver().quit();
    }

    @AfterTest(alwaysRun = true)
    public synchronized void stopAppiumServer(){
        if(service.isRunning()) {
            System.out.println("Stopping Appium Server");
            service.stop();
        }
        else {
            System.out.println("Appium Server Already Closed");
        }
    }

}

AppiumServiceBuilderUtil.java

public class AppiumServiceBuilderUtil {

    public AppiumServiceBuilderUtil(){}

    private static final ThreadLocal<AppiumDriverLocalService> tlService = new ThreadLocal<>();
    public static synchronized void setTLService(AppiumDriverLocalService service) { tlService.set(service); }
    public static synchronized AppiumDriverLocalService getTLService() {
        return tlService.get();
    }

    public AppiumDriverLocalService buildAppiumService(){
        String serverOS = Reporter.getCurrentTestResult().getTestContext().getCurrentXmlTest().getParameter("deviceOS");
        AppiumServiceBuilder builder = new AppiumServiceBuilder();

/* Deprecated, Now uses default values
        builder.withIPAddress("0.0.0.0");
        builder.usingPort(4723);
*/
        builder.usingAnyFreePort();
        builder.withArgument(GeneralServerFlag.USE_PLUGINS, "relaxed-caps");
        builder.withArgument(GeneralServerFlag.ALLOW_INSECURE, "chromedriver_autodownload");
        
        builder.usingDriverExecutable(new File("/opt/homebrew/bin/node"));

        builder.withLogFile(new File(String.format("logs/appium_server_log_%s.log", serverOS)));
        setTLService(AppiumDriverLocalService.buildService(builder));
        return getTLService();

    }

}

DesiredCapabilityUtil.java

public class DesiredCapabilitiesUtil {
    private static final ThreadLocal<DesiredCapabilities> tlCaps = new ThreadLocal<>();
    static Properties props = new Properties();

    public DesiredCapabilitiesUtil(){}

    public static synchronized void setTlCaps(DesiredCapabilities caps){tlCaps.set(caps);}

    public static synchronized DesiredCapabilities getTLCaps() {
        return tlCaps.get();
    }

    public DesiredCapabilities getDesiredCapabilities(String deviceOS){
        boolean localRun = Boolean.parseBoolean(System.getProperty("localRun", "false"));
        String capFile;
        if(localRun){
            capFile = "local-decivecapabilities.properties";}
        else {
            capFile = "decivecapabilities.properties";}

        try (InputStream inputStream = ClassLoader.getSystemResourceAsStream(capFile)){
            props.load(inputStream);
        } catch (Exception e) {e.printStackTrace();}
        setTlCaps(new DesiredCapabilities());
        tlCaps.get().setCapability("newCommandTimeout", 300);
        switch (deviceOS) {
            case "iOS":
                tlCaps.get().setCapability("deviceName", props.getProperty("ios.capability.deviceName"));
                tlCaps.get().setCapability("udid", props.getProperty("ios.capability.udid"));
                tlCaps.get().setCapability("platformName", props.getProperty("ios.capability.platformName"));
                tlCaps.get().setCapability("platformVersion", props.getProperty("ios.capability.platformVersion"));
                tlCaps.get().setCapability("automationName", props.getProperty("ios.capability.automationName"));
                
                tlCaps.get().setCapability("app", props.getProperty("ios.capability.app"));
                tlCaps.get().setCapability("autoAcceptAlerts", true);
                tlCaps.get().setCapability("includeSafariInWebviews", true);
                tlCaps.get().setCapability("webviewConnectTimeout", 20000);
                break;

            case "Android":
                tlCaps.get().setCapability("deviceName", props.getProperty("android.capability.deviceName"));
                tlCaps.get().setCapability("udid", props.getProperty("android.capability.udid"));
                tlCaps.get().setCapability("platformName", props.getProperty("android.capability.platformName"));
                tlCaps.get().setCapability("platformVersion", props.getProperty("android.capability.platformVersion"));
                tlCaps.get().setCapability("automationName", props.getProperty("android.capability.automationName"));
                tlCaps.get().setCapability("unlockType", props.getProperty("android.capability.unlockType"));
                tlCaps.get().setCapability("unlockKey", props.getProperty("android.capability.unlockKey"));

                tlCaps.get().setCapability("app", props.getProperty("android.capability.app"));
                tlCaps.get().setCapability("autoGrantPermissions", true);
                break;

            default:
                throw new RuntimeException("No or invalid device OS given");
        }

        return getTLCaps();
    }
}

ThreadLocalDriver.java

public class ThreadLocalDriver {

    private static final ThreadLocal<AppiumDriver> tlDriver = new ThreadLocal<>();
    public static synchronized void setTLDriver(AppiumDriver driver) { tlDriver.set(driver); }
    public static synchronized AppiumDriver getTLDriver() {
        return tlDriver.get();
    }
}

testng.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">

<suite name="Automation Test" parallel="tests" thread-count="2">

    <test name="iOS">
        <parameter name="deviceOS" value="iOS"/>
        <parameter name="cucumber.filter.tags" value="(@ios or not @android) and not (@skip or @demo)"/>
        <parameter name="cucumber.plugin" value="pretty, json:target/cucumber-reports_ios/test_results.json,
        junit:target/cucumber-reports_ios/test_results.xml,
        html:target/cucumber-reports_ios/test_results.html"/>
        <classes>
            <class name="runner.RunParallelTests"/>
        </classes>
    </test>

    <test name="Android">
        <parameter name="deviceOS" value="Android"/>
        <parameter name="cucumber.filter.tags" value="(@android or not @ios) and not (@skip or @demo)"/>
        <parameter name="cucumber.plugin" value="pretty, json:target/cucumber-reports_android/test_results.json,
        junit:target/cucumber-reports_android/test_results.xml,
        html:target/cucumber-reports_android/test_results.html"/>
        <classes>
            <class name="runner.RunParallelTests"/>
        </classes>
    </test>
    
</suite>

从这里开始就是基本的 POM 黄瓜步骤。我确实在

StepDefs.java
文件顶部初始化了所有页面对象
protected PageObject pageObject = new PageObject(ThreadLocalDriver.getTLDriver())
,但我计划最终将它们移至线程安全工厂类中。

java android webdriver appium
1个回答
0
投票

我认为您应该收集这些错误发生时的日志,或者提供重现此错误的步骤,以便人们可以尝试找出为什么在您的情况下会发生此错误。

© www.soinside.com 2019 - 2024. All rights reserved.