[fpc-devel] Speed of TTestCase

Martin Frb lazarus at mfriebe.de
Sat Jun 14 12:11:45 CEST 2025


I have/had several tests that took very long to run.

I have no figured out that between 50% and 80% of the time, went into 
concatenating/formatting the message for "AssertEqual" (and related).
Yes, some of my tests now run in less than 20% of the original time.

That is
- Any concatenation my code does before calling AssertEqual
- The call to ComparisonMsg in AssertEqual

So I started overloading AssertEqual

class procedure TFastTestCase.AssertEquals(const AMessage: string; 
Expected, Actual: integer);
begin
   if Expected = Actual then exit;
   inherited AssertEquals(AMessage, Expected, Actual);
end;

class procedure TFastTestCase.AssertEquals(const AMessage: string;
   const AFormatArgs: array of const; Expected, Actual: integer);
begin
   if Expected = Actual then exit;
   inherited AssertEquals(Format(AMessage, AFormatArgs), Expected, Actual);
end;

* Yes, I am aware that skips counting the amount of calls. (needs 
"Inc(AssertCount)" in case of early exit)
* The 2nd version eliminates any call to format in my own code.


I wonder if it is worth adding such changes to the official testcase.

------------------

Or maybe it is just the way I write tests?

E.g. I have a test, that computes lists, it then does

   for i := 0 to count do
     AssertEquals(format('...', [...]), AExp[i], ATestRes[i]);

Additionally those lists are tested in a loop, iterating through big 
amounts of control parameters for each test-list to be generated.

So I do end up with millions and millions of calls to AssertEqual.
And the same amount of calls to Format and ComparisonMsg, doing string 
processing.

Some of the time savings happen (and are significant) even when the test 
runs WITHOUT heaptrc.
But, using heaptrc in tests, is something that I commonly do, and string 
processing often involves mem re-allocs.




More information about the fpc-devel mailing list