/ $Id: kUnit.k.html,v 1.9 2001/06/22 07:02:12 sg Exp $
/ each test lives in an own file:
/   in subdirectory defined by TESTDIR (default <test>)
/   with name test*.k, test*.t or test*.s
/   containing everything needed to run the test
/   file <setUp.k> - if defined - is used to set things up for the testrun (.d.touch, defining vars etc)
/   file <tearDown.k) - if defined - cleans up after the testrun (rmdir temp directories etc)
/ run with:
/   showTestResults runTests[]
/ or in kdb:
/   runTests[]
/ then browse TESTRESULTS with something like:
/   ksql>show select from TESTRESULTS where fail
/
/ use stepTest to walk through a failing k test line by line

/ configuration, override these values in setUp.k
TESTDIR:"test" / use "\\" as path delimiter in TESTDIR, its used for dir as well as \l and \s
HIGHLIGHTPERCENT:10 / highlight the records in top nn% by time, set to 0 to disable
MAXMSDEFAULT:0i / allow setting an upper bound beyond which a test automatically fails

/ make assert available for all tests - works in K and Kdb
asserT:{:[~x;'y]}
assert:asserT[;"assert"]

baseKLoad:{."\\l ",TESTDIR,"/",x}
baseKdbLoad:{.d.r("load?";,(TESTDIR,"/",x))}

stepTest:{."\\s ",TESTDIR,"/",x}

loadTest:{[loader;fileName]
    MAXMS::MAXMSDEFAULT /default in case its not defined in the test file
    T:_T
    r:.[loader;fileName;:]
    r,:,ms:_(_T-T)*/24 60 60 1000
    r,:MAXMS
    r,:ms>MAXMS
    r,,fileName}

kLoad:loadTest[`baseKLoad]
kdbLoad:loadTest[`baseKdbLoad]

/ /o-d ensures newest tests get run first (most likely to break)
kTests:{:[*r:.[{`4:x};("dir ",TESTDIR,"\\test*.k /b/o-d");:];();*|r]}
kdbTests:{:[*r:.[{`4:x};("dir ",TESTDIR,"\\test*.t ",TESTDIR,"\\test*.s /b/o-d");:];();*|r]}

runTests:{ / run all found k&ksql tests
    :[*r:.[0::;TESTDIR,"\\nul";:];'"TESTDIR not found";]
    kLoad"setUp.k"
    r:kLoad'kTests[]
    if[7=4:.d.r
        kdbLoad"setUp.t"
        r,:kdbLoad'kdbTests[]
        kdbLoad"tearDown.t"]
    kLoad"tearDown.k"
    asserT[;"no tests"] 0<#r
    / save results as a global, then can browse them in kdb
    :TESTRESULTS::.+(`fail`err`ms`MAXMS`failms`fileName;+r)}

allOk:{&/~x.fail}

showTestResults:{ / if not in kdb then use this to browse
    results:x
    results.fail..e:results.err..e:results.ms..e:results.MAXMS..e:results.failms..e:results.fileName..e:0
    results.fail..f:4$
    results.fail..bg:009900 990000 results.fail
    results.fail..fg:000000 999999 results.fail
    results.err..f:-11$
    results.ms..f:5$
    if[0<HIGHLIGHTPERCENT::100&0|HIGHLIGHTPERCENT
        results.ms..bg:808000 999900 results.ms>{_0.01*(100-HIGHLIGHTPERCENT)*|/x}results.ms]
    results.MAXMS..f:{:[x=0i;"";-5$x]}
    results.failms..f:4$
    results.failms..bg:009900 990000 results.failms
    results.failms..fg:000000 999999 results.failms
    results.fileName..f:-25$
    td:_ssr[TESTDIR;"\\";"\\\\"]
    . n,"..l:\"kUnit :: ",td," :: TESTRESULTS/",(n:$`show$results),"; ",($+/results.ms),"ms\""}
    
sR:{showTestResults runTests x}

`0:"  sR[] / sR:{showTestResults runTests x}\n"