Как я могу динамически генерировать тестовые случаи в javascript/node?

Инфраструктура носового тестирования (для python) поддерживает динамическое создание тестовых случаев во время выполнения (из документации видно, что в пяти различных тестовых случаях):

def test_evens():
    for i in range(0, 5):
        yield check_even, i, i*3

def check_even(n, nn):
    assert n % 2 == 0 or nn % 2 == 0

Как я могу достичь этого результата, используя JavaScript-фреймворки, такие как mocha или qunit? (Я не привязан к какой-либо конкретной структуре на данный момент.)

Мой пример использования - написание тестового прогона для мониторинга нескольких элементов на внешнем сервере. Я хотел бы предоставить список URL ресурсов. Каждый тест пытается опросить этот ресурс и возвращает успех или неудачу в зависимости от того, что он находит. У меня есть прототип, встроенный в python (использующий нос), но я хотел бы реализовать в node.js, если смогу. В конце концов, это будет включено в настройку CI.

5 ответов

Решение

Да, вы можете динамически создавать тестовые наборы с кейсами, используя Mocha. Я установил мокко по всему миру npm install -g mocha и я использую должен.

var should = require('should');

var foo = 'bar';

['nl', 'fr', 'de'].forEach(function(arrElement) {
  describe(arrElement + ' suite', function() {
    it('This thing should behave like this', function(done) {
      foo.should.be.a.String();
      done();
    });
    it('That thing should behave like that', function(done) {
      foo.should.have.length(3);
      done();
    });
  });
});

Если вы хотите динамически создавать It() тесты с использованием данных, полученных асинхронно, вы можете (ab) использовать before() крюк с заполнителем It() тест, чтобы убедиться, что мокко ждет, пока 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');
});

С Mocha 1.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")

См. https://gist.github.com/cybertk/fff8992e12a7655157ed для получения дополнительной информации.

Стоит отметить, что в дополнение к принятому ответу, приведенному выше, документы Мокко теперь включают пример того, как этого добиться. Я воспроизвел это ниже для потомков.

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

Ага! Гениальный совет от Quanlong!

Вот мой пример генерации динамического теста с модулем readline Node:

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

});

При этом не используются динамические описания и т. Д., Просто обновляется текущий блок описания перед запуском основных тестов!

Другие вопросы по тегам