#----------------------------------------------------------------
#
# customMatch matchDouble
#
# Custom match routine that performs word-by-word comparisons
# using expr's floating point comparison operation (!=)
# for words that are [string is double].
#
# This custom match routine is required for tests to
# run on Microsoft Windows (and perhaps other) platforms
# where floating point numbers get a three digit
# exponent (i.e. 3.0e008 instead of 3.0e08).
#
# Note that this routines treats all white space (spaces,
# tabs and newlines) as equal.
#
#----------------------------------------------------------------
customMatch matchDouble matchDoubleProc
proc matchDoubleProc {expectedResult actualResult} {
# split expected/actual into list of words
set elist [split $expectedResult " \t\n"]
set alist [split $actualResult " \t\n"]
# perform word-by-word comparison
foreach eword $elist aword $alist {
if { [string is double $eword] && ! [string is integer $eword] } {
# perform numeric comparison
if { $eword != $aword } {return 0}
} else {
# perform string comparison
if { $eword ne $aword } {return 0}
}
}
return 1
}jnc The above was not working in my test cases. What about this?
proc matchDoubleProc {expectedResult actualResult} {
set expectedFormatted [format $expectedResult]
set decimalCount [string length [lindex [split $expectedFormatted "."] 1]]
set fmtCode "%.${decimalCount}f"
set actualFormatted [format $fmtCode $actualResult]
if { $expectedFormatted eq $actualFormatted } {
return 1
}
return 0
}An interesting variant on matchDouble would use a sigma parameter for approximate comparisons.
glennj I just started with tcltest and one use for customMatch jumped out at me. When I write functions that return a boolean, they might return the string "true" or "false", or they might return the result of an [expr] command (1/0). I wrote this customMatch that ensures the expected and actual values are either both true or both false (uses [apply], so required Tcl 8.5):
# test passes if expected and actual are both true or both false
customMatch boolean {apply {{e a} {expr {
[string is boolean -strict $e] &&
[string is boolean -strict $a] &&
(($e && $a) || (!$e && !$a))
}}}}The applied [test] command looks like:
test test-name {boolean command should return true} \
-body {command that returns some boolean value} \
-match boolean \
-result trueEF The following customMatch will test equality of dictionaries. It also uses [apply], thus is for "modern" Tcl. Note that it assumes that the content of the keys are strings, which might not be appropriate in all cases.
customMatch dictionary {apply {{expected actual} {
if {[dict size $expected] != [dict size $actual]} { return 0 }
dict for {k v} $expected {
if {![dict exists $actual $k]} { return 0 }
if {[dict get $actual $k] ne $v} { return 0 }
}
return 1
}}}
