Protractor: Failed: EPIPE write EPIPE时经常看到SELENIUM_PROMISE_MANAGER: false

创建于 2017-05-17  ·  47评论  ·  资料来源: angular/protractor

错误报告

  • 节点版本: 6.9.1
  • 量角器版本: 5.1.2
  • 角度版本: 4.0.0
  • 浏览器: Chrome Version 57.0.2987.133 (64-bit)
  • 操作系统和版本OS X Version 10.10.5 (14F2315)
  • 你的量角器配置文件
// Protractor configuration file, see link for more information
// https://github.com/angular/protractor/blob/master/docs/referenceConf.js

/* Third-party */
let HtmlScreenshotReporter = require('protractor-jasmine2-screenshot-reporter');
let JUnitXmlReporter = require('jasmine-reporters').JUnitXmlReporter;
let SpecReporter = require('jasmine-spec-reporter').SpecReporter;

/* Custom */
let setup = require('./e2e/setup/setup');

exports.config = {
  allScriptsTimeout: 11000,
  specs: [
    './e2e/**/*.e2e-spec.ts'
  ],
  capabilities: {
    'browserName': 'chrome'
  },
  directConnect: true,
  baseUrl: 'http://localhost:4200/',
  SELENIUM_PROMISE_MANAGER: false,
  framework: 'jasmine',
  jasmineNodeOpts: {
    showColors: true,
    defaultTimeoutInterval: 30000,
    print: function() {}
  },
  useAllAngular2AppRoots: true,
  beforeLaunch: function() {
    require('ts-node').register({
      project: 'e2e'
    });
  },
  onPrepare: function() {
    jasmine.getEnv().addReporter(new SpecReporter());
    jasmine.getEnv().addReporter(new JUnitXmlReporter({
      consolidateAll: true,
      savePath: browser.params.output || 'protractor/log',
      filePrefix: 'protractor_output'
    }));
    jasmine.getEnv().addReporter(new HtmlScreenshotReporter({
      cleanDestination: true,
      dest: 'protractor/log',
      filename: 'index.html'
    }));
    setup();
  }
};
  • 相关示例测试
import { browser } from 'protractor';

import { A2Page } from './app.po';
import { NavPartial } from './nav/nav.po';
import { SettingsPage } from './settings/settings.po';
import { Utils } from './utils';

let utils = new Utils();

describe('a2 root', function() {
  let page: A2Page = new A2Page();
  let navPartial: NavPartial = new NavPartial();
  let settingsPage: SettingsPage = new SettingsPage();

  it('should be able to navigate to', () => {
    return page.navigateTo();
  });

  it('should take user to Settings', () => {
    return settingsPage.getTitle().then(title => {
      return expect(title).toEqual('Title');
    }).then(() => {
      return settingsPage.getSubtitle();
    }).then(subtitle => {
      return expect(subtitle).toEqual('Subtitle');
    });
  });

  it('should have a Home menu', () => {
    return page.navigateTo().then(() => {
      return navPartial.isHomePresent();
    }).then(present => {
      return expect(present).toBeTruthy();
    });
  });

  it('should have an Info menu', () => {
    return page.navigateTo().then(() => {
      return navPartial.isInfoPresent();
    }).then(present => {
      return expect(present).toBeTruthy();
    });
  });
});
  • 运行测试的输出
$ npm run e2e -- --params.baseUrl 'https://myurl'

> [email protected] pree2e /Users/me/a2
> webdriver-manager update

