Vue + nightwatch + Chrome76进行e2e测试的正确配置(一)

2019.08.19 修正文章中的错误

除了单元测试之外,前端还有一个额外的测试:e2e测试,也就是端到端测试,用来模拟用户操作。对于Vue来说,推荐的e2e测试框架有nightwatch和cypress,因为cypress只支持Chrome,而且尤大之前用的是nightwatch,所以我也选择了nightwatch。

vue-cli对nightwatch的整合可以说很完善了,基本上只需要一条命令就能完成安装和配置,然后就可以开始写测试了:

vue add @vue/e2e-nightwatch

之所以说基本上只需要一条命令,因为nightwatch基于java,需要先安装和配置Java。

本来一切都很美好,但是前段时间Chrome自动更新到了76版本,然后就出了问题。用vue-cli新建一个项目,新建的项目居然过不了测试!报错如下:

Error retrieving a new session from the selenium server

Connection refused! Is selenium server started?
{ value:
   { message:
      'Unable to create new service: ChromeDriverService\nBuild info: version: \'3.141.59\', revision: \'e82be7d358\', time: \'2018-11-14T08:25:53\'\nSystem info: host: \'wensun\', ip:
 \'192.168.199.1\', os.name: \'Windows 10\', os.arch: \'amd64\', os.version: \'10.0\', java.version: \'1.8.0_211\'\nDriver info: driver.version: unknown',
     error: 'session not created' },
  status: 33 }

这就很神秘了。网上转一圈,看到说是chromedriver版本过低,也就是测试需要的驱动掉链子了。因为从报错信息里可以看到,selenium无法识别驱动的版本,显示为unknown。那就装一个新版本的驱动:

npm install --save-dev chromedriver

但是连这个都报错了:

npm ERR! The operation was rejected by your operating system.
npm ERR! It's possible that the file was already in use (by a text editor or antivirus),
npm ERR! or that you lack permissions to access it.
npm ERR!
npm ERR! If you believe this might be a permissions issue, please double-check the
npm ERR! permissions of the file and its containing directories, or try running
npm ERR! the command again as root/Administrator.

我:???

打开Windows的命令行,看看是不是chromedriver没有完全退出:

> tasklist|findstr chromedriver
chromedriver.exe              9980 Console                    1     14,752 K
chromedriver.exe             15464 Console                    1     14,672 K
> taskkill -pid 9980 -pid 15464 -f
成功: 已终止 PID 为 9980 的进程。
成功: 已终止 PID 为 15464 的进程。

首先吐槽Windows的命令行是真的难用。其次,chromedriver在后台居然有多个进程。我一开始以为是主从进程,或者是主进程和守护进程,后来才发现,运行几次测试,后台就会有几个进程……这个是真的不能理解。

解决完这个问题,再运行一次npm install --save-dev chromedriver,这次安装上了。重新运行测试,这次还是一样的报错:

Error retrieving a new session from the selenium server

Connection refused! Is selenium server started?
{ value:
   { message:
      'Unable to create new service: ChromeDriverService\nBuild info: version: \'3.141.59\', revision: \'e82be7d358\', time: \'2018-11-14T08:25:53\'\nSystem info: host: \'wensun\', ip:
 \'192.168.199.1\', os.name: \'Windows 10\', os.arch: \'amd64\', os.version: \'10.0\', java.version: \'1.8.0_211\'\nDriver info: driver.version: unknown',
     error: 'session not created' },
  status: 33 }

