This talk is designed to discuss the concepts of software testing. In it, I will outline the concept of software testing and summarize the current real-world best practices and procedures. We will then discuss how to, and the difficulties of, applying this to scientific software, but we won't actually discuss how to do it this week: next time will be a tutorial for that, based on this week's feedback.
Good projects have a policy of never accepting contributions without tests.
Good projects have a policy: if someone reports a bug, add a test to reproduce the bug, then fix it. Bug will not appear again.
Tests can be a lot of work! You can easily write more lines of code to test than to solve the problem sometimes. But if code is designed well, it can be very easy.
Example of system test: having test dataset that calculates quickly. You can quickly and often run on test data to make sure the script completes and has proper output.*
Example of tests for research: you may want unit tests on calculations, integration tests on some components, and no system tests: if the whole thing breaks, you'll notice anyway.
1 2 3 4 5 6 7 8 9 10 11 12 13 | from nose.tools import assert_true, assert_equal, assert_greater_equal, assert_less
from pcd.support.growsf_gb import *
def test_sole():
# For small graphs we can exactly specify what the outcome should be:
# alpha=0, delta=0
assert_isomorphic(sole(T=3, alpha=0, delta=0),
G({0:(1,2), 1:(0,2)}))
assert_isomorphic(sole(T=4, alpha=0, delta=0),
G({0:(1,2), 1:(0,2), 3:(1,2)}))
|
Put tests in the comments/docstrings in functions:
def factorial(n): """" >>> factororial(5) 120 """ ...
When run with the doctest framework, the >>> lines are input, and output is below.
Input is evaluated and must match output.
Very simple to make, and documents as well as test
Example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | def factorial(n):
"""Return the factorial of n, an exact integer >= 0.
If the result is small enough to fit in an int, return an int.
Else return a long.
>>> [factorial(n) for n in range(6)]
[1, 1, 2, 6, 24, 120]
>>> [factorial(long(n)) for n in range(6)]
[1, 1, 2, 6, 24, 120]
>>> factorial(30)
265252859812191058636308480000000L
>>> factorial(30L)
265252859812191058636308480000000L
"""
|
Python syntax:
1 2 3 | assert test_expression, message
# test__expression - evaluated, if True then nothing happens, if false raise AssertionError
# message - only evaluated if expression is False, used as the assertion message.
|
C syntax:
1 2 3 | #include <assert.h>
assert(expression);
|
Assertions are especially useful when making new functions and code. It is an important, and cheap, sanity check.
https://en.wikipedia.org/wiki/Test-driven_development
Examples:
Benefits from this:
Please give me feedback and requests.
Simply doing an internet search for most of these topics will yield plenty of reading and tutorials of all sorts of levels.