1

我开始使用 JSVerify 进行基于属性的测试。

给定一个接受字符串作为参数的函数(只是一个示例),我使用 JSVerify 传入大量任意字符串,并查看函数的行为是否符合所有字符串的预期。事实证明,有一些字符串会导致测试失败:到目前为止,我发现如果字符串包含\0000, \0001or \n,则测试失败。

我想更正我的代码,以便相应地处理这种情况,但为了防止回归,我想确保每个测试运行都包含这些情况。我还想避免对数字生成器的种子 ( rngState) 进行硬编码,因为这会阻止将来发现其他极端情况。

澄清一下:假设我正在测试我的功能foo()

jsc.assert(jsc.forall("string", (str) => {
  const result = foo(str)
  return (/* some expression that evaluates whether the result is correct */)
}))

foo()每次运行测试套件时,该测试都会向其中输入 100 个随机字符串。最初它正在通过。在一些运行之后它突然失败,因为这一次,随机字符串生成器生成了一个包含字符的字符串\0000,我的函数没有按预期处理。从现在开始,我希望我的测试每次都使用这个字符串作为输入,再加上通常的 100 个随机输入。

是否有使用 JSVerify 的内置方法来执行此操作?还是我应该将这些输入视为单独的测试用例?

4

1 回答 1

0

这就是我解决你提到的问题的方式。除了在每次测试调用中运行一个随机种子之外,我的代码还可以根据需要指定尽可能多的“坏”种子,而不是测试特定值。

注意:1)我使用的是 Mocha 2)我使用的是异步代码,所以我返回一个 Promise 3)这JSON.stringify让我可以很容易地看到上面给出的种子

您仍然可以在没有上述 1,2,3 的情况下使用此方法,并进行一些重构:

const _ = require('lodash');
var jsc = require('jsverify');

// mocha's describe
describe("StackOverflow", function () {
  it('example1', function(done) {

    let t = jsc.forall('array nat', function (in1) {
      let asComplex = foo(in1);
      let backAgain = bar(asComplex);

      return new Promise(function(resolve, reject) {
        setTimeout(() => {
          resolve(_.isEqual(backAgain,in1));
        },500); // setTimeout
      }); // promise
    }); // forall

    let props = {size:0xffffffff, tests: 1000};
    jsc.check(t, props).then( r => r === true ? done() : done(new Error(JSON.stringify(r))));
    props.tests = 3;
    jsc.check(t, props).then( r => r === true ? done() : done(new Error(JSON.stringify(r))));
    props.rngState = "8e1da6702e395bc84f";
    jsc.check(t, props).then( r => r === true ? done() : done(new Error(JSON.stringify(r))));
    // add more seeds here
  }); // it
}); // describe
于 2019-01-22T10:20:09.190 回答