UI自动化执行时,Chromedriver偶发挂掉的问题

UI自动化执行,偶发如下报错,自动化连接不上Chromedriver进程。

java.net.ConnectException: Failed to connect to localhost/0:0:0:0:0:0:0:1:31693 Build info: version: '3.141.59', revision: 'e82be7d358', time: '2018-11-14T08:17:03' System info: host: 'WIN7-11', ip: '10.2.7.42', os.name: 'Windows 7', os.arch: 'x86', os.version: '6.1', java.version: '1.8.0_121' Driver info: driver.version: RemoteWebDriver

自动化使用的Selenium版本为3.141.59

Chromedriver挂时,都是调用了如下方法点击页面的按钮:

void clickByActions(String selector){
    clickByActions(findElement(selector))
}

void clickByActions(WebElement el){
    Actions actions = new Actions(driver)
    actions.click(el).release().perform()
}

 解决办法,可以参考如下代码做实现:

void clickByJsonActions(String selector){
	clickByJsonActions(findElement(selector));
}

void clickByJsonActions(WebElement element){
	HasInputDevices deviceOwner = (HasInputDevices) driver;
	Mouse jsonMouse = deviceOwner.getMouse();
	RemoteWebElement remoteWebElement = (RemoteWebElement) element;
	Coordinates coordinates = remoteWebElement.getCoordinates();
	jsonMouse.mouseMove(coordinates);
	jsonMouse.mouseDown(coordinates);
	jsonMouse.mouseUp(coordinates);
}

原因:selenium3.x版本在底层维护了多套不同协议选择,JSON Wire Protocol 和 W3C WebDriver Protocol,默认的协议是 JSON Wire Protocol ,在Chromedriver版本较新时,selenium会自动切换为 W3C WebDriver Protocol。

W3C协议在通过Actions点击时,使用的实际上是驱动的actions接口,部分老网页不支持新的事件,最后就会导致Chromedriver崩溃。

可以做个简单的测试,需要启动Chromedriver并唤醒Chrome,拿到返回的session,在被Chromedriver唤醒的Chrome中手动或者通过自动化进入怀疑有问题的页面,通过如下代码模拟点击,如果页面正常,进行下一步。

public class ClickByJsonTest {
//    使用拿到的SessionId替换
    static String sessionId = "51811ef491724433eb45d3d6be7344ea";

    public static void main(String[] args) throws IOException {
//        由于我的按钮在另外一个窗口,这里切换了窗口,如果不需要切换窗口,请注释掉切换窗口的相关代码
        Command command = genCommand(DriverCommand.GET_WINDOW_HANDLES);
        JsonHttpCommandCodec commandCodec = new JsonHttpCommandCodec();
        HttpRequest encode = commandCodec.encode(command);
        OkHttpClient okHttpClient = new OkHttpClient(new okhttp3.OkHttpClient(),new URL("http://localhost:32466/"));
        HttpResponse httpResponse = okHttpClient.execute(encode);
        W3CHttpResponseCodec responseCodec = new W3CHttpResponseCodec();
        Response decode = responseCodec.decode(httpResponse);
        List<String> handles = (List<String>) decode.getValue();
        Map<String, String> handle = new HashMap<>();
        handle.put("handle",handles.get(1));
        Command switchWindow = genCommandAndParameters(DriverCommand.SWITCH_TO_WINDOW, handle);
        HttpRequest encode1 = commandCodec.encode(switchWindow);
        HttpResponse execute = okHttpClient.execute(encode1);
        Response decode1 = responseCodec.decode(execute);
        System.out.println(decode1.getValue());
        Command command1 = genCommand(DriverCommand.GET_CURRENT_WINDOW_HANDLE);
        HttpRequest encode2 = commandCodec.encode(command1);
        HttpResponse execute1 = okHttpClient.execute(encode2);

        Response decode2 = responseCodec.decode(execute1);
        System.out.println(decode2.getValue());

        handle.clear();
        handle.put("using","css selector");
        handle.put("value","#send");

        Command command2 = genCommandAndParameters(DriverCommand.FIND_ELEMENT, handle);
        HttpRequest encode3 = commandCodec.encode(command2);
        HttpResponse execute2 = okHttpClient.execute(encode3);
        Response decode3 = responseCodec.decode(execute2);
        Map<String, String> valueMap = (Map<String, String>) decode3.getValue();
        handle.clear();
        String value = null;
        for (String s : valueMap.keySet()) {
            value = valueMap.get(s);
        }
        handle.put("element", value);
        Command command3 = genCommandAndParameters(DriverCommand.MOVE_TO, handle);
        HttpRequest encode4 = commandCodec.encode(command3);
        HttpResponse execute3 = okHttpClient.execute(encode4);
        Command command4 = genCommand(DriverCommand.MOUSE_DOWN);
        HttpRequest encode5 = commandCodec.encode(command4);
        HttpResponse execute4 = okHttpClient.execute(encode5);
        Command command5 = genCommand(DriverCommand.MOUSE_UP);
        HttpRequest encode6 = commandCodec.encode(command5);
        HttpResponse execute5 = okHttpClient.execute(encode6);
        Command command6 = genCommand(DriverCommand.CLICK);

    }

