【问题标题】:Adjust string generator to avoid "\0" with FsCheck.Xunit in C#在 C# 中使用 FsCheck.Xunit 调整字符串生成器以避免“\0”
【发布时间】:2020-08-01 11:32:05
【问题描述】:

在使用字符串输入创建 FsCheck.Xunit 单元测试时,我正在努力解决频繁出现的包含“\0”的字符串,我认为这些字符串会输入 C 库并导致字符串截断。如果您运行下面的测试,您会发现 FsCheck 经常创建包含“\0”的字符串。

调整字符串生成器以避免包含“\0”的字符串的最简单方法是什么?我需要跨多个测试的这种行为,并且正在使用 .NET Core。

BR,马克

public class NewTests
{

    [Property(Verbose = true)]
    public Property Test1(string myString)
    {
        return (!myString.Contains("\0")).ToProperty();
    }

}

【问题讨论】:

    标签: c# unit-testing xunit fscheck


    【解决方案1】:

    最简单的方法是在测试中将其过滤掉,例如使用辅助方法。但是请注意,字符串本身也可以为空。

    如果您想要可以是 null 但不包含 null 字符的字符串:

    [Property]
    public bool TestIt(StringNoNulls s)
    {
        return s.Item == null || !s.Item.Contains("\0");
    }
    

    如果你想要非空字符串:

    [Property]
    public bool TestIt(NonNull<string> s)
    {
        return s != null;
    }
    

    如果你想要两者,我没有开箱即用的东西!但是,您可以执行以下操作:

    public class CustomArbs
    {
        public static Arbitrary<string> ReallyNoNullsAnywhere()
        {
            return Arb.Default.String().Filter(s => s != null && !s.Contains("\0"));
        }
    }
    
    [Property(Arbitrary = new[] { typeof(CustomArbs) })]
    public bool TestIt(string s)
    {
        return s != null && !s.Contains("\0");
    }
    

    还有PropertiesAttribute,您可以将其放在一个类上,以覆盖该类中所有属性上特定类型集的所有 Arbitrary 实例,因此您不必在每个测试方法上添加 Arbitrary 参数。

    我最终经常使用的一个模式不是覆盖 Arbitrary&lt;string&gt; 实例本身,而是创建一个包装器类型,因此在签名中我得到的字符串类型会变得很清楚:

    public class AntiNullString
    {
        public string Get { get; }
    
        public AntiNullString(string s)
        {
            Get = s;
        }
    }
    
    public class CustomArbs
    {
        public static Arbitrary<AntiNullString> ReallyNoNullsAnywhere()
        {
            return Arb.Default.String()
                .Filter(s => s != null && !s.Contains("\0"))
                .Convert(s => new AntiNullString(s), ans => ans.Get);
        }
    }
    
    [Property(Arbitrary = new[] { typeof(CustomArbs) })]
    public bool TestIt(AntiNullString s)
    {
        return s.Get != null && !s.Get.Contains("\0");
    }
    

    【讨论】:

    • 嗨,库尔特,非常感谢您的回复。尝试遵循您的最后一个建议,我创建了下面的课程。这是避免空值和空字符的最佳方法吗?任何改变这一点的建议表示赞赏! BR,标记``` 公共类 StringNotNullAndContainsNoNulls { 私有静态 Arbitrary ArbObject { get; } = Arb.Default.StringWithoutNullChars().Filter(s => !(s is null));公共字符串项目 => ArbObject.Generator.ToString(); } ```
    • [更新到之前的评论] 格式稍微好一点:public class StringNotNullAndContainsNoNulls { private static Arbitrary&lt;StringNoNulls&gt; ArbObject { get; } = Arb.Default.StringWithoutNullChars().Filter(s =&gt; !(s is null)); public string Item =&gt; ArbObject.Generator.ToString(); }
    • 不完全是,我在答案中添加了一个示例。
    猜你喜欢
    • 2014-02-05
    • 2013-07-12
    • 1970-01-01
    • 2015-01-08
    • 1970-01-01
    • 2022-11-24
    • 2014-06-05
    • 1970-01-01
    • 2023-02-09
    相关资源
    最近更新 更多