[13:56:14] I/update - chromedriver: file exists /Users/me/a2/node_modules/protractor/node_modules/webdriver-manager/selenium/chromedriver_2.29.zip
[13:56:14] I/update - chromedriver: unzipping chromedriver_2.29.zip
[13:56:14] I/update - chromedriver: setting permissions to 0755 for /Users/me/a2/node_modules/protractor/node_modules/webdriver-manager/selenium/chromedriver_2.29
[13:56:14] I/update - chromedriver: chromedriver_2.29 up to date
[13:56:14] I/update - selenium standalone: file exists /Users/me/a2/node_modules/protractor/node_modules/webdriver-manager/selenium/selenium-server-standalone-3.4.0.jar
[13:56:14] I/update - selenium standalone: selenium-server-standalone-3.4.0.jar up to date
[13:56:14] I/update - geckodriver: file exists /Users/me/a2/node_modules/protractor/node_modules/webdriver-manager/selenium/geckodriver-v0.16.1.tar.gz
[13:56:14] I/update - geckodriver: unzipping geckodriver-v0.16.1.tar.gz
[13:56:14] I/update - geckodriver: setting permissions to 0755 for /Users/me/a2/node_modules/protractor/node_modules/webdriver-manager/selenium/geckodriver-v0.16.1
[13:56:14] I/update - geckodriver: geckodriver-v0.16.1 up to date

> [email protected] e2e /Users/me/a2
> $(npm bin)/protractor "--params.baseUrl" "https://myurl"

[13:56:16] I/launcher - Running 1 instances of WebDriver
[13:56:16] I/direct - Using ChromeDriver directly...
Spec started

  a2 root
    ✓ should be able to navigate to
    ✓ should take user to Settings
    ✓ should have a Home menu
    ✗ should have an Info menu
      - Failed: EPIPE write EPIPE

**************************************************
*                    Failures                    *
**************************************************

1) a2 root should have an Info menu
  - Failed: EPIPE write EPIPE

Executed 4 of 4 specs (1 FAILED) in 22 secs.
[13:56:41] I/launcher - 0 instance(s) of WebDriver still running
[13:56:41] I/launcher - chrome #01 failed 1 test(s)
[13:56:41] I/launcher - overall: 1 failed spec(s)
[13:56:41] E/launcher - Process exited with error code 1

npm ERR! Darwin 14.5.0
npm ERR! argv "/Users/me/.nvm/versions/node/v6.9.1/bin/node" "/Users/me/.nvm/versions/node/v6.9.1/bin/npm" "run" "e2e" "--" "--params.baseUrl" "https://myurl"
npm ERR! node v6.9.1
npm ERR! npm  v3.10.8
npm ERR! code ELIFECYCLE
npm ERR! [email protected] e2e: `$(npm bin)/protractor "--params.baseUrl" "https://myurl"`
npm ERR! Exit status 1
npm ERR! 
npm ERR! Failed at the [email protected] e2e script '$(npm bin)/protractor "--params.baseUrl" "https://myurl"'.
npm ERR! Make sure you have the latest version of node.js and npm installed.
npm ERR! If you do, this is most likely a problem with the a2 package,
npm ERR! not with npm itself.
npm ERR! Tell the author that this fails on your system:
npm ERR!     $(npm bin)/protractor "--params.baseUrl" "https://myurl"
npm ERR! You can get information on how to open an issue for this project with:
npm ERR!     npm bugs a2
npm ERR! Or if that isn't available, you can get their info via:
npm ERR!     npm owner ls a2
npm ERR! There is likely additional logging output above.

npm ERR! Please include the following file with any support request:
npm ERR!     /Users/me/a2/npm-debug.log

也摘自 npm-debug.log:

18 verbose stack Exit status 1
18 verbose stack     at EventEmitter.<anonymous> (/Users/me/.nvm/versions/node/v6.9.1/lib/node_modules/npm/lib/utils/lifecycle.js:255:16)
18 verbose stack     at emitTwo (events.js:106:13)
18 verbose stack     at EventEmitter.emit (events.js:191:7)
18 verbose stack     at ChildProcess.<anonymous> (/Users/me/.nvm/versions/node/v6.9.1/lib/node_modules/npm/lib/utils/spawn.js:40:14)
18 verbose stack     at emitTwo (events.js:106:13)
18 verbose stack     at ChildProcess.emit (events.js:191:7)
18 verbose stack     at maybeClose (internal/child_process.js:877:16)
18 verbose stack     at Process.ChildProcess._handle.onexit (internal/child_process.js:226:5)
  • 重现错误的步骤
  1. 大致使用提到的 Node 和 Angular 版本,Chrome 浏览器,可能是 Mac OS X。(尚不确定该组合的具体问题。)
  2. 在配置中设置SELENIUM_PROMISE_MANAGER: false (禁用控制流)。
  3. 由于上述 (2),在您的测试套件中的任何地方都使用 Promise。
  4. 有一个套件,可以为多个测试中的每一个获取一个 URL 并单击或检查元素的存在。
  5. 很快你就会开始意外地遇到Failed: EPIPE write EPIPE错误。

