Python SDK tutorial, times10 function

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

You write the function in Python 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 function using the Antithesis Python SDK.

The rest of the document walks you through this process.

Creating your project

Step 0: Write your project. You begin by writing your function in Python with print debugging.

Make a directory where you would like to create your Python project and cd to that directory. (Our directory is /home/me/Projects – this will be printed in the logs later.)

mkdir myapp
cd myapp

Create a file myapp.py with the following content:

def times10(x: int) -> int:
    result = x * 10
    return result

def main():
    print("Hello, world!")
    print(f"3 x 10 = {times10(3)}")
    print(f"8 x 10 = {times10(8)}")

if __name__ == '__main__':
    main()

Now run:

python myapp.py

and it prints

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

Using our SDK functions

Recall that the basic SDK workflow is:

  1. Use SDK functions in your code.
  2. Run your Python project.

Step 1: Include the Antithesis SDK in dependencies

    python -m pip install antithesis

Step 2: Use Antithesis SDK functions in your code

You wrote a function 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.

Here’s how you’d do this with our SDK assertions:

from antithesis.assertions import sometimes, always
from antithesis.random import get_random

def times10(x: int) -> int:
    sometimes(x % 2 == 1, "input is sometimes odd", {"input": x})
    result = x * 10
    always(result % 2 == 0, "result is always even", {"result": result})
    return result

def main():
    print("Hello, world!")
    for i in range(50):
        x = get_random() % 500
        print(f"{x} x 10 = {times10(x)}")

if __name__ == '__main__':
    main()
  • Lines 1-2 You import the assert and random libraries.

  • You add two assertions to times10.

    • Line 7 You assert that the result is always even using an always assertion.

    • Line 5 You insert a Sometimes Assertion, stating that something will happen at least once across the entire testing session; in this case, that the function will be called with an odd argument.

      The two assertions complement one another: Always Assertions assert that the behavior is correct, while Sometimes Assertions assert that you’re testing under wide enough conditions to surface any potential incorrect behavior, to ensure the desired properties are not being trivially satisfied.

  • Lines 12-14 You use randomness to call the function with many random values (between 0 and 500). Previously, you called the function with hard-coded values but now you’ll pass the function random 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’re passing the function odd values, whereas previously the tests were hard-coded so you were certain that you were passing it odd values.

    You call the random package’s GetRandom function to draw a random number, and then pass this random number to times10. You use a loop to do this 50 times in a row. Every time the times10 function is called in this loop, it triggers the assertions in lines 12 & 14.

  • In summary You’ll test times10 by passing it a random integer 50 times in a row. You have asserted that all 50 outputs must be even and that at least one random input must be odd.

Step 3: Deploy your project

If you’re planning for local deployment then you’d be done here, but suppose instead you intend to send your project to Antithesis for testing. 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.

This example is simplified compared to what the full quickstart guide describes. Note that the function main is the workload and times10 is the software itself. There are no other 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.