首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >CircleCI上的间歇硒经济学误差

CircleCI上的间歇硒经济学误差
EN

Stack Overflow用户
提问于 2017-04-26 14:41:03
回答 1查看 445关注 0票数 0

我们的CircleCI测试使用selenium驱动程序通过PhantomJS运行UI测试。这些测试在我们的迷幻剂env中100%在本地工作,但是在CircleCI上大约有1/3的测试失败,这些错误包括:

代码语言:javascript
复制
   Error: ECONNREFUSED connect ECONNREFUSED 10.0.4.1:59525
      at ClientRequest.<anonymous> (node_modules/selenium-webdriver/http/index.js:238:15)
      at Socket.socketErrorListener (_http_client.js:310:9)
      at emitErrorNT (net.js:1278:8)
      at _combinedTickCallback (internal/process/next_tick.js:74:11)
      at process._tickCallback (internal/process/next_tick.js:98:9)
  From: Task: WebDriver.navigate().to(http://127.0.0.1:8080/src/public/login.php?t=ur&ign=1&ut=ad)
      at thenableWebDriverProxy.schedule (node_modules/selenium-webdriver/lib/webdriver.js:816:17)
      at Navigation.to (node_modules/selenium-webdriver/lib/webdriver.js:1140:25)
      at thenableWebDriverProxy.get (node_modules/selenium-webdriver/lib/webdriver.js:997:28)
      at User.logIn (testJs/ui/utils/user.js:9:16)
      at Host.logInAsHost (testJs/ui/utils/host.js:13:14)
      at Preferences.disableRevenueGeneration (testJs/ui/utils/preferences.js:57:14)
      at Context.<anonymous> (testJs/ui/tests/preferences.js:13:22)

这些错误发生在我们整个测试过程中的随机时间,它们不是由测试中的任何特定位置触发的。据我所知,这个问题发生在selenium/selenium-webdriver端,因为web服务器仍然处于正常工作状态,并且不会产生任何错误。

我试过以下所有的方法,但都没有奏效:

  1. 升级到最新的selenium-webdriver (3.4.0)
  2. 升级到最新版本的nodejs (6.9.2)
  3. 使用不同的web服务器
  4. 升级到最新版本的PhantomJS (1.9.7-15)
  5. 试着按https://github.com/SeleniumHQ/docker-selenium/issues/87使用https://github.com/SeleniumHQ/docker-selenium/issues/87
  6. 在node_modules/selenium-webdriver/http/index.js,中,我修改了代码以重新尝试ECONNREFUSED错误,方法是重用已经存在的ECONNRESET重试,即if (e.code === 'ECONNRESET') {变成if (e.code === 'ECONNRESET' || e.code === 'ECONNREFUSED') {。这是行不通的,因为selenium-webdriver只是无限期地重试,由此我意识到,问题似乎是,一旦遇到了ECONNREFUSED错误,selenium/selenium-webdriver就无法恢复。

有人找到解决办法了吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-04-26 19:42:33

警告:这只是一个黑客攻击,绝不是一个合适的解决方案,但它似乎是唯一一个在CircleCI上可靠地为我们工作的解决方案。希望其他人能找到更好的解决方案。

我们的测试框架mocha似乎有一个专门为selenium (go图)开发的重试机制:http://mochajs.org/#retry-tests。第一个问题是afterbefore中的代码没有被重试。因此,您需要将代码移动到beforeEachafterEach。第二个问题是,您需要在beforeEachafterEach中使用一些特殊的逻辑来处理驱动程序错误。

因此,为了利用这种机制,我们必须重构我们的测试,以便每个测试都有一个beforeEach,它设置一个新的webdriver实例,然后一个afterEach退出该驱动程序实例。这样,崩溃的驱动程序实例就不会停止所有后续的测试。我们开发了一个助手函数,我们在所有describe块的开头调用它,这样我们就不必为测试添加太多的代码了。

然后,我们将this.retries(10)添加到最顶层的describe块中。

下面是助手类:

代码语言:javascript
复制
var webdriver = require('selenium-webdriver');

// We default to using phantomjs, but in the future, when we run tests in other browsers, e.g. via
// SauceLabs, we'll want to change the browser.
var customPhantom = webdriver.Capabilities.phantomjs();
customPhantom.set('ssl-protocol', 'any');

// For convenience in tests
global.By = webdriver.By;
global.until = webdriver.until;

var SeleniumStabilizer = function () {};

SeleniumStabilizer.prototype.MAX_RETRIES = 10;

SeleniumStabilizer.prototype.createDriver = function () {
    global.driver = new webdriver.Builder()
        // .forBrowser('phantomjs')
        .withCapabilities(customPhantom)
        .build();

    // Resolves when driver is ready
    return global.driver;
};

SeleniumStabilizer.prototype.init = function (opts) {

    var self = this,
        n = 0;

    var beforeEachWithRetries = function () {
        // Create a fresh selenium driver for the next test
        return self.createDriver().then(function () {
            if (opts.onBeforeEach) {
                // Execute the test-specific defined onBeforeEach
                return opts.onBeforeEach();
            }
        }).catch(function (err) {
            // ECONNREFUSED error and we should retry?
            if (err.message.indexOf('ECONNREFUSED') !== -1 && n++ < self.MAX_RETRIES) {
                return beforeEachWithRetries();
            } else {
                throw err;              
            }
        });
    };

    opts.beforeEach(function () {
        n = 0;
        return beforeEachWithRetries();
    });

    var afterEachWithRetries = function () {
        return Promise.resolve().then(function () {
            if (opts.onAfterEach) {
                // Execute the test-specific defined onAfterEach
                return opts.onAfterEach();
            }
        }).then(function () {
            // Quit the selenium driver before starting the next test
            return driver.quit();
        }).catch(function (err) {
            // ECONNREFUSED error and we should retry?
            if (err.message.indexOf('ECONNREFUSED') !== -1 && n++ < self.MAX_RETRIES) {
                // Create a new driver
                return self.createDriver().then(function () {
                    return afterEachWithRetries();
                });
            } else {
                throw err;              
            }
        });
    };

    opts.afterEach(function () {
        n = 0;
        return afterEachWithRetries();
    });
};

然后,您的测试看起来是:

代码语言:javascript
复制
var seleniumStabilizer = new SeleniumStabilizer();

describe('my tests', function () {

  this.retries(seleniumStabilizer.MAX_RETRIES);

  describe('search engines', function () {

    seleniumStabilizer.init({
      beforeEach: beforeEach,
      afterEach: afterEach,
      onBeforeEach: function () {
        // e.g. return doPromiseAfterDriverSetUp();
      },
      onAfterEach: function () {
        // e.g. return doPromiseBeforeDriverQuits();
      }
    });

    it('should get google', function () {
      return driver.get('https://www.google.com');
    });

    it('should get amazon', function () {
      return driver.get('https://www.amazon.com');
    });

  });

});
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/43637382

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档