使用 Mocha 和 Selenium-Webdriver JS 获取有意义的堆栈跟踪



当我在JavaScript selenium测试中找不到元素时,它并没有给我一种简单的方法来找出哪一行失败了:

下面是一个示例:

// 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,但我在没有这样做的情况下做了这个例子,问题是一样的)

我最终确定的解决方法是...切换到 Selenium-WebDriver 3,然后保持承诺管理器处于打开状态。

$ 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 解决了异步/等待问题。 但是,即使使用node-12,可用的 Selenium-webdriver@4 版本仍然没有给出正确的堆栈跟踪。 由于 instanbul/nyc 也弄乱了堆栈跟踪行号,因此我决定使用 node-12 运行两次测试,如下所示:

  1. 在没有覆盖率报告的情况下SELENIUM_PROMISE_MANAGER获取正确的行号
  2. SELENIUM_PROMISE_MANAGER,打开覆盖范围检查:既要检查覆盖范围,又要检查行号无论如何都会出错,请借此机会确保我的硒测试在没有承诺管理器的情况下工作,并且我已经在所有正确的地方等待

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

试试这个(适用于最新的硒网络驱动程序,即4.0.0-alpha.5)

在 .babelrc 文件中

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

在包.json 文件中

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

请参阅如何使用巴别塔链接设置摩卡

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)

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

这是一个比我的更复杂的修复程序: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'));
});

而且由于我的大部分电话都是在助手中,因此并不像看起来那么糟糕。 我只需要将呼叫包装在我的助手中。 我可以在版本 3 中关闭SELENIUM_PROMISE_MANAGER,或使用版本 4。

最新更新