我没有使用等待。 我也无法在测试代码中识别出任何未处理的承诺(而且我对承诺很有经验),尽管在一些评论中已经提出了这一点,所以我必须允许这种可能性。 尽管如此,如果是这样的话,节点会因未处理的承诺而崩溃还是令人惊讶的。 因此,除了我的测试或量角器或 webdriver 等可能存在的任何问题之外,这里似乎存在一个节点错误。

  • 您正在运行测试的 URL(如果相关)

抱歉,不公开。

最有用的评论

在我们的项目中出现EPIPE错误,因为测试(在 TypeScript 中)错误地使用await s。 因此,未处理的 Promise 拒绝随机发生并导致这些错误。 一旦我修复了不正确的用法,我们在 Node 8 上就不再有这些错误了。

尝试仔细检查您的测试是否存在await的错误用法(缺失或多余)或不正确的 Promise 链接(例如,当您忘记从帮助方法返回 Promise 时)。 在我们的例子中,典型的错误是使用:

browser.wait(await EC.invisibilityOf(fade)); // incorrect

代替:

await browser.wait(EC.invisibilityOf(fade)); // correct

也许它会帮助同样有这个问题的人。

所有47条评论

我也经常碰到这个。 当 Chrome 在后台时,它似乎更频繁地发生,也许是唯一的。 可能只是巧合

是的,我也遇到了这个丑陋的错误!

