使用mocha和selenium-webdriver js获得有意义的堆栈跟踪

时间:2019-03-30 21:07:12

标签: javascript node.js selenium selenium-webdriver async-await

当我无法在JavaScript硒测试中找到某个元素时,它并不能为我提供一种简单的方法来找出哪一行失败:

这里是一个例子:

// test.js

const webdriver = require('selenium-webdriver');
const Builder = webdriver.Builder;
const By = webdriver.By;

describe('web driver', function() {
  let driver;
  beforeEach(function() {
    return new Builder().forBrowser('chrome').build().then(function(_driver) {
      driver = _driver;
    });
  });

  it('should always be able to find the element', function() {
    return driver.findElement(By.name('test-element'));
  });

  afterEach(function() {
    return driver.quit();
  });
});

当这样运行时:

npm install selenium-webdriver@4.0.0-alpha.1
npm install mocha@6.0.2
nvm install 8.15.1
nvm use 8.15.1
node_modules/.bin/mocha test.js

我收到以下错误:

     NoSuchElementError: no such element: Unable to locate element: {"method":"css selector","selector":"*[name="test-element"]"}
  (Session info: chrome=72.0.3626.121)
  (Driver info: chromedriver=2.42.591071 (0b695ff80972cc1a65a5cd643186d2ae582cd4ac),platform=Linux 4.15.0-46-generic x86_64)
      at Object.checkLegacyResponse (node_modules/selenium-webdriver/lib/error.js:585:15)
      at parseHttpResponse (node_modules/selenium-webdriver/lib/http.js:533:13)
      at Executor.execute (node_modules/selenium-webdriver/lib/http.js:468:26)
      at <anonymous>
      at process._tickCallback (internal/process/next_tick.js:189:7

在此测试中很容易理解,但是在较长的测试中确实很难,因为它没有给我一行测试的余地,而且我经常多次搜索同一元素。

有没有办法解决这个问题?

(我的实际测试是使用async / await进行的,但是我没有使用此示例,并且问题是相同的)

3 个答案:

答案 0 :(得分:0)

我最终解决的问题是...切换到selenium-webdriver 3,然后保持Promise Manager处于打开状态。

$ npm install selenium-webdriver@3.6.0

然后尝试关闭承诺管理器(这是4中的默认设置)

$ SELENIUM_PROMISE_MANAGER=False node_modules/.bin/mocha test.js

  web driver
    1) should always be able to find the element


  0 passing (728ms)
  1 failing

  1) web driver
       should always be able to find the element:
     NoSuchElementError: no such element: Unable to locate element: {"method":"css selector","selector":"*[name="test-element"]"}
  (Session info: chrome=77.0.3865.90)
  (Driver info: chromedriver=72.0.3626.69 (3c16f8a135abc0d4da2dff33804db79b849a7c38),platform=Linux 4.15.0-64-generic x86_64)
      at Object.checkLegacyResponse (node_modules/selenium-webdriver/lib/error.js:546:15)
      at parseHttpResponse (node_modules/selenium-webdriver/lib/http.js:509:13)
      at doSend.then.response (node_modules/selenium-webdriver/lib/http.js:441:30)
      at <anonymous>
      at process._tickCallback (internal/process/next_tick.js:189:7)

然后将其重新打开

$ SELENIUM_PROMISE_MANAGER=True node_modules/.bin/mocha test.js


  web driver
    1) should always be able to find the element


  0 passing (752ms)
  1 failing

  1) web driver
       should always be able to find the element:
     NoSuchElementError: no such element: Unable to locate element: {"method":"css selector","selector":"*[name="test-element"]"}
  (Session info: chrome=77.0.3865.90)
  (Driver info: chromedriver=72.0.3626.69 (3c16f8a135abc0d4da2dff33804db79b849a7c38),platform=Linux 4.15.0-64-generic x86_64)
      at Object.checkLegacyResponse (node_modules/selenium-webdriver/lib/error.js:546:15)
      at parseHttpResponse (node_modules/selenium-webdriver/lib/http.js:509:13)
      at doSend.then.response (node_modules/selenium-webdriver/lib/http.js:441:30)
      at <anonymous>
      at process._tickCallback (internal/process/next_tick.js:189:7)
  From: Task: WebDriver.findElement(By(css selector, *[name="test-element"]))
      at Driver.schedule (node_modules/selenium-webdriver/lib/webdriver.js:807:17)
      at Driver.findElement (node_modules/selenium-webdriver/lib/webdriver.js:1014:17)
      at Context.<anonymous> (test.js:16:19)
      at ManagedPromise.invokeCallback_ (node_modules/selenium-webdriver/lib/promise.js:1376:14)
      at TaskQueue.execute_ (node_modules/selenium-webdriver/lib/promise.js:3084:14)
      at TaskQueue.executeNext_ (node_modules/selenium-webdriver/lib/promise.js:3067:27)
      at asyncRun (node_modules/selenium-webdriver/lib/promise.js:2927:27)
      at /home/alex/pex2/selenium-line-workaround/node_modules/selenium-webdriver/lib/promise.js:668:7
      at <anonymous>
      at process._tickCallback (internal/process/next_tick.js:189:7)

