Nightwatch测试模块导入主测试报错排查求助
我正在学习Nightwatch,已经成功运行了第一个测试,现在想要优化测试结构,创建可复用的通用测试模块来构建主测试。我尝试用CommonJS的require/exports来实现,但因为更熟悉ES6的import/export,可能犯了基础错误。测试能正常运行通过,但最终控制台会抛出TypeError: Cannot read property 'url' of undefined的错误。
文件结构
Tests ├─auth │ └─ auth.js └─index.js
配置文件
nightwatch.json
{ "src_folders" : ["tests"], "output_folder" : "reports", "selenium" : { "start_process" : true, "server_path" : "./bin/selenium-server-standalone-3.8.1.jar", "log_path" : "", "port" : 4444, "cli_args" : { "webdriver.chrome.driver" : "./bin/chromedriver" } }, "test_settings" : { "default" : { "launch_url" : "http://localhost", "selenium_port" : 4444, "selenium_host" : "localhost", "desiredCapabilities": { "browserName": "chrome", "javascriptEnabled": true, "acceptSslCerts": true } } } }
package.json
{ "name": "mostesting", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "test-e2e": "nightwatch" }, "author": "", "license": "ISC", "dependencies": { "babel-plugin-add-module-exports": "^0.2.1", "nightwatch": "^0.9.19", "selenium-webdriver": "^4.0.0-alpha.1" }, "devDependencies": { "babel-core": "^6.26.0", "babel-plugin-add-module-exports": "^0.2.1", "babel-preset-es2015": "^6.24.1" } }
测试代码
index.js
const auth = require('./auth/auth.js') module.exports = { 'Log into system': auth.login() }
auth.js
exports.login = function (client) { client .url('http://myurl.co.uk') .waitForElementVisible('body', 1000) .assert.title('Reach - Log in') .assert.visible('#UserName') .setValue('#UserName', 'XXXX') .assert.visible('#Password') .setValue('#Password', 'XXXX') .assert.visible('input[value="Login"]') .click('input[value="Login"]') .waitForElementVisible('img.test', 10000, false) }
错误信息
OK. 6 assertions passed. (8.549s) There was an error while starting the test runner: TypeError: Cannot read property 'url' of undefined at Object.exports.login (/Applications/MAMP/htdocs/mostesting/tests/auth/auth.js:3:5) at Object.<anonymous> (/Applications/MAMP/htdocs/mostesting/tests/index.js:4:27) at Module._compile (module.js:571:32) at Object.Module._extensions..js (module.js:580:10) at Module.load (module.js:488:32) at tryModuleLoad (module.js:447:12) at Function.Module._load (module.js:439:3) at Module.require (module.js:498:17) at require (internal/module.js:20:19) at new Module (/Applications/MAMP/htdocs/mostesting/node_modules/nightwatch/lib/runner/module.js:7:23)
问题原因与修复方案
问题根源
你在index.js里直接调用了auth.login(),这会在模块加载时就执行这个函数,而此时Nightwatch还没有传入client对象,所以client是undefined,导致调用client.url()时抛出错误。
Nightwatch期望测试用例是一个函数,它会在测试运行时自动把client实例传入这个函数。而你现在是把login()执行后的返回值(这里是undefined,因为你的login函数没有返回值)赋值给测试用例,这就不符合Nightwatch的要求了。
修复代码
修改index.js
把auth.login()改成auth.login,也就是把函数本身赋值给测试用例,而不是立即执行函数:
const auth = require('./auth/auth.js') module.exports = { 'Log into system': auth.login // 去掉后面的括号,不要立即执行 }
(可选)改用ES6模块语法
如果你更习惯ES6的import/export,可以做以下调整:
- 把
auth.js改成ES6导出:
export function login(client) { client .url('http://myurl.co.uk') .waitForElementVisible('body', 1000) .assert.title('Reach - Log in') .assert.visible('#UserName') .setValue('#UserName', 'XXXX') .assert.visible('#Password') .setValue('#Password', 'XXXX') .assert.visible('input[value="Login"]') .click('input[value="Login"]') .waitForElementVisible('img.test', 10000, false) }
- 修改
index.js使用ES6导入:
import { login } from './auth/auth.js'; module.exports = { 'Log into system': login }
不过要注意,Nightwatch v0.9.x本身不支持ES6模块,所以你需要确保Babel已经正确配置,能够把ES6代码转译为CommonJS,这样Node.js才能正确加载。你的package.json里已经有了babel相关依赖,只要配置好.babelrc文件即可:
{ "presets": ["es2015"], "plugins": ["add-module-exports"] }
额外建议
- 测试函数最后最好加上
client.end()来关闭浏览器,除非你要在后续测试中复用同一个浏览器实例:
exports.login = function (client) { client .url('http://myurl.co.uk') // ... 其他操作 .waitForElementVisible('img.test', 10000, false) .end(); // 关闭浏览器 }
内容的提问来源于stack exchange,提问作者mtwallet

