(我最近问了 this question 并接受了一个答案,但它仍然不是我需要的。)我真的需要根据从模块加载的数据创建动态测试。数组中的每一项都将拥有自己的 describe
语句以及特定的 Protractor 操作。我以前的帖子有一个答案说要使用 it
语句,但我不能那样做,因为发生的事情太多了。
我的主要问题是数据没有及时加载describe
。我有另一个建议使用 VCR.js 或类似的东西,但我认为这些不会起作用,因为我使用的是模块。有没有办法可以将数据保存到单独的文件并加载它?那是个好方法吗?
var data = require('get-data'); //custom module here
describe('Test', function() {
var itemsArr;
beforeAll(function(done) {
data.get(function(err, result) {
itemsArr = result; //load data from module
done();
});
})
//error: Cannot read property 'forEach' of undefined
describe('check each item', function() {
itemsArr.forEach(function(item) {
checkItem(item);
});
});
function checkItem (item) {
var itemName = item.name;
describe(itemName, function() {
console.log('describe');
it('should work', function() {
console.log('it');
expect(true).toBeTruthy();
});
});
}
});
更新:
我使用了 Eugene 的答案并想出了这个。我无法按照自己的意愿测试每个单独的研究,因为 it
语句不会触发。这个问题还能解决吗??
describe('check each item', function () {
it('should load data', function (done) {
browser.wait(itemsPromise, 5000);
itemsPromise.then(function(itemsArr) {
expect(itemsArr).toBeTruthy();
studyArr = itemsArr.filter(function (item) {
return item.enabled && _.contains(item.tags, 'study');
});
studyCount = studyArr.length;
expect(studies.count()).toEqual(studyCount);
checkItems(studyArr);
done();
});
});
function checkItems (itemsArr) {
itemsArr.forEach(function (item) {
describe(item.id, function () {
console.log('checkItems', item.id);
// doesn't work
it('should work', function (done) {
expect(false).toBeTruthy();
done();
});
});
});
}
});
最佳答案
您正在尝试做一些 Jasmine 不允许的事情:在测试套件启动后生成测试。参见 this comment关于 Jasmine 的问题:
Jasmine doesn't support adding specs once the suite has started running. Usually, when I've needed to do this, I've been able to know the list of options ahead of time and just loop through them to make the it calls. [...]
("添加规范"=== "添加测试")
重点是您可以动态生成测试,但只能在测试套件开始执行测试之前。其一个推论是测试生成不能是异步的。
您的第二次尝试没有成功,因为它试图将测试添加到已在运行的套件中。
您的第一次尝试更接近您的需要,但它也不起作用,因为 describe
立即调用其回调,因此 beforeAll
尚未在您的 describe
尝试生成测试。
解决方案
这一切都归结为在测试套件开始执行测试之前计算 itemsArr
的值。
您可以创建一个 .getSync
方法来同步返回结果。您的代码将类似于:
var data = require('get-data'); //custom module here
var itemsArr = data.getSync();
describe('Test', function() {
describe('check each item', function() {
itemsArr.forEach(function(item) {
checkItem(item);
});
});
[...]
如果无法编写 .getSync
函数,您可以让外部进程负责生成 JSON 输出,然后您可以将其反序列化为 itemsArr
。您将使用 child_process
的 ...Sync
功能之一执行此外部进程| .
这是第二个选项如何工作的示例。我用以下代码创建了一个 get-data.js
文件,该文件使用 setTimeout
来模拟异步操作:
var Promise = require("bluebird"); // Bluebird is a promise library.
var get = exports.get = function () {
return new Promise(function (resolve, reject) {
var itemsArr = [
{
name: "one",
param: "2"
},
{
name: "two",
param: "2"
}
];
setTimeout(function () {
resolve(itemsArr);
}, 1000);
});
};
// This is what we run when were are running this module as a "script" instead
// of a "module".
function main() {
get().then(function (itemsArr) {
console.log(JSON.stringify(itemsArr));
});
};
// Check whether we are a script or a module...
if (require.main === module) {
main();
}
然后,在 spec 文件中:
var child_process = require('child_process');
var itemsArr = JSON.parse(child_process.execFileSync(
"/usr/bin/node", ["get-data.js"]));
describe('Test', function() {
itemsArr.forEach(function(item) {
checkItem(item);
});
function checkItem (item) {
var itemName = item.name;
describe(itemName, function() {
console.log('describe');
it('should work', function() {
console.log('it');
expect(true).toBeTruthy();
});
});
}
});
我已经使用 jasmine-node
测试了上面的代码。以及以下文件结构:
.
├── data.js
├── get-data.js
└── test
└── foo.spec.js
./node_modules
中有 bluebird
和 jasmine-node
。这是我得到的:
$ ./node_modules/.bin/jasmine-node --verbose test
describe
describe
it
it
Test - 5 ms
one - 4 ms
should work - 4 ms
two - 1 ms
should work - 1 ms
Finished in 0.007 seconds
2 tests, 2 assertions, 0 failures, 0 skipped
关于javascript - 在测试执行之前从模块加载数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34231878/