browser.end() 后 Nightwatch 未终止

Nightwatch not terminating after browser.end()

我在 运行ning Nightwatch 启动了一个子进程来启动我的本地服务器。 Nightwatch 运行 测试成功完成,浏览器 windows 全部关闭,但 nightwatch 进程在打印消息 "OK. 10 total assertions passed." 后继续 运行。

我认为这可能与我在 nightwatch 进程中观看事件的方式有关,但据我所知,我正在观看所有表明 Nightwatch 正在退出的事件。

从未调用 runner.js 中的方法 shutdown()。如何让 Nightwatch 在测试完成时终止?

更新

如果我删除 sign-in.js 中的最后一个测试,那么 Nightwatch 会按预期退出。

runner.js

import spawn from 'cross-spawn'

// 1. start the dev server using production config
process.env.NODE_ENV = 'testing'

let servers

function shutdown (result) {
  console.log('HERE', result)
  try {
    // Passing a negative PID to kill will terminate all child processes, not just the parent
    if (servers) process.kill(-servers.pid)
  } catch (e) {
    console.error('Unable to shutdown servers, may need to be killed manually')
  }

  if (result) {
    console.error(result)
    process.exit(1)
  } else {
    process.exit(0)
  }
}

function watch (child) {
  child.on('close', shutdown)
  child.on('disconnect', shutdown)
  child.on('error', shutdown)
  child.on('exit', shutdown)
  child.on('uncaughtException', shutdown)
}

try {
  servers = spawn('yarn', ['run', 'dev-all'], { cwd: '..', stdio: 'inherit', detached: true })
  watch(servers)

  // 2. run the nightwatch test suite against it
  // to run in additional browsers:
  //    1. add an entry in test/e2e/nightwatch.conf.json under "test_settings"
  //    2. add it to the --env flag below
  // or override the environment flag, for example: `npm run e2e -- --env chrome,firefox`
  // For more information on Nightwatch's config file, see
  // http://nightwatchjs.org/guide#settings-file
  var opts = process.argv.slice(2)
  if (opts.indexOf('--config') === -1) {
    opts = opts.concat(['--config', 'e2e/nightwatch.conf.js'])
  }
  if (opts.indexOf('--env') === -1) {
    opts = opts.concat(['--env', 'chrome'])
  }

  var runner = spawn('./node_modules/.bin/nightwatch', opts, { stdio: 'inherit' })
  watch(runner)
  watch(process)
} catch (error) {
  shutdown(error)
}

nightwatch.conf.js

require('babel-register')
var config = require('../../frontend/config')

// http://nightwatchjs.org/guide#settings-file
module.exports = {
  src_folders: ['e2e/specs'],
  output_folder: 'e2e/reports',
  custom_assertions_path: ['e2e/custom-assertions'],

  selenium: {
    start_process: true,
    server_path: 'node_modules/selenium-server/lib/runner/selenium-server-standalone-3.0.1.jar',
    host: '127.0.0.1',
    port: 4444,
    cli_args: {
      'webdriver.chrome.driver': require('chromedriver').path
    }
  },

  test_settings: {
    default: {
      selenium_port: 4444,
      selenium_host: 'localhost',
      silent: true,
      globals: {
        devServerURL: 'http://localhost:' + (process.env.PORT || config.dev.port)
      }
    },

    chrome: {
      desiredCapabilities: {
        browserName: 'chrome',
        javascriptEnabled: true,
        acceptSslCerts: true
      }
    },

    firefox: {
      desiredCapabilities: {
        browserName: 'firefox',
        javascriptEnabled: true,
        acceptSslCerts: true
      }
    }
  }
}

sign-in.js(测试之一)

import firebase from 'firebase-admin'
import uuid from 'uuid'

import * as firebaseSettings from '../../../backend/src/firebase-settings'

const PASSWORD = 'toomanysecrets'