仔细观察之后发现,selenium的版本是3.141.59。查看文档后发现,这个版本只支持Chrome 71-75。事实上,在这里还有可能遇到``session not created: Chrome version must be between 71 and 75`的报错。

首先想到的解决方案肯定是回退Chrome版本,退到75版本,但回退很麻烦,而且总不能因为这个一直用旧版本浏览器,也不符合正常用户的使用习惯。肯定有什么解决方案。

去vue-cli的issue里查询,发现了这么一条:

oh you may have to use @vue/cli-plugin-e2e-nightwatch v4.0.0-beta.0…
It was a breaking change to update the chromedriver dependency so it’s only landed in v4… I totally forgot that.

……vue-cli默认安装的是3.10.0的稳定版本,但如果想支持新版本的chromedriver,必须要升级到4.x的测试版。在写这篇文章的时候,我安装的版本是4.0.0-beta.3:

"devDependencies": {
    "@vue/cli-plugin-e2e-nightwatch": "^4.0.0-beta.3"
}

到了这里终于能跑了。如果还不能跑,报错Cannot find module 'chromedriver',首先试试删掉node_modules之后重新npm install

然而,好景不长,跑虽然能跑了,但是开始疯狂报错:

 Error while running .isElementDisplayed() protocol action: TypeError [ERR_UNESCAPED_CHARACTERS]: Error while trying to create HTTP request for "/wd/hub/session/ff75c2c3ab2a905187aa80
193cfde80d/element/[object Object]/displayed": Request path contains unescaped characters
............
_________________________________________________

TEST FAILURE: 1 error during execution 0 tests failed, 1 passed. 10.254s

 × test
 – default e2e tests (5.632s)

中间的报错信息因为太长就省略了。也就是说,现在的问题是,测试能跑但跑不对。这里的不对不是说代码写错了,而是指测试本身出现了问题。后来查阅nightwatch的release note,发现了端倪:

  • Fixed #2118 - Set default POST body to be empty JSON in order to use chromedriver 75
    If using Chromedriver 75 you need to set the following capabilities in your config:
desiredCapabilities : {
    browserName : 'chrome',
    chromeOptions: {
        w3c: false
    }
}

Chromedriver 75 has W3C Webdriver protocol enabled by default, however we recommend sticking to the JSONWire for now as some endpoints aren’t implemented yet (e.g. /displayed). If using the default w3c webdriver mode, make sure to adjust the config like so:

{
    capabilities: {
        browserName : 'chrome'
    },
    webdriver: {
        use_legacy_jsonwire: false
    }
}

原来,从Chrome75版本开始,就默认使用了W3C的webdriver协议,但nightwatch用的是JSONWP,和W3C不兼容,所以如果想要正常使用,必须关闭W3C的协议。也就是说,可以在测试文件里加上这么一段:

module.exports = {
    desiredCapabilities: {
        browserName: "chrome",
        chromeOptions: {
            w3c: false
        }
    }
}

虽然release note里提到了另一种写法,但亲测不可用……可能是vue-cli内部有别的配置导致的不可用。最后的测试文件应该长这样:

// tests/e2e/specs/test.js
module.exports = {
  desiredCapabilities: {
    browserName: "chrome",
    chromeOptions: {
      w3c: false
    }
  },
  'default e2e tests': browser => {
    browser
      .url(process.env.VUE_DEV_SERVER_URL)
      .waitForElementVisible('#app', 5000)
      .assert.elementPresent('.hello')
      .assert.containsText('h1', 'Welcome to Your Vue.js App')
      .assert.elementCount('img', 1)
      .end();
  }
};

如果还是不清楚……可以看看示例项目:chrome76-e2e-test-conf-example的stage1分支。

一切正常。兴冲冲地加进travis(具体怎么配置travis就不谈了,不然就跑题了;而且网上也有很多相关的资料),然后就报错了:

 Error: Timeout while trying to connect to Selenium Server on port 4444.
       at Socket.socketErrorListener (_http_client.js:392:9)
       at emitErrorNT (internal/streams/destroy.js:91:8)
       at emitErrorAndCloseNT (internal/streams/destroy.js:59:3)
       at process._tickCallback (internal/process/next_tick.js:63:19)

为什么会这样?在Windows下明明是好好的。

此外还有一个问题,这些配置是针对单个测试文件的,我们总不能每次新建一个测试文件就重复一次上面的操作,或者直接把所有的测试写在一个文件里,这个问题也是需要解决的。

这些问题让我陷入了沉思。

目录

Vue + nightwatch + Chrome76进行e2e测试的正确配置(二)

你可能感兴趣的:(前端杂谈,有趣的bug,配置踩坑,大概是测试)