Ward

A testing framework for Python 3.6 and beyond.

Descriptive testing

Describe your tests with strings, not long_and_unreadable_function_names .

@test ( "the eggs are green" ) async def _ ( ) : eggs = await get_food ( "eggs" ) assert eggs . colour == "green"

PASS test_food : 7 : the eggs are green FAIL test_users : 12 : get_user(id=1) returns user 1 SKIP test_todos : 19 : mark_done(todo_id=3) returns todo 3 [WIP]

Readable output

Understand failures quickly with colourful unified diff output.

Comparison: LHS vs RHS shown below



['apples', 'bananas', 'kiwi s']

['apples', 'bananas', 'orange s']

Powerful test tagging and selection

Tag your tests and use tag expressions to select precisely which tests to run.

$ ward --tags "(unit or integration) and slow" For example, tag tests with an issue tracker number to easily run tests associated with an issue: $ ward --tags "FEATURE-1234 or FEATURE-4567"

Modular test dependencies

Manage test setup and teardown using fixtures that rely on Python's import system, not name matching.

1. Define a unit of test data anywhere, and tell Ward how long to cache it for. user_fixtures.py @fixture ( scope = Scope . Module ) def user ( ) : u = User ( id = 1 , name = "sam" ) return u 2. Import it and bind it as a default argument. Ward will inject the resolved fixture into your test. test_users.py from user_fixtures import user @test ( "get_user returns the correct user" ) async def _ ( expected = user ) : found = await get_user ( id = expected . id ) assert found == expected

Expressive parameterised testing

Parameterise tests to have Ward call your test multiple times with different arguments.

@test ( "truncate('{text}', num_chars={num_chars}) returns '{expected}'" ) def _ ( text = s , num_chars = each ( 20 , 11 , 10 , 5 ) , expected = each ( s , s , "hello w..." , "he..." ) , ) : result = truncate ( text , num_chars ) assert result == expected Ward will expand this into 4 distinct tests, each with their own description: PASS test_util : 47 [1/4] : truncate('hello world', num_chars=20) returns 'hello world' FAIL test_util : 47 [2/4] : truncate('hello world', num_chars=11) returns 'hello world' PASS test_util : 47 [3/4] : truncate('hello world', num_chars=10) returns 'hello w...' PASS test_util : 47 [4/4] : truncate('hello world', num_chars=5) returns 'he...'

More features

ASYNC SUPPORT Write async tests and fixtures. CROSS PLATFORM Tested on Windows, Mac OS, and Linux systems. ZERO CONFIG Sensible defaults make configuration optional. TEST SEARCH Loose querying of test code for quick development. LOW OVERHEAD Roughly half the framework overhead of Pytest. WORKS WITH HYPOTHESIS Works with Hypothesis out of the box, with deeper support planned.

Interested in helping push Ward forward?