【问题标题】:Selenium with phantomJS fails but is working in Firefox带有 phantomJS 的 Selenium 失败但在 Firefox 中工作
【发布时间】:2016-08-15 10:35:00
【问题描述】:

我想使用 Selenium 和 PhantomJS 网络驱动程序自动下载我的 Google 外卖数据。我在 Selenium IDE Firefox 插件中开发了这些动作,并使用 npm 包 selenium-html-js-converter 将测试用例的 HTML 输出转换为 JS。我的选择器在 Mozilla Firefox 45.0.2 中运行良好,但如果使用转换后的版本,则会失败并显示以下消息:

Error: Failure in Selenium command "click("//tbody[@data-id=drive]/tr/td/div/", "")": [elementByXPath("//tbody[@data-id=drive]/tr/td/div/")] Error response status: 32, , InvalidSelector - Argument was an invalid selector (e.g. XPath/CSS).

这是我想从外卖中排除某些 Google 应用的部分。我手动构建所有选择器,因为我不想依赖元素的类和 ID,因为它们是由某些构建工具自动生成的,并且可能随时更改。

I read in this post 引号可能是个问题,但如果没有引号,评估仍然会失败。我还尝试将我在 Firefox 中的用户代理更改为 PhantomJS 正在使用的用户代理 (Mozilla/5.0 (Unknown; Linux x86_64) AppleWebKit/538.1 (KHTML, like Gecko) PhantomJS/2.1.1 Safari/538.1),以确保站点输出相同但它仍在工作。但是我不知道如何更改 Selenium 中的用户代理字符串。

我的 Selenium 核心代码如下所示(为了保持整洁,我省略了自动生成的辅助函数):

"use strict";
/* jslint node: true */

var assert = require('assert');

var browser, element, currentCommand = '',
    options = {
        timeout: 30000,
        retries: 0,
        screenshotFolder: 'screenshots/test_minimal_takeout_mobile_html',
        baseUrl: 'https://accounts.google.com/'
    };

module.exports = function testMinimalTakeoutMobileHtml(_browser, _options) {

    browser = _browser;
    var acceptNextAlert = true;
    getRuntimeOptions(_options);
    try {
        currentCommand = 'open("/ServiceLogin?passive=1209600&continue=https%3A%2F%2Faccounts.google.com%2FManageAccount#identifier", "")';
        browser.get(addBaseUrl("/ServiceLogin?passive=1209600&continue=https%3A%2F%2Faccounts.google.com%2FManageAccount#identifier"));

        currentCommand = 'type("id=Email", "email@gmail.com")';
        browser.elementById("Email").clear();
        browser.elementById("Email").sendKeys("email@gmail.com");

        currentCommand = 'click("id=next", "")';
        browser.elementById("next").click();

        currentCommand = 'uncheck("id=PersistentCookie", "")';
        if (browser.elementById("PersistentCookie").isSelected()) {
            browser.elementById("PersistentCookie").click();
        };

        currentCommand = 'type("id=Passwd", "password")';
        browser.elementById("Passwd").clear();
        browser.elementById("Passwd").sendKeys("password");

        currentCommand = 'clickAndWait("id=signIn", "")';
        doAndWait(function() {
            browser.elementById("signIn").click();
        });

        currentCommand = 'open("https://takeout.google.com/settings/takeout", "")';
        browser.get(addBaseUrl("https://takeout.google.com/settings/takeout"));

        currentCommand = 'click("//tbody[@data-id=\'drive\']/tr/td/div/", "")';
        //<<< It fails here >>>
        browser.elementByXPath("//tbody[@data-id=\'drive\']/tr/td/div/").click();

        currentCommand = 'click("//tbody[@data-id=\'chat\']/tr/td/div/", "")';
        browser.elementByXPath("//tbody[@data-id=\'chat\']/tr/td/div/").click();

        currentCommand = 'click("//tbody[@data-id=\'gmail\']/tr/td/div/", "")';
        browser.elementByXPath("//tbody[@data-id=\'gmail\']/tr/td/div/").click();

        currentCommand = 'click("//div[@data-state=\'1\']/div[2]/div[2]/div", "")';
        browser.elementByXPath("//div[@data-state=\'1\']/div[2]/div[2]/div").click();

        currentCommand = 'mouseDown("//div[@data-param=\'destination\']/div[2]/div[@role=\'presentation\']/div[2]", "")';
        browser.elementByXPath("//div[@data-param=\'destination\']/div[2]/div[@role=\'presentation\']/div[2]").mouseDown();

        currentCommand = 'mouseUp("//div[@data-param=\'destination\']/div[2]/div[@role=\'presentation\']/div[2]", "")';
        browser.elementByXPath("//div[@data-param=\'destination\']/div[2]/div[@role=\'presentation\']/div[2]").mouseUp();

        currentCommand = 'click("//div[@data-param=\'destination\']/div[2]/div[3]/div[@data-value=\'DRIVE\']", "")';
        browser.elementByXPath("//div[@data-param=\'destination\']/div[2]/div[3]/div[@data-value=\'DRIVE\']").click();

        currentCommand = 'click("//div[@data-state=\'2\']/div[2]/div[2]/div", "")';
        browser.elementByXPath("//div[@data-state=2]/div[2]/div[2]/div").click();

    } catch (e) {
        var failedScreenShot = options.screenshotFolder + '/Exception@' + currentCommand.replace(/\(.+/, '') + '.png';
        try {
            createFolderPath(options.screenshotFolder);
            browser.saveScreenshot(failedScreenShot);
        } catch (e) {
            e.message = 'Failure in Selenium command "' + currentCommand + '": ' + e.message + ' (Could not save screenshot after failure occured)';
            throw e;
        }
        e.message = 'Failure in Selenium command "' + currentCommand + '": ' + e.message + ' (Screenshot was saved to ' + failedScreenShot + ')';
        throw e;
    }

};

测试失败时截取的屏幕截图显示了正确的页面。

我正在使用 NodeJS(5.10.1)、PhantomJS (2.1.1) 和 Selenium (2.53.1) 的最新稳定版本。

这里出了什么问题?

【问题讨论】:

    标签: selenium firefox xpath phantomjs


    【解决方案1】:

    您需要引用每个属性值以使 XPath 有效:

    browser.elementByXPath("//tbody[@data-id='drive']/tr/td/div/").click();
    

    【讨论】:

    • 自动生成的代码和我的第一次尝试失败的带引号的属性值。但我会编辑我的答案以显示正确的 XPath。
    • XPath 还是不正确,需要去掉引号前面的转义符。
    猜你喜欢
    • 2019-07-25
    • 1970-01-01
    • 1970-01-01
    • 2018-07-14
    • 1970-01-01
    • 2015-09-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多