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