fscheck/FsCheck

FsCheck generating test objects in C#

Closed this issue ยท 5 comments

Hi there ๐Ÿ‘‹

I'm trying to generate a list of C# records as test data for a property based test, but face a few issues.

1. Nullable reference types

How can I configure the generator to respect nullability of reference types in C#?

FullName is not allowed to be null -> don't generate null values
Notes is allowed to be null -> generate null values

public record Customer 
{
    public string FullName { get; init; }
    public string? Notes { get; init }
}

2. Generating complex objects

Let's assume I need to generate random samples of the type below, but there are certain rules on what's valid input.

Example Rules:
Name: Any not null string
Shorthand: First 3 chars from Name, if Name is shorter then 3 then equal to Name.
InternalPhonePrefix: Any random string.

(excuse my silly examples ๐Ÿ™ƒ)

public record Department 
{
    public string Name { get; init; }
    public string Shorthand { get; init }
    public string InternalPhonePrefix { get; init; }
}

I guess this would work, but is there a better way?

    public static Arbitrary<Department> RandomDepartment() =>
        Arb.Generate<(string, string, string)>()
            .Select(department => new Department
            {
                Name = department.Item1,
                Shorthand = department.Item2,
                InternalPhonePrefix = department.Item3
            })
            .ToArbitrary();

For number 2, you can use the query syntax

var generator =
    from name in Arb.Generate<string>()
    from phone in Arb.Generate<string>()
    select new Department
    {
        Name = name,
        Shorthand = name.Substring(0, 2),
        InternalPhonePrefix = phone
    }

For number 2, you can use the query syntax

var generator =
    from name in Arb.Generate<string>()
    from phone in Arb.Generate<string>()
    select new Department
    {
        Name = name,
        Shorthand = name.Substring(0, 2),
        InternalPhonePrefix = phone
    }

Thanks! That's quite handy

It's also useful if you're using the CSharpFunctionalExtensions nuget package. You can do the same thing with a bunch of Result's or Maybe's. Not as good as a computation expression in F#, but it gets the job done.

Nullable reference types

FsCheck cannot currently do this, based on the type alone. From a quick searc, since .NET 6 or 7 we can check the nullability of a type at runtime, so this may be possible to implement via that route.

Generating complex objects

@BennieCopeland's is probably the best way to do that.

Nullable reference types

FsCheck cannot currently do this, based on the type alone. From a quick searc, since .NET 6 or 7 we can check the nullability of a type at runtime, so this may be possible to implement via that route.

Interesting ๐Ÿ‘

Generating complex objects

@BennieCopeland's is probably the best way to do that.

Yup, that actually works pretty well.