Attack Your C# Code With Property-Based Testing


If you work with .NET and C#, chances are you’ll need to write tests for your code from time to time.

Whether it is to validate the functional specifications of a new feature, check that an API behaves as expected by end users, or make sure your code isn’t breaking at some point in the future.

For these testing needs, there are plenty of different techniques available. There is unit testing. Or integration testing. Lastly, you could opt for property-based testing instead.

Property-based testing is a type of testing that checks the behavior of a program by testing a property or characteristic of the output, rather than a specific example. This allows for more comprehensive testing, as a property is less likely to be missed than a specific example.

In this article, we’ll explain property-based testing, how it can help you test software, and some sample use cases where it would be ideal for you as a developer or tester.

What is property-based testing?

Property-based testing is a software testing method in which test cases are generated automatically from a set of properties the software should satisfy. The approach is similar to unit testing in that individual unit of the software are tested for correctness.

However, in property-based testing, instead of testing a unit with a fixed set of input values, a property is selected. The unit is tested with a large number of randomly-generated input values that should all satisfy the property. If even one test case fails, the property is considered to be violated.

Example-based testing is a technique in which you test your code using only specific inputs and expected outputs.

An example of property-based testing: suppose your code defines a property called an input value, which can have values from 1 to 15. For this example, you can write a property-based test to test values between 1 to 15,  values greater than 15, and negative values. If your code survived a property-based test, it indicates that your program has a higher resilience.

How to perform property-based testing in C#?

You can call a property-based test a ‘Generative Test’ because you use a generative engine like an FSCheck to randomly generate the possible inputs and check if your properties work as they are supposed to work.

Therefore, from a property-based test, you can have a more in-depth understanding of the behavior of your functionality under the test.

FsCheck is a testing tool that can be used for property-based testing in C#. It can help you to define properties, test data generators, and monitor the test data distribution. You need to provide the program specification with properties in functions, methods, or objects that need to satisfy.

FSCheck then uses a  large number of randomly generated cases for the properties to carry out property-based testing.

How to install FSCheck

You can install the FsCheck for C# by installing the FsCheck NuGet packages. Use the following command to install it. 

dotnet add package FsCheck –version 2.16.5

For this example code, let’s also use the FsCheck.Xunit NuGet package since we will be writing tests using the xUnit unit test framework

dotnet add package FsCheck.Xunit –version 2.16.5

Example 

Let’s understand how to use this tool to write property-based tests using an example. 

Below is a sample code that declares the class MathOperations with the Divide method that divides two numbers together and returns the result, and the Add method that adds two numbers together and returns the results.

public class MathOperations
{
    public static int Divide(int x, int y)
    {
        return x / y;
    }

    public static int Add(int x, int y)
    {
        return (x + y);
    }
}

Next, let’s create a test class for property-based testing for the above two functions. You can use various types of properties in the FsCheck package based on the behavior you want to test. First, create a test project.

Then go to the test project and add the following test methods to test each function.

[Property]
public Property TestAddition(int x)
{
    return
        (MathOperations.Add(1, x) == MathOperations.Add(x, 1))
        .Classify(x > 1, "Greater than 1'")
        .Classify(x < 50, "Less than 50");
}

[Property]
public Property TestDivision(int x, int y)
{
    Func<bool> property = () => MathOperations.Divide(x * y, y) == x;
    return property.When(y != 0);
}

The TestAddition method uses a classified property to check a range of inputs to the function to check the commutative property of the addition. It states that it doesn’t matter if you reverse the order the numbers which you add.

The TestAddition method uses numbers between x > 1  and x < 50.

The second test method tests the division. It evaluates that the given input is always not below zero since you cannot divide by zero in the program. It is an example where you use ‘conditional and lazy properties” properties in the FsCheck package.

Run the tests.

Every test output provides additional information.

TestAddition test output

TestDivision test output

As you can see from the output, the test has run 100 tests for each. For our TestAddition method, you can see that 100 tests have run combining different categories of input values. 

You can use a Collect method to see the actual input values for each property-based test run. The following example code declares a collection property and prints each input value in the console in each test run.

[Property]
public Property TestAddition2(int x, int y)
{
    return (MathOperations.Add(x, y) == MathOperations.Add(y, x))
        .Collect($"Input Values : X {x} y :{y}");
}

You will get the test output as follows.

TestAddition2 test output

As you can see from the above example, the property-based tests allow you to understand the behavior of your code in more detail than usual example-based unit testing that uses only a fixed set of input values.

Conclusion

You can use property-based testing to test the code against possible inputs that can break your code. For property-based testing in C#, you can use the FsCheck Nuget package.

You can use different types of properties based on your test requirement. Property-based testing helps you understand your code’s behavior for all the possible input permutations.

Recent Posts