| 10-06-2007, 08:49 PM | #1 |
Unit testing is a common practice intended to check that each layer of your code is probably correct. Typically it's not so important for warcraft because map code is shallow and non cyclical; each trigger is mostly unrelated to the next. Nonetheless I found it very helpful when doing updating rounds on systems. The goal is to automatically run a bunch of tests for your functions when debug mode is enabled. Here's a small library I'm using to help out: JASS:library Test initializer RunTests function interface proposition takes nothing returns boolean public function Closeto takes real x, real y returns boolean return RAbsBJ(x - y) <= 0.001 endfunction private function prop_Closeto takes nothing returns boolean return Closeto(1,1) and Closeto(1,1.0005) and not Closeto(0,1) endfunction public function DebugMsg takes string s returns nothing call BJDebugMsg(s) call Cheat("DebugMsg: "+s) endfunction public function Assert takes string name, proposition t returns nothing if t.evaluate() then call BJDebugMsg("|cff00ff00"+"OK "+"|r"+name) call Cheat("DebugMsg: OK "+name) else call DebugMsg("|cffff0000"+"Failed "+"|r"+name) call Cheat("DebugMsg: Failed "+name) endif endfunction private function RunTests takes nothing returns nothing debug local string n = "SelfTest " debug call Test_Assert(n+"Closeto",proposition.prop_Closeto) endfunction endlibrary
One thing that sucks about doing things this way is that just returning false when a test fails is pretty lame. You have to go through commenting and uncommenting each return in the function until you find the failure. It needs something like return ("this failed test",false) or throw out propositions and the function passing and use assert inside the test cases. Prepending every line with debug sucks, and the RunTests function gets called anyway. What sort of preprocessing power would make this easier? Are there more generic functions like Closeto that every tester should have? |
| 10-07-2007, 09:39 AM | #2 |
The best idea I have is adding out parameters (or ref parameters). An option that doesn't need preprocessor changes is changing it to return a string and interpreting an empty string as true. I'm not going to suggest throw/catch *shudders* As for utility functions: You'll often want to display rawcodes, so Rawcode2Integer and Integer2Rawcode functions may be a good addition. I don't know if people still use I2H, if that's the case an IsValid<Handle> function can be nice. However I don't know if this can be implemented for certain handle types (timers, triggers). At least it's possible for widgets (GetTypeId function) |
