In [16]:
%xmode plain


Exception reporting mode: Plain

battle_tested was originally created to harden your safeties.

In the example below battle_tested is being used to harden a function that is suppose to give you a predictable list of strings so you can continue with your code knowing the input has already been sanitized.


In [41]:
def list_of_strings_v1(iterable):
    """ converts the iterable input into a list of strings """
    # build the output
    out = [str(i) for i in iterable]
    # validate the output
    for i in out:
        assert type(i) == str
    # return
    return out

Here's an example of what many programmers would consider enough of a test.


In [42]:
list_of_strings_v1(range(10))


Out[42]:
['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']

The above proves it works and is pretty clean and understandable right?


In [43]:
from battle_tested import fuzz

fuzz(list_of_strings_v1)


testing: list_of_strings_v1()
Falsifying example: fuzz(arg_list=[False])
total tests: 5
Traceback (most recent call last):

  File "<ipython-input-43-62eb12834a26>", line 3, in <module>
    fuzz(list_of_strings_v1)

  File "/Users/cody/py3/lib/python3.6/site-packages/battle_tested/__init__.py", line 428, in fuzz
    fuzz()

  File "/Users/cody/py3/lib/python3.6/site-packages/battle_tested/__init__.py", line 392, in fuzz
    @given(strategy)

  File "/Users/cody/py3/lib/python3.6/site-packages/hypothesis/core.py", line 648, in wrapped_test
    state.run()

  File "/Users/cody/py3/lib/python3.6/site-packages/hypothesis/core.py", line 542, in run
    print_example=True, is_final=True

  File "/Users/cody/py3/lib/python3.6/site-packages/hypothesis/executors.py", line 58, in default_new_style_executor
    return function(data)

  File "/Users/cody/py3/lib/python3.6/site-packages/hypothesis/core.py", line 111, in run
    return test(*args, **kwargs)

  File "/Users/cody/py3/lib/python3.6/site-packages/battle_tested/__init__.py", line 424, in fuzz
    raise ex

  File "/Users/cody/py3/lib/python3.6/site-packages/battle_tested/__init__.py", line 399, in fuzz
    fn(*arg_list)

  File "<ipython-input-41-94743c50bb29>", line 4, in list_of_strings_v1
    out = [str(i) for i in iterable]

TypeError: 

------------------ battle_tested crashed list_of_strings_v1() ------------------

Error Message:

   TypeError - 'bool' object is not iterable

Breakpoint: <ipython-input-41-94743c50bb29> - line 4
To reproduce this error, run:

   list_of_strings_v1(False)

----------------------------------------------------------------------------------

And with 2 lines of code, that was proven wrong.

While you could argue that the input of the tests is crazy and would never happen with how you structured your code, lets see how hard it really is to rewrite this function so it actually can reliably act as your input's filter.


In [44]:
def list_of_strings_v2(iterable):
    """ converts the iterable input into a list of strings """
    try:
        iter(iterable)
        # build the output
        out = [str(i) for i in iterable]
    except TypeError: # raised when input was not iterable
        out = [str(iterable)]
    # validate the output
    for i in out:
        assert type(i) == str
    # return
    return out

fuzz(list_of_strings_v2)


testing: list_of_strings_v2()
tests: 52           speed: 483/sec  avg: 483
tests: 567          speed: 1504/sec  avg: 994
tests: 927          speed: 1444/sec  avg: 1144
tests: 1482         speed: 1558/sec  avg: 1247
tests: 1953         speed: 1573/sec  avg: 1312
tests: 2261         speed: 1499/sec  avg: 1343
tests: 2721         speed: 1525/sec  avg: 1369
total tests: 3208tests: 3163         speed: 1531/sec  avg: 1390
battle_tested: no falsifying examples found

With the new version, the code not only seems like it can have anything thrown at it, battle_tested prove's its validity by running thousands of tests without a single issue.