function createUser (user) {
  console.log('Creating user', user.uid)
  let db = firebase.database()
  return Promise.all([
    firebase.auth().createUser({
      uid: user.uid,
      email: user.email,
      emailVerified: true,
      displayName: user.fullName,
      password: PASSWORD
    }),
    db.ref('users').child(user.uid).set({
      email: user.email,
      fullName: user.fullName
    }),
    db.ref('roles').child(user.uid).set({
      instructor: false
    })
  ])
}

function destroyUser (user) {
  if (!user) return

  console.log('Removing user', user.uid)
  let db = firebase.database()
  try { db.ref('roles').child(user.uid).remove() } catch (e) {}
  try { db.ref('users').child(user.uid).remove() } catch (e) {}
  try { firebase.auth().deleteUser(user.uid) } catch (e) {}
}

module.exports = {
  'Sign In links exist': browser => {
    // automatically uses dev Server port from /config.index.js
    // default: http://localhost:8080
    // see nightwatch.conf.js
    const devServer = browser.globals.devServerURL

    browser
      .url(devServer)
      .waitForElementVisible('#container', 5000)

    browser.expect.element('.main-nav').to.be.present
    browser.expect.element('.main-nav a[href^=\'https://oauth.ais.msu.edu/oauth/authorize\']').to.be.present
    browser.expect.element('.main-nav a[href^=\'/email-sign-in\']').to.be.present
    browser.end()
  },
  'Successful Sign In with Email shows dashboard': browser => {
    const devServer = browser.globals.devServerURL

    firebase.initializeApp(firebaseSettings.appConfig)

    let userId = uuid.v4()
    let user = {
      uid: userId,
      email: `${userId}@test.com`,
      fullName: 'Test User'
    }

    createUser(user)

    browser.url(devServer)
      .waitForElementVisible('.main-nav a[href^=\'/email-sign-in\']', 5000)
      .click('.main-nav a[href^=\'/email-sign-in\']')
      .waitForElementVisible('button', 5000)
      .setValue('input[type=text]', user.email)
      .setValue('input[type=password]', PASSWORD)
      .click('button')
      .waitForElementVisible('.main-nav a[href^=\'/sign-out\']', 5000)
      .end(() => {
        destroyUser(user)
      })
  }
}

测试成功完成后,我看到以下内容:

grimlock:backend egillespie$ ps -ef | grep nightwatch
501 13087 13085   0  1:51AM ttys000    0:02.18 node ./node_modules/.bin/nightwatch --presets es2015,stage-0 --config e2e/nightwatch.conf.js --env chrome

我没有明确关闭 Firebase 连接。这导致最后一个测试无限期挂起。

以下是我在执行测试清理后关闭连接的方式:

browser.end(() => {
  destroyUser(user).then(() => {
    firebase.app().delete()
  })
})

destroyUser 函数现在看起来像这样:

function destroyUser (user) {
  if (!user) return Promise.resolve()

  let db = firebase.database()
  return Promise.all([
    db.ref('roles').child(user.uid).remove(),
    db.ref('users').child(user.uid).remove(),
    firebase.auth().deleteUser(user.uid)
  ])
}

我试过以下方法:

在"nightwatch.conf.js",

"test_settings" { "default" { "silent": true, ... }, ... }

我将 "silent" 从 true 设置为 false

它导致控制台变得冗长。 chromedriver.exe 将在 运行 测试后和平退出

我使用的 vue 模板来自:https://github.com/vuejs-templates/pwa

我的平台:

  • Windows 7(64 位)
  • node v8.1.3
  • "nightwatch": "^0.9.16",
  • "selenium-server": "^3.6.0",
  • "chromedriver": "^2.33.1"

在我的情况下(vue/vuetify 的夜视)在每次测试后都是这样的:

afterEach:function(browser,done){
    done();
}
AfterAll(async()=>{
   await closeSession();
   await stopWebDriver();
}

将其放入配置文件@Erik Gillespie

Nightwatch 仍然存在 browser.end() 的问题 如果你 运行 守夜人 node.js 你可以停止这个过程 通过做类似的事情:

browser.end(() => {
  process.exit();
});

它将关闭浏览器并结束进程。