Skip to main content

before_after provides utilities for testing race conditions

Project description

before_after provides utilities to help test race conditions.

When testing Python programs that run in multiple threads or processes it’s useful to simulate race conditions to ensure you handle them properly. before_after provides two functions, before and after, that allow you to insert pre or post functions to be called before/after a function you want to test.

See this blog post for a practical example of using before_after in tests.

Patching

before_after is sugar over the Mock library. It’s recommended that you read the docs before using before_after, especially Where to patch.

Example usage

Practical example of testing race conditions

def before_fn(*a, **k):
    print 'before_fn called with', a, k

def after_fn(*a, **k):
    print 'after_fn called with', a, k

def hello(name, greeting='Hello'):
    print '{greeting} {name}!'.format(
        greeting=greeting, name=name)

with before_after.before('__main__.hello', before_fn):
    hello('World')

# before_fn called with ('World',) {}
# Hello World!

with before_after.after('__main__.hello', after_fn):
    hello('everybody', greeting='Hi there')

# Hi there everybody!
# after_fn called with ('everybody',) {'greeting': 'Hi there'}

Use with recursive functions

By default, before_after only calls the before_fn/after_fn function once. This is useful if you’re calling the original function within the before_fn/after_fn, since otherwise you’ll blow the stack. This behaviour can be disabled by passing once=False.

my_list = []

def before_fn(*a, **k):
    print 'calling my_append in before_fn'
    my_append(1)

def my_append(item):
    print 'appending', item, 'to my_list'
    my_list.append(item)
    print 'my_list is now', my_list

with before_after.before('__main__.my_append', before_fn):
    my_append(2)

# calling my_append in before_fn
# appending 1 to my_list
# my_list is now [1]
# appending 2 to my_list
# my_list is now [1, 2]

with before_after.before('__main__.my_append', before_fn, once=False):
    my_append(2)

# calling my_append in before_fn
# calling my_append in before_fn
# calling my_append in before_fn
# ...
# RuntimeError: maximum recursion depth exceeded while calling a Python object

It’s recommended that if you’re passing once=False that you make sure your program will exit cleanly!

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

before_after-0.1.3.tar.gz (3.8 kB view details)

Uploaded Source

File details

Details for the file before_after-0.1.3.tar.gz.

File metadata

  • Download URL: before_after-0.1.3.tar.gz
  • Upload date:
  • Size: 3.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No

File hashes

Hashes for before_after-0.1.3.tar.gz
Algorithm Hash digest
SHA256 3290bda2d6c721cf407c1358721c1f02fdc5ceb7de528508f36924a791f02a63
MD5 77a8ef0887695d277cf134f60f563678
BLAKE2b-256 bd05ee7c4131e2e9a89d019507bc95862057be2a49ec53abd48e8ec78a1f1849

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page