将 require 与相对路径一起使用
我们在 Protractor 上进行了相当多的端到端测试.我们遵循页面对象模式,这有助于我们保持测试的清洁和模块化.我们还有一组辅助函数来帮助我们遵循 DRY 原则.p>
问题:
单个规范可能需要多个页面对象和帮助模块.例如:
"使用严格";var helpers = require("./../../helpers/helpers.js");var localStoragePage = require("./../../helpers/localStorage.js");var sessionStoragePage = require("./../../helpers/sessionStorage.js");var loginPage = require("./../../po/login.po.js");var headerPage = require("./../../po/header.po.js");var queuePage = require("./../../po/queue.po.js");describe("登录功能", function () {之前(函数(){browser.get("/#login");localStoragePage.clear();});//...});
您可以看到我们在每个 require 语句中都有该目录遍历:./../..
.这是因为我们有一个 specs
目录,我们将规范和多个目录保存在其中,这些目录按正在测试的应用程序功能分组.
问题:
在 Protractor 中解决相对路径问题的规范方法是什么?
换句话说,我们希望避免遍历树,向上导入模块.而是从基本应用程序目录中下去会更干净.
<小时>尝试和想法:
关于解决这个问题有一篇很棒的文章:更好的 Node.js 本地 require() 路径,但我不确定在使用 Protractor 开发测试时推荐使用哪个选项.
我们也尝试过使用 require.main
来构造路径,但它指向 node_modules/protractor
目录而不是我们的应用程序目录.
我遇到了同样的问题,我最终得到了以下解决方案.在我的 Protractor 配置文件中,我有一个变量,它存储了我的 e2e 测试的基本文件夹的路径.此外,Protractor 配置提供了 onPrepare
回调,您可以在其中使用名为 global
的变量为您的测试创建全局变量.您将它们定义为该 global
变量的属性,并使用与在测试中使用全局 browser
或 element
相同的方式.我用它来创建自定义全局 require 函数来加载不同类型的实体:
//__dirname 重新调整此特定配置文件的路径//假设 protractor.conf.js 在项目的根目录下var basePath = __dirname + '/test/e2e/';///path/to/project/test/e2e/出口.config = {onPrepare: 函数 () {//relativePath" - 相对于basePath"变量的路径//如果你的实体文件有后缀 - 你也可以把它们放在这里//更不用说每次都在测试文件中global.requirePO = function (relativePath) {return require(basePath + 'po/' + relativePath + '.po.js');};global.requireHelper = function (relativePath) {return require(basePath + 'helpers/' + relativePath + '.js');};}};
然后您可以立即在测试文件中使用这些全局实用方法:
"使用严格";var localStorageHelper = requireHelper('localStorage');///path/to/project/test/e2e/helpers/localStorage.jsvar loginPage = requirePO('登录');///path/to/project/test/e2e/po/login.po.jsvar productShowPage = requirePO('product/show');///path/to/project/test/e2e/po/product/show.po.jsdescribe("登录功能", function () {之前(函数(){browser.get("/#login");localStorageHelper.clear();});//...});
We have a rather big set of end-to-end tests on Protractor. We are following the Page Object pattern which helps us to keep our tests clean and modular. We also have a set of helper functions which help us to follow the DRY principle.
The Problem:
A single spec may require multiple page objects and helper modules. For instance:
"use strict";
var helpers = require("./../../helpers/helpers.js");
var localStoragePage = require("./../../helpers/localStorage.js");
var sessionStoragePage = require("./../../helpers/sessionStorage.js");
var loginPage = require("./../../po/login.po.js");
var headerPage = require("./../../po/header.po.js");
var queuePage = require("./../../po/queue.po.js");
describe("Login functionality", function () {
beforeEach(function () {
browser.get("/#login");
localStoragePage.clear();
});
// ...
});
You can see that we have that directory traversal in every require statement: ./../..
. This is because we have a specs
directory where we keep the specs and multiple directories inside grouped by application functionality under test.
The Question:
What is the canonical way to approach the relative path problem in Protractor?
In other words, we'd like to avoid traversing the tree, going up to import modules. It would be much cleaner to go down from the base application directory instead.
Attempts and thoughts:
There is a great article about approaching this problem: Better local require() paths for Node.js, but I'm not sure which of the options is a recommended one when developing tests with Protractor.
We've also tried to use require.main
to construct the path, but it points to the node_modules/protractor
directory instead of our application directory.
I had the same problem and I ended up with the following solution.
In my Protractor config file I have a variable which stores a path to a base folder of my e2e tests. Also, Protractor config provides the onPrepare
callback, where you can use a variable called global
to create global variables for your tests. You define them as a properties of that global
variable and use the same way you use globals browser
or element
in tests. I've used it to create custom global require functions to load different types of entities:
// __dirname retuns a path of this particular config file
// assuming that protractor.conf.js is in the root of the project
var basePath = __dirname + '/test/e2e/';
// /path/to/project/test/e2e/
exports.config = {
onPrepare: function () {
// "relativePath" - path, relative to "basePath" variable
// If your entity files have suffixes - you can also keep them here
// not to mention them in test files every time
global.requirePO = function (relativePath) {
return require(basePath + 'po/' + relativePath + '.po.js');
};
global.requireHelper = function (relativePath) {
return require(basePath + 'helpers/' + relativePath + '.js');
};
}
};
And then you can use these global utility methods in your test files right away:
"use strict";
var localStorageHelper = requireHelper('localStorage');
// /path/to/project/test/e2e/helpers/localStorage.js
var loginPage = requirePO('login');
// /path/to/project/test/e2e/po/login.po.js
var productShowPage = requirePO('product/show');
// /path/to/project/test/e2e/po/product/show.po.js
describe("Login functionality", function () {
beforeEach(function () {
browser.get("/#login");
localStorageHelper.clear();
});
// ...
});
相关文章