如何在javascript/node中动态生成测试用例?

如何在javascript/node中动态生成测试用例?,javascript,node.js,testing,Javascript,Node.js,Testing,nose测试框架(用于python)支持(文档中的以下内容导致了五个不同的测试用例): 我如何使用诸如mocha或qunit之类的javascript框架实现这个结果?(目前,我并不依附于任何特定的框架。) 我的用例是编写一个测试运行程序来监视外部服务器上的几个项目。我将提供一个资源URL列表。每个测试都尝试轮询该资源,并根据找到的内容返回成功或失败。我有一个用python构建的原型(使用nose),但如果可以的话,我想在node.js中实现。最终,这将包含在CI设置中。是的,您可以使用动态创建

nose测试框架(用于python)支持(文档中的以下内容导致了五个不同的测试用例):

我如何使用诸如mocha或qunit之类的javascript框架实现这个结果?(目前,我并不依附于任何特定的框架。)


我的用例是编写一个测试运行程序来监视外部服务器上的几个项目。我将提供一个资源URL列表。每个测试都尝试轮询该资源,并根据找到的内容返回成功或失败。我有一个用python构建的原型(使用nose),但如果可以的话,我想在node.js中实现。最终,这将包含在CI设置中。

是的,您可以使用动态创建测试套件,其中包含案例。我已经在全球范围内安装了摩卡
npm安装-g mocha
,我使用


使用Mocha1.21.4,您可以按照以下方式在运行时创建套件/测试

require('chai').should()

Mocha = require 'mocha'
Test = Mocha.Test
Suite = Mocha.Suite


mocha = new Mocha
suite = Suite.create mocha.suite, 'I am a dynamic suite'
suite.addTest new Test 'I am a dynamic test', ->
  true.should.equal true

mocha.run () ->
  console.log("done")

有关更多详细信息,请参见。值得注意的是,除了上述公认的答案之外。我在下面为后代复制了它

var assert = require('assert');

function add() {
  return Array.prototype.slice.call(arguments).reduce(function(prev, curr) {
    return prev + curr;
  }, 0);
}

describe('add()', function() {
  var tests = [
    {args: [1, 2],       expected: 3},
    {args: [1, 2, 3],    expected: 6},
    {args: [1, 2, 3, 4], expected: 10}
  ];

  tests.forEach(function(test) {
    it('correctly adds ' + test.args.length + ' args', function() {
      var res = add.apply(null, test.args);
      assert.equal(res, test.expected);
    });
  });
});

如果要使用异步获取的数据动态创建
It()
测试,可以(ab)使用带有占位符
It()
测试的
before()
挂钩,以确保摩卡等待
before()
运行。为方便起见,以下是来自的示例:

before(function () {
    console.log('Let the abuse begin...');
    return promiseFn().
        then(function (testSuite) {
            describe('here are some dynamic It() tests', function () {
                testSuite.specs.forEach(function (spec) {
                    it(spec.description, function () {
                        var actualResult = runMyTest(spec);
                        assert.equal(actualResult, spec.expectedResult);
                    });
                });
            });
        });
});

it('This is a required placeholder to allow before() to work', function () {
    console.log('Mocha should not require this hack IMHO');
});

是的!来自中国的绝妙建议

下面是我使用节点的readline模块生成动态测试的示例:

const Mocha = require('mocha');
var Test = Mocha.Test;
var Suite = Mocha.Suite;

var mocha = new Mocha();
var suite = Suite.create(mocha.suite, 'My test suite with dynamic test cases');

lineReader
    .on('line', function (line) {
        suite.addTest(new Test(line, function () {
            return true;
        }));
    })
    .on('close', function () {
        mocha.run();
    });

我喜欢@rob3c的答案,但试图简化一下:

describe("Master test suite", function () {
  before(async function () {
    const rows = await mySQLQuery();

    describe(`Testing ${rows.length} rows`, function () {
      rows.forEach(function (row, index) {
        it(`Test row ${index}`, async function() {
          console.log("your row assertions go here")
        });
      });
    });
  });


  it("stub", async function(){})  // this is important!
});

您可以通过在异步方法返回响应后手动更新tests属性来完成此操作:

