On 11/10/2013 5:06 AM, Tarek Ziadé wrote:
Le 11/10/13 11:00 AM, Markus Unterwaditzer a écrit :
While it is a nice idea, i don't think this feature deserves its own syntax.
To put it another way, we already have syntax support for testing: assert, which is sugar for conditional stateements, but with extra features; and functions, which are executed when called.
Like most suggested new keywords, 'where' is certain to by in use already as an identifier. So we need a really good reason, with no better alternative, to make it a keyword.
yes, that's what we all already do: tests in test_xxx functions. And the adopted convention is to have the tests in dedicated tests modules, which defeats the benefit of having real isolated unit tests just by the function code.
As others have noted, one big reason for the convention is that testing class methods usually requires big chunks of code that are better isolated in another file. However, the convention is not a rule, and for pure module-level functions that run in isolation, one is free to include tests in the doc string or just after. See example below.
And even if we place the test function just besides the tested function, Python will not make any distinction : they are both just functions.
Functions are fine. Distinction is easily done by an obvious name convention.
Having the ability to distinguish tests and regular code at the language level has benefits like the ability to ignore tests when you run the app in production etc.
Functions only run when called.
For my book, most example code consists of classical functions. For these, I am doing the following, adapted for your sum example. For didactic reasons, I like having the tests immediately follow the function code; the input-output pairs serve as testable documentation. (This code does not run at the moment as I am midstream in changing the test module.) The first and last statements are boilerplate that is part of a _template.py file.
from xploro.test import main, ftest
def sum_rec(seq): if seq: return seq + sum_rec(seq[1:]) else: return 0
def sum_for(seq): ret = 0 for num in seq: ret += num return ret
def test_sum(): ftest((sum_rec, sum_for), ((, 0), (, 1), ([1,2,3], 6),) )
if __name__ == '__main__':
ftest calls each function with each input of the input-output pairs and checks that the function output matches the output given. main scans globals() for functions named 'test_xxx' and calls them.
Anyway, I prefer the above to the 'where' suggestion.
-- Terry Jan Reedy