What is Antithesis? How we're different Problems we solve Security approach Demo Fintech Blockchain Databases Customer stories Working with Antithesis Contact us Backstory Leadership Careers Brand Distributed systems reliability glossary Cost of outages white paper Deterministic simulation testing Property-based testing

.NET SDK tutorial, Times10 method

You are a 10x programmer and will soon have your annual performance review, so you are writing a method that takes any number and multiplies it by ten. That way if anybody names some productivity, you can respond with your 10x-greater productivity.

You write the method in C# and at first you use print debugging. However, this performance review is very important for your career so you decide not to take any chances. You ultimately decide to thoroughly test this method using the Antithesis .NET SDK.

The rest of the document walks you through this process.

Creating your project

Step 0: Create your project

You begin by writing your class in C# with System.Console.WriteLine debugging. cd to a directory where you would like to create your C# project. Use the dotnet CLI to create a new console project as shown below. A directory will be created for the new project.

dotnet new console --name MyTimes10App

Edit MyTimes10App/Program.cs with the following content:

static int Times10(int x)
{
    int result = x * 10;
    return result;
}

Console.WriteLine("Hello, world!");
Console.WriteLine($"{3} x 10 = {Times10(3)}");
Console.WriteLine($"{8} x 10 = {Times10(8)}");

Now run your changes.

dotnet run --project MyTimes10App

and it prints

Hello, world!
3 x 10 = 30
8 x 10 = 80

Using our SDK classes

Recall that the basic SDK workflow is:

  1. Add a PackageReference to Antithesis.SDK in your .NET project file.
  2. Call SDK methods from your code.
  3. Build your .NET project.
  4. Deploy your build.

Step 1: Add a PackageReference to Antithesis.SDK in your .NET project file

The Antithesis.SDK package is available on NuGet:

<PackageReference Include="Antithesis.SDK" Version="1.0.31" />

Step 2. Call SDK methods from your code

You wrote a method to multiply numbers by ten. What sorts of properties should it have? The output should always be even. You should also make sure you are testing a wide variety of inputs, such as both even and odd numbers.

Modify the code. The modifications are individually explained below.

using Antithesis.SDK;
using System.Text.Json.Nodes;

static int Times10(int x)
{
    // Input value
    var inputDetails = new JsonObject() { ["input"] = x };
    Assert.Sometimes(x % 2 == 1, "input is sometimes odd", inputDetails);

    // Calculated result
    int result = x * 10;
    var resultDetails = new JsonObject() { ["result"] = result };
    Assert.Always(result % 2 == 0, "result is always even", resultDetails);

    return result;
}

Console.WriteLine("Hello, world!");

for (int i = 0; i < 50; i++)
{
    int x = Antithesis.SDK.Random.SharedFallbackToSystem.Next(500);
    Console.WriteLine($"{x} x 10 = {Times10(x)}");
}
  • Lines 1-2 You imported the Antithesis .NET SDK and support for System.Text.Json.Nodes.JsonObject.

  • You added two assertions to Times10.

    • Line 13 You assert that the result is even using an Always Assertion. This is a fairly conventional assertion.

    • Line 8 You insert a Sometimes Assertion, or an assertion that something will happen at least once across the entire testing session. You assert that sometimes during testing, the method will be called with an odd argument.

      The two types of assertions complement one another: Always Assertions assert that the behavior is correct, whereas Sometimes Assertions assert that you are testing under wide enough conditions to surface any potential incorrect behavior. In this case, the output would trivially be even if you only passed it even inputs – you must ensure your properties are not being trivially satisfied!

    • Lines 20-24 You use randomness to call the method with many random values (between 0 and 499). Previously, you called the method with hardcoded values but now you will pass the method values and test that the output is always even. This approach is more powerful but makes Sometimes Assertions necessary – now you must test that you are passing the method odd values, whereas previously the tests were hardcoded so you were certain that you were passing it odd values.

  • You call the method Next to draw a random integer, and then pass this random integer to Times10. You use a loop to do this fifty times in a row. Every time the Times10 method is called in this loop, it triggers the assertions in lines 8 & 13.

  • In summary: You’ll test Times10 by passing it a random integer fifty times in a row. You’ve asserted that all fifty outputs must be even and that at least one random integer must be odd.

You can now build and run your project:

dotnet run --project MyTimes10App

Preparing your project for Antithesis

To send code to Antithesis, you should build as described above. Antithesis will explore your software and search for violations of the properties you have defined.

You must send us containers as described in getting started. The executable should be included in your container.

This example is simplified compared to what the full quickstart guide describes. Note that the C# top level statements are the workload and the Times10 method is the software itself. There are no dependencies.

Ultimately, you’ll receive a triage report that confirms the properties you defined are true: the output of the function is always even and the inputs to the function are sometimes odd. You now have a well-tested function that can multiply numbers by ten, indisputably proving that you’re a 10x programmer.

  • Introduction
  • How Antithesis Works
  • Tutorial
  • Testing with Antithesis
  • Build and run an etcd cluster
  • Meet the Test Composer
  • User manual
  • Setup guide
  • Properties and Assertions
  • Properties in Antithesis
  • Assertions in Antithesis
  • Sometimes Assertions
  • Properties to test for
  • Test Composer
  • Test Composer basics
  • Test Composer reference
  • Principles of test composition
  • Checking test templates locally
  • Getting started with Test Composer
  • Webhooks
  • Launching a test
  • Retrieving logs
  • Launching a debugging session
  • Webhook API
  • Reports
  • The triage report
  • Findings
  • Environment
  • Utilization
  • Properties
  • The bug report
  • Context, Instance, & Logs
  • Bug likelihood over time
  • Statistical debug information
  • Search dashboard & multiverse map
  • Multiverse debugging
  • Overview
  • The Antithesis multiverse
  • Querying with event sets
  • The Environment and its utilities
  • Using the Antithesis Notebook
  • Cookbook
  • Antithesis' testing environment
  • The Antithesis Environment
  • Fault Injection
  • CPUID
  • Reference
  • Handling External Dependencies
  • SDK reference
  • Go
  • Tutorial
  • Instrumentor
  • Assert (reference)
  • Lifecycle (reference)
  • Random (reference)
  • Java
  • Tutorial
  • Instrumentation
  • Assert (reference)
  • Lifecycle (reference)
  • Random (reference)
  • C
  • C++
  • Tutorial
  • C/C++ Instrumentation
  • Assert (reference)
  • Lifecycle (reference)
  • Random (reference)
  • JavaScript
  • Python
  • Tutorial
  • Assert (reference)
  • Lifecycle (reference)
  • Random (reference)
  • Rust
  • Tutorial
  • Instrumentation
  • Assert (reference)
  • Lifecycle (reference)
  • Random (reference)
  • .NET
  • Tutorial
  • Instrumentation
  • Assert (reference)
  • Lifecycle (reference)
  • Random (reference)
  • Languages not listed above
  • Assert (reference)
  • Lifecycle (reference)
  • Assertion Schema
  • Tooling integrations
  • CI integration
  • Discord and Slack integrations
  • Issue tracker integration - BETA
  • Configuring Antithesis
  • Instrumentation
  • User management
  • Sizing your deployment
  • Best practices
  • Docker best practices
  • Is Antithesis working?
  • Optimizing for Antithesis
  • Finding more bugs
  • FAQ
  • About Antithesis POCs
  • Product FAQs
  • Release notes
  • Release notes