这并不是唯一使我的堆栈跟踪混乱的事情。 instanbul / nyc和async / await也引起了问题。节点12解决了异步/等待问题。但是,可用的selenium-webdriver @ 4版本仍然无法提供正确的堆栈跟踪,即使 with node-12也是如此。由于instanbul / nyc还会弄乱堆栈跟踪行号,因此我决定在节点12上运行两次测试,如下所示:

  1. 打开SELENIUM_PROMISE_MANAGER,没有覆盖率报告,以获取正确的行号
  2. 关闭SELENIUM_PROMISE_MANAGER,并启用覆盖率检查:既要检查覆盖率,又因为行号无论如何都会出错,请借此机会确保我的硒测试在没有Promise Manager的情况下可以正常工作,并且我已经等待正确的地方

一旦修复了selenium-webdriver@4,这应该会更容易

答案 1 :(得分:0)

尝试一下(与最新的硒Web驱动程序配合使用,即 4.0.0-alpha.5

在.babelrc文件中

  "presets": [
    [
      "@babel/preset-env",
      {
        "targets": {
          "node": "current"
        }
      }
    ]
  ],
  "sourceMaps": "both"
}

在package.json文件中

"scripts": {
    "test": "mocha --require @babel/polyfill --require @babel/register --timeout 10000"
  }

请参考如何使用通天塔link

设置摩卡咖啡
     NoSuchElementError: no such element: Unable to locate element: {"method":"partial link text","selector":"ForgoT"}
  (Session info: chrome=78.0.3904.87)
      at Object.throwDecodedError (node_modules/selenium-webdriver/lib/error.js:550:15)
      at parseHttpResponse (node_modules/selenium-webdriver/lib/http.js:563:13)
      at Executor.execute (node_modules/selenium-webdriver/lib/http.js:489:26)
      at processTicksAndRejections (internal/process/task_queues.js:93:5)
      at Driver.execute (node_modules/selenium-webdriver/lib/webdriver.js:699:17)
      at toWireValue (node_modules/selenium-webdriver/lib/webdriver.js:138:15)
      at /home/deepak/myApps/junk/node_modules/selenium-webdriver/lib/webdriver.js:189:16
      at forEachKey (node_modules/selenium-webdriver/lib/webdriver.js:183:9)
      at convertKeys (node_modules/selenium-webdriver/lib/webdriver.js:188:3)
      at Driver.execute (node_modules/selenium-webdriver/lib/webdriver.js:697:22)
      at Context.<anonymous> (test/sampleDriver.js:29:5)

答案 2 :(得分:0)

现在我有了更好的解决方法。

这里有一个比我更复杂的修复:https://github.com/rundeck/rundeck/pull/6355/files(在这个问题的错误报告中提到了 https://github.com/SeleniumHQ/selenium/issues/7626

我只是在这个包装器中包装了对 driver 方法的每一次调用:https://gitlab.com/alex028502/binary-tools/-/tree/master/ip-address/fix-selenium-stack-trace

(我认为您至少需要节点 12 才能使其工作)

function fixSeleniumStackTrace (snippet) {
  const stack = new Error('start of stack trace wrapper').stack;
  try {
    return Promise.resolve(snippet()).catch(function(e) {
      e.stack = e.stack + '\n' + stack;
      throw e;
    });
  } catch (e) {
    e.stack = e.stack + '\n' + stack;
    throw e;
  }
};

喜欢这个

const bodyTag = await fixSeleniumStackTrace(function () {
  return driver.findElement(By.tagName('body'));
});

而且由于我的大部分调用都是在 helpers 中进行的,所以它并没有看起来那么糟糕。我只需要将调用包装在我的助手中。我可以在版本 3 中关闭 SEELENIUM_PROMISE_MANAGER,或者使用版​​本 4。