对这里迟到的回应表示歉意; 我还没来得及复制这个。 你们中的某个人能否提供一个重现此问题的 Angular 2 应用程序的小型示例 repo(您可以使用 https://github.com/NickTomlin/protractor-mcve 作为入门)?

删除控制流是朝着正确方向迈出的一步,但它可能会揭示一些我们需要考虑的问题(比如这个)。 谢谢!

@NickTomlin @wcainboundary我刚刚将我的 nodejs 升级到了最新的稳定版本,它现在可以正常工作了。

没用:

$node -v
v6.10.1

工作正常:

$node -v
v7.10.0

我在节点 v8.0.0 中看到错误

我也看到这个错误_without_ protractor(直 [email protected],我相信它之前的 3.3)。 在 OS X 上从未发生过,但在我们的构建代理 (Linux) 上却经常发生。

我还没有看到针对 Selenium 提出的这个问题,但它可能应该是。

我在 OSX 中看到过这个错误。

对我来说,这个问题与时间有关。 我的测试试图与不可用的元素进行交互。 尽管角度任务已完成,但页面上的某些渲染未完成,这导致了此问题。 由于连接速度较慢,因此在我们托管的网格上更容易重现。

我确实在 waitForAngularEnabled 设置为 true 和 false 时看到了这一点。

在升级之前,我们曾经在一些相同的测试中遇到超时错误。 我想知道 Webdriver 3.x 是否只是用不同的方式说同样的话......

+1,在 OS X 10.12.5 上本地运行我的规范时遇到同样的问题

对于它的价值,我不太可能在以下位置看到 EPIPE 错误:

  • 节点 7.10.1
  • OSX 10.12.5
  • 量角器 5.1.2
  • 铬 59.0.3071.115

而且,当我说_不太可能_时,我的意思是当我使用上述配置运行我的套件 7 次时,如果我立即关注 Chrome 浏览器并且没有将鼠标从 Chrome 停靠图标上移开(可能不相关的)。

在我们的项目中出现EPIPE错误,因为测试(在 TypeScript 中)错误地使用await s。 因此,未处理的 Promise 拒绝随机发生并导致这些错误。 一旦我修复了不正确的用法,我们在 Node 8 上就不再有这些错误了。

尝试仔细检查您的测试是否存在await的错误用法(缺失或多余)或不正确的 Promise 链接(例如,当您忘记从帮助方法返回 Promise 时)。 在我们的例子中,典型的错误是使用:

browser.wait(await EC.invisibilityOf(fade)); // incorrect

代替:

await browser.wait(EC.invisibilityOf(fade)); // correct

也许它会帮助同样有这个问题的人。

这个问题解决了吗? 我仍然在节点版本 7.7.3 和量角器版本 5.1.1 中看到它

@sri1987见我上面的评论。 这很可能是您的代码中的问题,而不是 Protractor 中的问题。

@ sri1987如果它不能始终如一地重现,那肯定与某处丢失/额外的await有关。

最近使用 SELENIUM_PROMISE_ MANAGER:false经常遇到这些错误
运行多个测试时

此处和 #4507 中的问题似乎是并发 webdriver 命令。 @wvanderdeijl针对 #4508 中ElementArrayFinder::map()的特殊情况提出了解决方案。 在正确解决此问题之前, browser.driver.schedule()的以下包装器(它创建一个队列以防止执行任何并发的 webdriver 命令)可能是一种解决方法。

遇到 EPIPE 错误的人可以定期测试吗? 它可能会在一定程度上减慢测试执行速度。

例如,可以在 Protractor 的onPrepare()挂钩中调用以下代码。

let currentCommand = Promise.resolve();
// Serialise all webdriver commands to prevent EPIPE errors
const webdriverSchedule = browser.driver.schedule;
browser.driver.schedule = (command: Command, description: string) => {
  currentCommand = currentCommand.then(() =>
    webdriverSchedule.call(browser.driver, command, description)
  );
  return currentCommand as any;
}

或一些额外的日志记录:

let currentCommand = Promise.resolve();
let concurrencyCounter = 0;
// Serialise all webdriver commands to prevent EPIPE errors
const webdriverSchedule = browser.driver.schedule;
browser.driver.schedule = (command: Command, description: string) => {
  console.log(`${++concurrencyCounter} concurrent webdriver command(s). Latest command: ${description}`);
  currentCommand = currentCommand.then(() =>
    webdriverSchedule.call(browser.driver, command, description)
      .then(result => {
        concurrencyCounter--;
        return result;
      })
      .catch(error => {
        concurrencyCounter--;
        //console.lgErrLabel('Webdriver error')(command, description, error);
        console.error('Webdriver error:', command, description, error);
        throw error;
      })
  );
  return currentCommand as any;
}

@renehamburger
我认为你在那儿。 我缩小了我的大部分错误来自返回 Promise.all 调用的函数,所以我很确定它一定与并发有关

@renehamburger谢谢。 将此添加到我的 protractor.conf.js 的 onPrepare 部分后:

let currentCommand = Promise.resolve();
// Serialise all webdriver commands to prevent EPIPE errors
const webdriverSchedule = browser.driver.schedule;
browser.driver.schedule = (command, description) => {
   currentCommand = currentCommand.then(() =>
      webdriverSchedule.call(browser.driver, command, description)
    );
    return currentCommand;
};

错误“失败:EPIPE 写入 EPIPE”消失了。

@Xaz16 :作为解决方法为我们工作,谢谢!

但是“EPIPE write EPIPE”错误似乎是 Selenium 中的一个错误: https ://github.com/SeleniumHQ/selenium/issues/5345 将在 4.0.0 中解决。

所以我们必须等到 Protractor 使用 4.0.0 版本,我们才能删除这个解决方法。

我们有指向Protractor路线图的链接吗? 或者根本不存在

@renehamburger ,你能帮忙吗? 我尝试重新编写您的解决方法,以防万一SELENIUM_PROMISE_MANAGER: false 。 目前,如果我只是复制/粘贴您的解决方案,我觉得可以使用async/await解决很多奇怪的问题。

@CrispusDH我不得不将代码片段更改为

let currentCommand = Promise.resolve(); // Serialise all webdriver commands to prevent EPIPE errors const webdriverSchedule = browser.schedule; browser.schedule = (command, description) => { currentCommand = currentCommand.then(() => webdriverSchedule.call(browser, command, description) ); return currentCommand; };

所以基本上删除.driver

使用 Async/await 似乎比 controlFlow 更混乱。

即使在尝试上述解决方案后,Mac OS Sierra 上仍然会出现该错误。

有没有其他解决方案可以尝试。

谢谢

在我们的例子中,在某些断言中似乎错误地使用了 async/await。

有这个:

    const modal = await page.getModalInfo()
    expect(modal.isDisplayed()).toBeTruthy()

代替:

    const modal = page.getModalInfo()
    expect(await modal.isDisplayed()).toBeTruthy()

@danigar函数isDisplayed()返回promise,所以如果你想解决它,必须使用await。 所以你在第二个例子中的第二行代码看起来不错。
第一行中的await怎么样,这取决于返回的内容getModalInfo() 。 目前还不清楚,我看不到第一行和第二行之间的联系。

@marcincharezinski jasmine将在except()中自行解析Promise ,而无需await

是的。 抱歉耽搁了@marcincharezinski。 第一行的getModalInfo()方法返回一个 ElementFinder(未包装在 Promise 中),正如您在第一个示例中看到的,我们为它使用awaiting
我们遇到了一些类似的问题,一旦我们解决了这些问题,EPIPE 错误就消失了😊。

@CrispusDH - 我曾经想过同样的事情,直到由于我无法理解的原因而不断遇到测试失败的问题。 我回去并在我的except()语句中添加了await并清除了它们。

@Mokkapps至少在 TypeScript 中,您的代码会给出错误:
类型 '(命令:命令,描述:字符串)=> Promise void' 不可分配给类型'T(命令:命令,描述:字符串)=> Promise T'。
类型“Promise void”不可分配给类型“Promise T”。
“Promise void”类型中缺少属性“cancel”。

@kahan002

我们终于用这段代码解决了

function patchSchedule() {
  if (os.platform() === 'darwin') {
    let currentCommand = Promise.resolve();
    let concurrencyCounter = 0;
    // Serialise all webdriver commands to prevent EPIPE errors
    const webdriverSchedule = browser.driver.schedule;
    browser.driver.schedule = (command: Command, description: string) => {
      currentCommand = currentCommand.then(() =>
        webdriverSchedule
          .call(browser.driver, command, description)
          .then(result => {
            concurrencyCounter--;
            return result;
          })
          .catch(error => {
            concurrencyCounter--;
            // tslint:disable-next-line:no-console
            console.error('Webdriver error:', command, description, error);
            throw error;
          })
      );
      return currentCommand as any;
    };
  }
}

在 protractor.conf.ts 中调用

onPrepare: () => { patchSchedule(); },

感谢@Mokkapps分享。 一些注意事项,以防有人想将它改编为 typeScript 和像我这样的环境。 os.platform()未知,所以我使用process.platform 。 我不得不import { Command } from "selenium-webdriver";我不得不注释掉 concurrencyCounter 因为它从未被读取过。 而且由于我对隐式 any 有 typeScript 警告,因此我需要在.then((result : any) => {.catch((error: any) => {中明确显示它们。 我不是在抱怨代码,我很高兴你分享了它(它似乎解决了这个问题,虽然它有点难说,因为它是断断续续的)。 我希望这个评论对某人有帮助。 非常感谢您回复我和其他人。
但也许我的更改破坏了您的修复,因为我刚刚得到 UnhandledPromiseRejectionWarning: Unhandled Promise Rejection (rejection id: 4): Error: EPIPE write EPIPE
(节点:8514)[DEP0018] DeprecationWarning:不推荐使用未处理的承诺拒绝。 将来,未处理的 Promise 拒绝将使用非零退出代码终止 Node.js 进程。
毕竟。 我会回去看看我必须在哪里滥用await

OSX 用户有什么进展吗?

我认为这可能是由与其他一些类似错误相同的情况触发的,解决方法是在 Selenium 节点代码和浏览器之间的通信中使用 HTTP keep-alive。 去年,Selenium 主线对此进行了修复 - 但未在该代码的任何版本中发布。

这是我们在此处使用的解决方法,从另一位评论者在另一期中所写的内容中借用和编辑。 设置一个 NPM package.script 来运行它:

"scripts": {
    "install": "webdriver-manager update && node keep-alive-patch.js",

修补程序代码是:

const fs = require('fs');
const chromeFile = 'node_modules/selenium-webdriver/chrome.js';
fs.readFile(chromeFile, 'utf8', function (err, data) {
  if (err)
    throw err;

  const result = data.replace(/new http.HttpClient\(url\)/g,
    "new http.HttpClient(url, new (require('http').Agent)({ keepAlive: true }))");
  console.log(`Patching ${chromeFile}`);
  fs.writeFileSync(chromeFile, result, 'utf8');
});

有了这个补丁,Protractor 在 Windows 和 OSX 上对我们来说都是 99%+,使用SELENIUM_PROMISE_MANAGER: false 。 您的里程可能会有所不同,具体取决于您的 EPIPE 错误是否是由与我们的方式相同的潜在情况引起的。

我发现使用链(或数组)等待似乎最容易受到攻击。 因此,例如,我刚刚看到 let testFormatID: string =await element.all(by.className('ng-star-inserted')).all(by.tagName('td')).get(1) 的错误。获取文本(); 错误可能是我的,而我所写的内容可能不起作用。

#4792似乎解决了我在 Mac OS X 上的问题。感谢 IgorDorokhov 的提示。

@kahan002不客气!

量角器中包含 4.0.0-alpha.1 的任何 ETA 吗?

4792 没有为我解决问题。 仍然得到Failed: EPIPE write EPIPE错误 1 ​​出 5 在 ElementArrayFinder 上进行过滤:

$$('classified-section').filter((section) => section.isDisplayed())

请升级到[email protected] 。 好像在那里解决了。

@demisx在这里修补了它,它对我有用

@rafalf谢谢。 如果您正在谈论“从 selenium-3.7.0 获取index.js并添加 ECONNREFUSED”,那么我已经尝试过了,但偶尔仍然会出现此错误。 如果我误解了您的评论,请告诉我。

在 MacOS Mojave 上,最新的 protractor 5.4.1、chromedriver_2.43 和 async/await 仍然经常发生 EPIPE 错误。 我们不能再在 CI 上运行 E2E 规范了。 进行多次手动运行,直到全部通过。 很不稳定。

@demisx
这主要发生在我身上eachfilter和其他使用 iwth 数组的函数

我是如何重做的

        // EPIPE write EPIPE
        // await $$("short-list-component.ng-valid mat-label").each(async function (element) {
        //     labels.push(await element.getText())
        // });
        // this.logInfo("getMatLabels: " + labels);
        // return labels

        let l = await $$("q-short-list-component.ng-valid mat-label");
        for (let element of l){
            text = await element.getText();
            labels.push(text)
        }

@rafalf是的,这是我们摆脱的第一件事。 虽然它降低了 EPIPE 错误的频率,但它们并没有完全消失。 运行具有多种功能的量角器时,情况会变得更糟。 所以,到目前为止@kylecordes补丁似乎正在完成这项工作。 谢谢@kylecordes! 希望此修复程序能很快达到master

题外话,你不需要awaitlet l = await $$("q-short-list-component.ng-valid mat-label")$$返回ElementArrayFinder ,而不是承诺。 😉

@demisx不,你错了,也许这就是为什么你仍然会出现 EPIPE 错误:舞者:
是的 - 它返回 ElementArrayFinder 而无需等待,但您将无法对其进行迭代
这部分不起作用

for (let element of l){
            text = await element.getText();
            labels.push(text)
        }

如果我这样做await ,我会得到一个元素列表;)我可以通过

@rafalf对不起,我的错。 我错过了await下面的迭代部分。 你是绝对正确的。

我可能弄错了,但在我以下列方式使用 ElementArrayFinder 的地方,这些错误似乎间歇性地发生:
await $$('some-selector').click()

@yyankowski是的,这也是我的经验。 我看到这个错误发生在$$上。 特别是,当尝试在 $$ 返回的$$ ElementArrayFinder上调用方法时。

此页面是否有帮助?
0 / 5 - 0 等级