In the last post, I only went into profiling. Here's a simple testing usage scenario. Suppose you want to make sure that a certain body of code throws an exception of a particular type. That means you have to wrap it up in a try / except block, and test the type of the exception. The logic to do this would be quite repetitive if it had to be expanded out long-hand. Fortunately, that's not the case:
procedure ExpectException(ExClass: ExceptClass; const Code: TProc); var noThrow: Boolean; begin noThrow := False; try Code; noThrow := True; except on e: Exception do if not e.ClassType.InheritsFrom(ExClass) then raise Exception.CreateFmt('Failed - %s expected, %s actually raised', [ExClass.ClassName, e.ClassName]); end; if noThrow then raise Exception.CreateFmt('Failed - %s not raised', [ExClass.ClassName]); end;
Here it is in use:
var list: TList; begin list := TList.Create; try ExpectException(EListError, procedure begin list[42] := nil; end); finally list.Free; end; end;
2 comments:
Now that is quite neat. Very similar to the sort of test code I write with Smoketest:
procedure TTestCase.TestMethod;
begin
try
.. test case code
ExpectException(EAccessViolation);
except
ExpectException(EAccessViolation);
end;
The need to repeat the ExpectException() test being needed to catch both the pass (got the exception) and fail (didn't) conditions.
That repetition isn't particularly arduous but it is a little ugly.
This is a nice example. Thanks for the blogs, I'm almost beginning to understand these anonymous methods ;-)
Post a Comment