Programming Testing: Good Tests

From wikinotes
  1. You must write tests that can be explicitly trusted
  2. Tests must be maintainable (which includes not taking a long time to maintain them)
  3. Tests must be readable


1. Trustworthy Tests

  • Tests should *never* contain logic (if statements, case statements, etc) (if they do, split it into 2x tests).
  • Write test before code. Write code until test is satisfied. Change values in test to make sure it is not a false positive.
  • copy-on-write tests. Do not modify a test. create a new test, and make sure they are both satisfied before deleting the old test.
  • Unit-tests should not depend on anything not contained in the functions being tested.
  • Unit-tests should be run separately from integration tests. All unit tests should pass, regardless of changes.
  • Test public-methods only. Private methods are more likely to be renamed, or change.
    • If you feel the need to test a private method, consider making it public as a member of a new class. (not sure I agree with this entirely).
    • An alternative view is to write tests at the highest-possible level that does not require mocking - regardless of public/private.
  • one assert per test (otherwise if first test fails, no other tests run)

2. Maintainable Tests

  • keep tests short. very short. 2-5 lines short.
    • Tests should compare a result to a constant-value
    • a TestCase setUp() method is run before every individual test. Place code common to all tests there.
    • If some code is reused in a handful of tests, extract it into it's own method.

3. Readable Tests

  • test-method names must read like a sentence. (tests are not called, they can be long)
  • readability is more important in tests than maintainability.
  • add params to test, repeat same test using multiple sets of values
from pytest import mark
@mark.parametrize(('numbers', 'expected'), [
    ('',    0),
    ('1',   1),
    ('1,2', 3),
])
def test_resultOfSum( numbers, expected ):
    result = str_sum( numbers )
    assert result == expected