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

标签 javascript node.js asynchronous jasmine protractor

(我最近问了 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 中有 bluebirdjasmine-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/

相关文章:

javascript - 反向 Javascript 触发 CSS 动画

JavaScript 调用对象语法

javascript - jQuery - $(this) + 选择器 - .each()

javascript - 在node.js上显示html

node.js - createWriteStream 和路径不起作用

c - select(2)为什么叫 "synchronous"多路复用?

c++ - grpc c++ 异步完成队列事件

javascript - 如何显示下一张幻灯片和/或上一张幻灯片的某些像素?

javascript - index.html 不从 babel 加载转译的 javascript

c# - 如何在新线程上运行任务并立即返回给调用者?