【问题标题】:Generating unique strings in FsCheck在 FsCheck 中生成唯一的字符串
【发布时间】:2016-04-20 16:56:32
【问题描述】:

我需要生成唯一的非null 字符串用作Dictionary 键。我试过类似的东西:

 public static Gen<NonNull<string>> UniqueStrings()
 {
     return from s in Arb.Default.NonNull<string>().Generator
            select s;
 }

然后我使用UniqueString() in:

public static Arb<Foo> Foos()
{
    // Foo's constructor will use the string parameter
    // as key to an internal Dictionary
    return (from nonNullString in UniqueStrings()
            select new Foo(nonNullString.Item)).ToArbitrary();
}

但是,我在属性测试 Foo 时遇到异常,因为 FsCheck 有时会两次生成相同的字符串,从而导致 DuplicateKeyException

如何生成唯一字符串以传递给Foo 的构造函数?

【问题讨论】:

  • 我错过了什么吗?基于 Guid 的 Guid.NewGuid().ToString(); 将是唯一的字符串。

标签: c# fscheck property-based-testing


【解决方案1】:

您可以在插入字典之前添加一个简单的检查,而不是生成 uniq 字符串。

更新: 好的。在一代之后洗牌你的字符串。你可以阅读here
它是关于整数数组,但您可以轻松地为字符串自定义它

【讨论】:

  • 我尽量不要修改Foo 的实现,因为我只是想防止FsCheck 生成相同的string 密钥。修改Foo的实现就像回避问题而不是解决问题。
【解决方案2】:

要生成唯一字符串,您可以使用 Guid 生成器,这是生成唯一字符串的标准方法,即使跨多台计算机也是如此。

【讨论】:

  • 虽然 guid 是唯一的,但它们也具有相同的长度和字符集,这可能足以或可能不足以测试具有足够多样化输入集的算法(空值、长字符串、特殊字符等...)。
【解决方案3】:

您无法强制FSCheck生成器生成唯一值,因为您基本上没有访问先前生成的值的历史,也不会FSCheck本身保证唯一性。

在这种情况下,您可以在这种情况下进行,例如生成字符串列表,然后唯一的ify使用Distinct()例如列表。然后,您还可以使用类似的方法生成Foo列表。

例如:

Gen<Foo[]> res = from s in Arb.Default.Set<string>().Generator
                 select s.Select(ss => new Foo(ss)).ToArray();

(注意你不能从中获取ss out因为c#不允许你混合不同的linq方法,一个是在Gen,一个是在IEnumerable

一个propos,我想知道这不是您要检查的额外财产。如果用户的Foo应该给它一个唯一的字符串,那是如何支持的?如果他们没有?

会发生什么

【讨论】:

  • 您介意显示如何唯一的ify字符串列表,然后将它传递给Foo的构造函数?我尝试了类似于from ss in Gen.Default.Set&lt;NonNull&lt;string&gt;&gt;().Generator from s in ss select new Foo(s)但我得到一个编译错误,说没有SelectMany 987654330 @ span>
  • 我的意思是Arb.Default span>
  • @ 987654332的构造函数@将插入string到987654334 @所以如果string参数不是唯一的,它会抛出。恕我直言,这不是一个很好的设计,因为前提是如此不清楚,但我别无选择,只能坚持这个实施。我所能做的就是生成更多的测试,希望发现它的缺陷。 span>
猜你喜欢
  • 1970-01-01
  • 2014-11-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-11-21
  • 2010-10-18
  • 1970-01-01
相关资源
最近更新 更多