describe(`sometest`, function() {
  let results = null
  before(async () => {
    results = await someAsyncMethod();
    results.forEach((result, index) => {
      // to hold on to the new dynamic tests
      const newTest = it(result.name || `test ${index}`, () => {
        // do something here in test
      });
      // update the test objects before the main tests run
      this.tests.push(newTest);
    });
  });

  it(`sometest`, () => {
    expect(results.length).toBeGreaterThan(2);
  });

});

这不使用动态描述等,只是在主测试运行之前更新当前描述块

节点是否与
node.js
中的节点相同?也许您应该标记它,因为在浏览器中,
javascript
将被解释为javascript的意思。干得好,这对我来说很有用。一个简单的问题是,您可能不需要使用aysnc。您可能只需要使用['n1','fr','de'].forEach()。如果您的测试是同步的,它们将按顺序运行,并且不会比其他测试慢。如果您的测试是异步的,那么它们将异步运行,但是forEach循环将保持循环,尽管这两种方式都不重要,async.each或[]。forEach应该大致相同。除非我错过了什么,而且它()不知怎么被阻塞了?@Alex Mills你说得对。我更新了代码并删除了async.NB!这只适用于同步动态创建的测试用例。在一般情况下,Mocha不支持这一点。@polkovnikov.ph您是对的,这个被接受的答案只能同步工作,这实际上并没有回答OP关于从服务器请求生成它们的问题(在nodejs中总是异步的)。但是,您可以使用下面我的答案中的hack动态地异步生成测试:@rob3c我已经看到了您的答案,但是它比我准备在项目中放置一个库要复杂一些。我刚刚切换到
node tap
,它可以在开箱即用的情况下正常工作。我尝试了所有方法来实现这一点,包括尝试使用几乎没有文档的摩卡TDD框架。上面的方法是有效的,但我只想补充一点,外部的“descripe”实际上只是一个占位符。重要的是内部试块。一旦构建了动态测试,您将需要返回一个新的承诺,并使用一个新的“then”方法钩住该承诺,该方法将创建一个“after”块。因此,有两个承诺。@rob3c如果在()之后添加
before
块,那么您会注意到,它不会等待
before()
完成。
before()
中的循环肯定会创建所有这些
descripe()
块,但不会等待它们完成。有没有办法做到这一点?@Harry
before()
调用在调用任何声明的
after()
调用之前完成。然而,在其回调中调用的任何承诺到那时都可能尚未完成,这正是异步javascript的本质。看起来您的问题实际上是关于javascript承诺如何工作和协调的更一般的问题,而不是像这个问题中所问的那样如何动态生成mocha测试。在这里进一步讨论javascript的一般特性可能不太合适,但是如果您在搜索中没有找到满意的答案,我建议您创建一个新问题。我正试图在cypress中使用这个问题-您有没有想过为什么加载我的期望文件并运行It()会不起作用动态测试?@rex我以前没有使用过cypress.io,但FAQ说它是在mocha之上构建的,在浏览器中运行javascript。这个黑客可以在浏览器中使用普通的mocha.js,所以我不知道cypress如何包装它有什么不同。也许这最好作为一个单独的问题来问,因为这个问题是关于直接使用mocha的?这只适用于同步数据。这非常棒,因为当模拟带有“useNock”标志的请求时,它与节点tdd配合得很好
describe("Master test suite", function () {
  before(async function () {
    const rows = await mySQLQuery();

    describe(`Testing ${rows.length} rows`, function () {
      rows.forEach(function (row, index) {
        it(`Test row ${index}`, async function() {
          console.log("your row assertions go here")
        });
      });
    });
  });


  it("stub", async function(){})  // this is important!
});
describe(`sometest`, function() {
  let results = null
  before(async () => {
    results = await someAsyncMethod();
    results.forEach((result, index) => {
      // to hold on to the new dynamic tests
      const newTest = it(result.name || `test ${index}`, () => {
        // do something here in test
      });
      // update the test objects before the main tests run
      this.tests.push(newTest);
    });
  });

  it(`sometest`, () => {
    expect(results.length).toBeGreaterThan(2);
  });

});