Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/node.js/38.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 在测试执行之前从模块加载数据_Javascript_Node.js_Asynchronous_Jasmine_Protractor - Fatal编程技术网

Javascript 在测试执行之前从模块加载数据

Javascript 在测试执行之前从模块加载数据,javascript,node.js,asynchronous,jasmine,protractor,Javascript,Node.js,Asynchronous,Jasmine,Protractor,(我最近问了,并接受了一个答案,但这仍然不是我需要的。)我真的需要从模块加载的数据创建动态测试。数组中的每个项都有自己的description语句,带有某些量角器动作。我上一篇文章的答案是使用it语句,但我不能这样做,因为事情太多了 我的主要问题是,description没有及时加载数据。我有另一个建议使用VCR.js或类似的东西,但我不认为这些会起作用,因为我使用的是一个模块。有没有一种方法可以将数据保存到单独的文件中并加载?那是个好办法吗 var data = require('get-da

(我最近问了,并接受了一个答案,但这仍然不是我需要的。)我真的需要从模块加载的数据创建动态测试。数组中的每个项都有自己的
description
语句,带有某些量角器动作。我上一篇文章的答案是使用
it
语句,但我不能这样做,因为事情太多了

我的主要问题是,
description
没有及时加载数据。我有另一个建议使用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();
      });
    });
  }

});
更新:

我用了尤金的答案,得出了这个结论。我无法按照我的意愿测试每项研究,因为
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();
         });
       });
     });
   }
 });

尝试使用承诺,比如:

  var deferred = protractor.promise.defer();
  var itemsPromise = deferred.promise;
  beforeAll(function() { 
    data.get(function(err, result) {
      deferred.fulfill(result);
    });
  })
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);
    });
  });

[...]
然后:

  describe('check each item', function() {
    itemsPromise.then(function(itemsArr) {
        itemsArr.forEach(function(item) {
          checkItem(item);
        });
    });
  });

我能想到的另一个解决方案是使用
浏览器。等待
直到itemsArr变为非空。

您的
获取数据
模块是否使用量角器执行一些浏览器操作?如果是这样,您将需要在controlFlow的上下文中设置/获取itemsArr。否则,它将读取
get data
模块中的所有代码,但推迟其执行,而不是等到它完成后再继续执行那些expect语句

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();
      });
    });
  }

});

您试图做一些Jasmine不允许的事情:在测试套件启动后生成测试。见《茉莉花》一期:

Jasmine不支持在套件开始运行后添加规范。通常,当我需要这样做的时候,我能够提前知道选项列表,然后循环使用它们来进行it调用。[……]

(“添加规格”==“添加测试”)

关键是,您可以动态生成测试,但只能在测试套件开始执行测试之前生成。由此产生的一个推论是,测试生成不能是异步的

您的第二次尝试不起作用,因为它正在尝试向已运行的套件添加测试

您的第一次尝试更接近您所需要的,但它也不起作用,因为
descripe
立即调用其回调,因此
before
descripe
尝试生成测试时尚未运行

解决 这一切归结为在测试套件开始执行测试之前计算
itemsArr
的值

您可以创建一个同步返回结果的
.getSync
方法。然后,您的代码将类似于:

  var deferred = protractor.promise.defer();
  var itemsPromise = deferred.promise;
  beforeAll(function() { 
    data.get(function(err, result) {
      deferred.fulfill(result);
    });
  })
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
。您可以使用的
…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();
}
然后,在等级库文件中:

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节点
测试了上面的代码。以及以下文件结构:

.
├── data.js
├── get-data.js
└── test
    └── foo.spec.js
/node\u模块
中有
蓝鸟
茉莉花节点
。这就是我得到的:

$ ./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

您是否在
data.get()
callback中检查了
err
?@mscdex我能够得到结果,但是没有及时加载
descripe('check each item')
您是否尝试在第二个descripe或it语句中调用done?考虑到它正在等待一个异步事件,这似乎是有意义的。@swestner你是什么意思?如果我在之前调用
done()
外部
它是未定义的这类工作,但我仍然有相同的问题。查看我的更新帖子当我尝试此操作时,我得到“未找到规格”,并说测试已完成,然后我再次得到forEach错误感谢您的回答。我认为第二个选项对我来说更好。如果我需要将模块放在一个单独的文件中,名为
.get()
模块。导出
函数,然后将该文件加载到我的规范中,会有什么不同吗?我已经开始尝试了,但我可能做得不对,或者这不是正确的方法。我看不出这是怎么回事。如果将
module.exports
设置为一个函数,并且此函数依赖于从
.get()
返回数据,那么您也将
模块.exports
设置为异步函数,这是您最初试图避免的问题。是的,您是对的。我想我可以尝试
child\u流程
,但我不太熟悉它的工作原理。看起来
execSync
spawnSync
都不错,但我不知道命令行选项如何与我的玩偶配合使用谢谢。我不确定这是否有效,但谢谢你的帮助和努力