如何在量角器运行之前启动服务器并在之后进行清理

How to start a server before protractor runs and clean up afterwards

Protractor 似乎没有提供任何开箱即用的解决方案来在 运行 之前启动服务器。在功能测试之前必须 运行 多个命令 运行 是一种糟糕的用户体验,并且不利于自动化测试。

Angular-cli 有它自己的相当复杂的解决方案,这个插件声称可以复制它,尽管它对我不起作用并且可能没有维护。 https://www.npmjs.com/package/protractor-webpack

编辑:接受以下更好的解决方案

我想出了一个使用 child_process.exec 的解决方案,虽然我不太喜欢它,但它似乎运行良好。我想分享它以防万一有人需要它,看看是否有人能提出更好的解决方案。

在量角器的 beforeLaunch 挂钩中启动进程:

beforeLaunch: () => {
    webpackServerProcess = exec(`webpack-dev-server --port=3003 --open=false`, null, () => { 
      console.log(`Webpack Server process reports that it exited. Its possible a server was already running on port ${port}`)
    });
  },

然后在配置块上方我们设置退出处理程序以确保服务器在我们完成后被杀死。

let webpackServerProcess; // Set below in beforeLaunch hook
function cleanUpServer(eventType) {
  console.log(`Server Cleanup caught ${eventType}, killing server`);
  if (webpackServerProcess) {
    webpackServerProcess.kill();
    console.log(`SERVER KILLED`);
  }
}

[`exit`, `SIGINT`, `SIGUSR1`, `SIGUSR2`, `uncaughtException`].forEach((eventType) => {
  process.on(eventType, cleanUpServer.bind(null, eventType));
})

需要各种事件侦听器来处理 cntrl+c 事件和进程被 ID 杀死的情况。奇怪的是节点没有提供包含所有这些的事件。

Protractor 也有 onCleanUp,它将在文件中的所有规格完成后 运行。

并且您通过保留对进程的引用来做正确的事情,以便稍后可以终止它。

let webpackServerProcess;
beforeLaunch: () {
    webpackServerProcess = exec('blah'); // you could use spawn instead of exec
},
onCleanUp: () {
    process.kill(webpackServerProcess.pid);
    // or webpackServerProcess.exit();
}

由于您使用 child_process.exec 启动 serverProcess,而不是处于分离状态,如果主进程被 SIGINT 或其他任何东西终止,它应该会消失。所以你甚至不必杀死它或清理它。

我找到了一种更可靠的方法来使用 webpack-dev-server 节点 api。这样就不会产生单独的进程,我们也不必清理任何东西。此外,它会阻止量角器,直到 webpack 准备就绪。

  beforeLaunch: () => {
    return new Promise((resolve, reject) => {
      new WebpackDevServer(webpack(require('./webpack.config.js')()), {
        // Do stuff
      }).listen(APP_PORT, '0.0.0.0', function(err) {
        console.log('webpack dev server error is ', err)
        resolve()
      }).on('error', (error) => {
        console.log('dev server error ', error)
        reject(error)
      })
    })
  },