FsCheck:如何生成依赖于其他测试数据的测试数据?
FsCheck: How to generate test data that depends on other test data?
FsCheck 有一些简洁的默认 Arbitrary
类型来生成测试数据。但是,如果我的一个考试日期取决于另一个考试日期怎么办?
例如,考虑 string.Substring()
的 属性 结果子字符串永远不会比输入字符串长:
[Fact]
public void SubstringIsNeverLongerThanInputString()
{
Prop.ForAll(
Arb.Default.NonEmptyString(),
Arb.Default.PositiveInt(),
(input, length) => input.Get.Substring(0, length.Get).Length <= input.Get.Length
).QuickCheckThrowOnFailure();
}
虽然 Substring
的实现当然是正确的,但这个 属性 失败了,因为最终会生成一个 PositiveInt
比生成的 NonEmptyString
更长的结果一个例外。
Shrunk: NonEmptyString "a" PositiveInt 2 with exception: System.ArgumentOutOfRangeException: Index and length must refer to a location within the string.
我可以保护与 if (input.Length < length) return true;
的比较,但如果 属性 甚至没有被检查,我最终会进行大量测试。
如何让 FsCheck 只生成不超过输入字符串的 PositiveInt
?我想我必须使用 Gen<T>
class,但它的界面让我很困惑......我尝试了以下但仍然 PositiveInt
s 超出了字符串:
var inputs = Arb.Default.NonEmptyString();
// I have no idea what I'm doing here...
var lengths = inputs.Generator.Select(s => s.Get.Length).ToArbitrary();
Prop.ForAll(
inputs,
lengths,
(input, length) => input.Get.Substring(0, length).Length <= input.Get.Length
).QuickCheckThrowOnFailure();
您可以创建依赖于使用 SelectMany
从另一个生成的值的生成器。这也允许您使用 LINQ 查询语法,例如
var gen = from s in Arb.Generate<NonEmptyString>()
from i in Gen.Choose(0, s.Get.Length - 1)
select Tuple.Create(s, i);
var p = Prop.ForAll(Arb.From(gen), t =>
{
var s = t.Item1.Get;
var len = t.Item2;
return s.Substring(0, len).Length <= s.Length;
});
Check.Quick(p);
FsCheck 有一些简洁的默认 Arbitrary
类型来生成测试数据。但是,如果我的一个考试日期取决于另一个考试日期怎么办?
例如,考虑 string.Substring()
的 属性 结果子字符串永远不会比输入字符串长:
[Fact]
public void SubstringIsNeverLongerThanInputString()
{
Prop.ForAll(
Arb.Default.NonEmptyString(),
Arb.Default.PositiveInt(),
(input, length) => input.Get.Substring(0, length.Get).Length <= input.Get.Length
).QuickCheckThrowOnFailure();
}
虽然 Substring
的实现当然是正确的,但这个 属性 失败了,因为最终会生成一个 PositiveInt
比生成的 NonEmptyString
更长的结果一个例外。
Shrunk: NonEmptyString "a" PositiveInt 2 with exception: System.ArgumentOutOfRangeException: Index and length must refer to a location within the string.
我可以保护与 if (input.Length < length) return true;
的比较,但如果 属性 甚至没有被检查,我最终会进行大量测试。
如何让 FsCheck 只生成不超过输入字符串的 PositiveInt
?我想我必须使用 Gen<T>
class,但它的界面让我很困惑......我尝试了以下但仍然 PositiveInt
s 超出了字符串:
var inputs = Arb.Default.NonEmptyString();
// I have no idea what I'm doing here...
var lengths = inputs.Generator.Select(s => s.Get.Length).ToArbitrary();
Prop.ForAll(
inputs,
lengths,
(input, length) => input.Get.Substring(0, length).Length <= input.Get.Length
).QuickCheckThrowOnFailure();
您可以创建依赖于使用 SelectMany
从另一个生成的值的生成器。这也允许您使用 LINQ 查询语法,例如
var gen = from s in Arb.Generate<NonEmptyString>()
from i in Gen.Choose(0, s.Get.Length - 1)
select Tuple.Create(s, i);
var p = Prop.ForAll(Arb.From(gen), t =>
{
var s = t.Item1.Get;
var len = t.Item2;
return s.Substring(0, len).Length <= s.Length;
});
Check.Quick(p);