(我最近问this question并接受了答案,但它仍然不是我需要的。)我真的需要根据从模块加载的数据创建动态测试。数组中的每个项目都有自己的describe
语句,并带有某些量角器操作。我之前的帖子有一个答案,说要使用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();
});
});
});
}
});
答案 0 :(得分:3)
您正在尝试执行Jasmine不允许的操作:在测试套件启动后生成测试。有关Jasmine的问题,请参阅this comment:
一旦套件开始运行,Jasmine不支持添加规范。通常,当我需要这样做时,我已经能够提前知道选项列表并且只是循环通过它们来进行调用。 [...]
("添加规格" ==="添加测试")
关键是你可以动态生成测试,但之前测试套件已开始执行测试。其中一个推论是测试生成不能是异步的。
您的第二次尝试不起作用,因为它正在尝试将测试添加到已经运行的套件中。
您的第一次尝试更接近您的需求,但它不起作用,因为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
答案 1 :(得分:0)
尝试使用承诺,例如:
var deferred = protractor.promise.defer();
var itemsPromise = deferred.promise;
beforeAll(function() {
data.get(function(err, result) {
deferred.fulfill(result);
});
})
然后:
describe('check each item', function() {
itemsPromise.then(function(itemsArr) {
itemsArr.forEach(function(item) {
checkItem(item);
});
});
});
我能想到的另一个解决方案是使用browser.wait
等待itemsArr变为空。
答案 2 :(得分:0)
你的get-data
模块是否正在使用量角器做一些浏览器?如果是这样,您将需要在controlFlow的上下文中设置/获取itemsArr。否则,它将读取get-data
模块中的所有代码,但是推迟执行,而不是等到它完成,然后再向前移动到那些期望语句。
var data = require('get-data'); //custom module here
var itemsArr;
describe('Test', function() {
beforeAll(function() {
// hook into the controlFlow and set the value of the variable
browser.controlFlow().execute(function() {
data.get(function(err, result) {
itemsArr = result; //load data from module
});
});
});
//error: Cannot read property 'forEach' of undefined
describe('check each item', function() {
// hook into the controlFlow and get the value of the variable (at that point in time)
browser.controlFlow().execute(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();
});
});
}
});