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.

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
  • Welcome to Antithesis
  • How Antithesis works
  • Using Antithesis with AI
  • Get started
  • Setup guide
  • Overview
  • For Docker Compose users
  • For Kubernetes users
  • Test an example system
  • Overview
  • With Docker Compose
  • Overview
  • Build and run an etcd cluster
  • Add a test template
  • With Kubernetes
  • Overview
  • Build and run an etcd cluster
  • Add a test template
  • Product
  • Test templates
  • Overview
  • Creating test templates
  • Test commands
  • How to check a test template locally
  • How to port tests to Antithesis
  • Test launchers
  • The triage report
  • Overview
  • Findings
  • Environment
  • Utilization
  • Properties
  • Logs Explorer & multiverse map
  • Debugging
  • Overview
  • Causality analysis
  • Multiverse debugging
  • Simple Multiverse debugging
  • Advanced
  • Overview
  • The Antithesis multiverse
  • Querying with event sets
  • Environment utilities
  • Using the Antithesis Notebook
  • Cookbook
  • Tooling integrations
  • CI integration
  • Discord and Slack integrations
  • Issue tracker integration - BETA
  • Configuration
  • Access and authentication
  • The Antithesis environment
  • Best practices
  • Docker best practices
  • Kubernetes best practices
  • Optimizing for testing
  • Concepts
  • Properties and Assertions
  • Overview
  • Properties in Antithesis
  • Assertions in Antithesis
  • Sometimes Assertions
  • Properties to test for
  • Fault injection
  • Reference
  • Webhooks
  • Overview
  • Launching a test
  • Launching a debugging session
  • webhook reference
  • Antithesis API
  • Handling external dependencies
  • SDK reference
  • Overview
  • Define test properties
  • Generate randomness
  • Manage test lifecycle
  • Assertion catalog
  • Coverage instrumentation
  • Go
  • Go SDK
  • Instrumentor
  • Tutorial
  • Assert (reference)
  • Lifecycle (reference)
  • Random (reference)
  • Java
  • Java SDK
  • Using the SDK
  • Building your software
  • Tutorial
  • Assert (reference)
  • Lifecycle (reference)
  • Random (reference)
  • C SDK
  • C++
  • C++ SDK
  • C/C++ Instrumentation
  • Tutorial
  • Assert (reference)
  • Lifecycle (reference)
  • Random (reference)
  • JavaScript
  • Python
  • Python SDK
  • Tutorial
  • Assert (reference)
  • Lifecycle (reference)
  • Random (reference)
  • Rust
  • Rust SDK
  • Instrumentation
  • Tutorial
  • Assert (reference)
  • Lifecycle (reference)
  • Random (reference)
  • .NET
  • .NET SDK
  • Instrumentation
  • Tutorial
  • Assert (reference)
  • Lifecycle (reference)
  • Random (reference)
  • Languages not listed above
  • Fallback SDK
  • Assert (reference)
  • Lifecycle (reference)
  • Assertion Schema
  • FAQ
  • Product FAQs
  • About Antithesis POCs
  • Release notes
  • Release notes
  • General reliability resources
  • Reliability glossary
  • Techniques for better software testing
  • Autonomous testing
  • Deterministic simulation testing
  • Property-based testing
  • White paper — How much does an outage cost?
  • Catalog of reliability properties for key-value datastores
  • Catalog of reliability properties for blockchains
  • Test ACID compliance with a ring test