You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Nightwatch测试模块导入主测试报错排查求助

Nightwatch.js: TypeError: Cannot read property 'url' of undefined when reusing test modules

我正在学习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,可以做以下调整:

  1. 把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)
}
  1. 修改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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 06:42:12