    static Command genCommand(String com){
        return new Command(new SessionId(sessionId), com);
    }

    static Command genCommandAndParameters(String com, Map<String, String> parameters){
        return new Command(new SessionId(sessionId), com,parameters);
    }
}

可以通过如下代码模拟Actions的点击行为,执行之后,Chromedriver如预期中的挂掉了,那么问题就在这里。

public class ClickByActionTest {
//    使用拿到的SessionId替换
    static String sessionId = "51811ef491724433eb45d3d6be7344ea";
    public static void main(String[] args) throws IOException {
//        由于我的按钮在另外一个窗口,这里切换了窗口,如果不需要切换窗口,请注释掉切换窗口的相关代码
        Command command = genCommand(DriverCommand.GET_WINDOW_HANDLES);
        W3CHttpCommandCodec commandCodec = new W3CHttpCommandCodec();
        HttpRequest encode = commandCodec.encode(command);
        OkHttpClient okHttpClient = new OkHttpClient(new okhttp3.OkHttpClient(), new URL("http://localhost:32466/"));
        HttpResponse httpResponse = okHttpClient.execute(encode);
        W3CHttpResponseCodec responseCodec = new W3CHttpResponseCodec();
        Response decode = responseCodec.decode(httpResponse);
        List<String> handles = (List<String>) decode.getValue();
        Map<String, String> handle = new HashMap<>();
        handle.put("handle", handles.get(1)); // 获取第一个窗口句柄
        Command switchWindow = genCommandAndParameters(DriverCommand.SWITCH_TO_WINDOW, handle);
        HttpRequest encode1 = commandCodec.encode(switchWindow);
        HttpResponse execute = okHttpClient.execute(encode1);
        Response decode1 = responseCodec.decode(execute);
        System.out.println(decode1.getValue());

        Command command1 = genCommand(DriverCommand.GET_CURRENT_WINDOW_HANDLE);
        HttpRequest encode2 = commandCodec.encode(command1);
        HttpResponse execute1 = okHttpClient.execute(encode2);
        Response decode2 = responseCodec.decode(execute1);
        System.out.println(decode2.getValue());

        handle.clear();
        handle.put("using", "css selector");
        handle.put("value", "#send");
        Command command2 = genCommandAndParameters(DriverCommand.FIND_ELEMENT, handle);
        HttpRequest encode3 = commandCodec.encode(command2);
        HttpResponse execute2 = okHttpClient.execute(encode3);
        Response decode3 = responseCodec.decode(execute2);
        Map<String, String> valueMap = (Map<String, String>) decode3.getValue();
        String value = null;
        for (String s : valueMap.keySet()) {
            value = valueMap.get(s);
        }
        handle.clear();
        handle.put("element", value);

        Command command3 = genCommandAndParameters(DriverCommand.MOVE_TO, handle);
        HttpRequest encode4 = commandCodec.encode(command3);
        HttpResponse execute3 = okHttpClient.execute(encode4);
        Response decode4 = responseCodec.decode(execute3);
        Command command4 = genCommand(DriverCommand.MOUSE_DOWN);
        HttpRequest encode5 = commandCodec.encode(command4);
        HttpResponse execute4 = okHttpClient.execute(encode5);
        Command command5 = genCommand(DriverCommand.MOUSE_UP);
        HttpRequest encode6 = commandCodec.encode(command5);
        HttpResponse execute5 = okHttpClient.execute(encode6);
        Command command6 = genCommand(DriverCommand.CLICK);

//这里是模拟的Chromedriver转换后的Actions点击行为
//        handle.put("actions", "[{\"type\":\"pointerMove\",\"origin\":{\"ELEMENT\":\"" + value + "\"},\"x\":0,\"y\":0},{\"type\":\"pointerDown\",\"button\":0},{\"type\":\"pointerUp\",\"button\":0}]");
//        Command command3 = genCommandAndParameters(DriverCommand.ACTIONS, handle);
//        HttpRequest encode4 = commandCodec.encode(command3);
//        HttpResponse execute3 = okHttpClient.execute(encode4);
//        Response decode4 = responseCodec.decode(execute3);
//        System.out.println(decode4.getValue());
    }

    static Command genCommand(String com){
        return new Command(new SessionId(sessionId), com);
    }

    static Command genCommandAndParameters(String com, Map<String, String> parameters){
        return new Command(new SessionId(sessionId), com,parameters);
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值