C#,xunit,fscheck:使用自定义生成器或受限随机字符串编写简单的属性测试

4
我正在尝试解决钻石卡塔问题,以学习如何使用fscheck库编写基于属性的测试。我想用C#编写测试,并使用Visual Studio 2017。
我想编写一个基于属性的测试,只生成字母而非随机字符作为输入。但我不确定如何编写fscheck所需的生成器,并将代码放在哪个文件中?
我已经搜索了各处并阅读了文档,但遇到了麻烦(部分原因是我无法很好地将F#翻译成C#)。
如何使用[Property]来限制输入数据只包含字母?
如果有更好的方法,请告诉我。
[编辑:]
我编辑了我的代码示例,其中包含 Kurt Schelfthout 的一个可行解决方案。

测试
using DiamondKata;
using FsCheck;
using FsCheck.Xunit;
using Xunit;

namespace DiamondKataTests
{
    public static class Arbitraries
    {
        private static readonly string upperAlphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
        private static readonly string lowerAlphabet = ""; //upperAlphabet.ToLower();
        private static readonly char[] wholeAlphabet = (lowerAlphabet + upperAlphabet).ToCharArray();
        public static Arbitrary<char> LetterGenerator()
        {
            return Gen.Elements(wholeAlphabet).ToArbitrary();
        }
    }

    public class DiamondKataTests
    {
        // THIS WORKS and is apparently the preferred way of doing things
        // also see here: https://dev59.com/ilwY5IYBdhLWcg3wRF9S
        [Property()]
        public Property shouldReturnStringAssumesValidCharWasProvided()
        {
            return Prop.ForAll(Arbitraries.LetterGenerator(), letter =>

                // test here
                Assert.NotNull(Diamond.Create(letter))
            );
        }

        // Second solution ...
        // Error here: Arbitraries is a type not valid in the given context
        [Property(Arbitrary = new[] { typeof<Arbitraries> })]
        public void testThatAssumesValidCharWasProvided(char lettersOnlyHERE)
        {
            // ?
        }
    }
}

测试类

namespace DiamondKata
{
    public class Diamond
    {
        public static string Create(char turningPointCharacter)
        {
            return "";
        }
    }
}

如果您将Arbitraries设置为非静态类,则第二种解决方案应该起作用。 - Jeff Walker Code Ranger
1个回答

4

您不能在属性中设置约束条件,可以传递给属性的类型受到限制,无法实现这一点。

您有几个选择。您可以为char定义自定义的Arbitrary实例,即Arbitrary<char>的实现,并配置属性以使用该实例。

public static class Arbitraries
{
    public static Arbitrary<char> LetterGenerator()
    {
        return Gen.Elements(wholeAlphabet).ToArbitrary();
    }
}

public class DiamondKataTestClass1
{
    [Property(Arbitrary=new[] { typeof<Arbitraries> })]
    public void testThatAssumesValidCharWasProvided(char lettersOnlyHERE)
    {
        // ?
    }
}

您可以使用更加灵活的API来内联自定义生成器:
public class DiamondKataTestClass1
{
    [Property()]
    public Property testThatAssumesValidCharWasProvided()
    {
        Prop.ForAll(Arbitraries.LetterGenerator()) (letter =>
        // test here
        )
    }
}

{btsdaf} - Shakka
{btsdaf} - Shakka

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接