[Richard Suchenwirth] 2005-12-12 - Earlier versions of this "[testing] [framework]" are found in several pages of mine, but this latest result of evolution (or [intelligent design] ;-) just has to be shared. It's about adding self-tests to a file of [Tcl] code. When the file is loaded as part of a [library], just the [proc] definitions are executed. If however you feed this file directly to a [tclsh], that fact is detected, and the [e.g.] calls are executed. If the result is not the one expected, this is reported on stdout; and in the end, you even get a little statistics, somehow like [tcltest]. ---- # PROLOG -- self-test: if this file is sourced at top level if {[info exists argv0]&&[file tail [info script]] eq [file tail $argv0]} { set Ntest 0; set Nfail 0 proc e.g. {cmd -> expected} { incr ::Ntest catch {uplevel 1 $cmd} res if {$res ne $expected} { puts "$cmd -> $res, expected $expected" incr ::Nfail } } } else {proc e.g. args {}} ;# does nothing, compiles to nothing ##------------- Your code goes here, with e.g. tests following proc sum {a b} {expr {$a+$b}} e.g. {sum 3 4} -> 7 proc mul {a b} {expr {$a*$b}} e.g. {mul 7 6} -> 42 # testing a deliberate error (this way, it passes): e.g. {expr 1/0} -> "divide by zero" ## EPILOG -- show statistics: e.g. {puts "[info script] : tested $::Ntest, failed $::Nfail"} -> "" ---- ''[escargo] 12 Dec 2005'' - It might be interesting to refactor the code to put the predicate about ''if this file is [source]d at top level'' as a separate piece of code. Other code could then use that predicate to decide about other actions to take in that case. (I think e.g. is very clever, just by itself.) ''[escargo] 20 Mar 2006'' - I just thought of another reason for isolating the predicate. This would one of those cases where the author wants to put in a small demonstration. It's perhaps interesting to note that it might be difficult to include both unit tests and a demonstration when you can only tell if a file has been sourced at top level. It looks like you either do both or neither; there's no obvious way to decide which to do otherwise. (Unless you check for some global variable, maybe.) [RS] 2008-09-04 - For that requirement, one could use temporary environment variables: if [info exists env(XTEST)] { # activate e.g. ... } if [info exists env(XDEMO)] { # perform demo here } $ XTEST=1 XDEMO=1 myscript.tcl or, even more flexible: put the following line at a suitable position into the file: if [info exists env(DO)] {eval $env(DO)} $ DO='puts hello; do this; do that' myscript.tcl ---- [Category Testing] | [Arts and crafts of Tcl-Tk programming]