Test Driven Development with mORMot 2 with Delphi and FPC

ArnaudBouchez1 10 views 53 slides Oct 29, 2025
Slide 1
Slide 1 of 53
Slide 1
1
Slide 2
2
Slide 3
3
Slide 4
4
Slide 5
5
Slide 6
6
Slide 7
7
Slide 8
8
Slide 9
9
Slide 10
10
Slide 11
11
Slide 12
12
Slide 13
13
Slide 14
14
Slide 15
15
Slide 16
16
Slide 17
17
Slide 18
18
Slide 19
19
Slide 20
20
Slide 21
21
Slide 22
22
Slide 23
23
Slide 24
24
Slide 25
25
Slide 26
26
Slide 27
27
Slide 28
28
Slide 29
29
Slide 30
30
Slide 31
31
Slide 32
32
Slide 33
33
Slide 34
34
Slide 35
35
Slide 36
36
Slide 37
37
Slide 38
38
Slide 39
39
Slide 40
40
Slide 41
41
Slide 42
42
Slide 43
43
Slide 44
44
Slide 45
45
Slide 46
46
Slide 47
47
Slide 48
48
Slide 49
49
Slide 50
50
Slide 51
51
Slide 52
52
Slide 53
53

About This Presentation

Every project should have tests. Every project should start by writing tests. In a nutshell, this is what Test Driven Development implies.

In this interactive session, we will try to define which paths are possible to properly include tests to new or existing projects.

As a practical example, we w...


Slide Content

Test Driven Development
with mORMot 2
The more tests…
the better

Welcome
Arnaud Bouchez
•Open Source Founder
• mORMot 1, mORMot 2, SynPDF, dmustache
•Modern Object Pascal
Delphi and FPC -Embarcadero MVP
•Synopse Tranquil IT
https://synopse.info https://tranquil.it

Welcome
Arnaud Bouchez
•Open Source Founder
• mORMot 1, mORMot 2, SynPDF, dmustache
•Modern Object Pascal
Delphi and FPC -Embarcadero MVP
•Synopse Tranquil IT
https://synopse.info https://tranquil.it

Test Driven Design
(aka TDD)
with mORMot 2

Disclaimer
This was a last time session…
so please by nice with me 

Today’s Special
•Technical Debt
•Software Seams
•Test Driven Design
•mormot2tests

Today’s Special
•Technical Debt
•Software Seams
•Test Driven Design
•mormot2tests

Technical Debt

Technical Debt

Technical Debt
We all know or even still maintain
Delphi software older than a few decades
–Stuck with Delphi 7 / 2007
–Stuck with a single database
–Stuck with unmaintained UI component(s)
–Stuck with millions of line of code,
without any unit tests

Technical Debt
Delphi software older than a few decades
–Stuck with Delphi 7 / 2007
–Stuck with a single database
–Stuck with unmaintained UI component(s)
–Stuck with millions of line of code,
without any unit tests

Technical Debt
Legacy Systems induce a technical debt
Like a financial debt,
incurs interestpayment
•Extra efforts in any future
development
•Higher maintenance costs

Technical Debt
Marco Geuzesaid this morning
that legacy code is not Technical Debt

Technical Debt
Marco Geuzesaid this morning
that legacy code is not Technical Debt
it may not be 100% debt
but it certainly has some debt

Technical Debt
Marco Geuzesaid this morning
that legacy code is not Technical Debt
but of course, it is working
and has domain/business knowledge

Technical Debt

Today’s Special
•Technical Debt
•Software Seams
•Test Driven Design
•mormot2tests

Software Seams

Software Seams

Software Seams
A place where
you can alter your program behavior
without editing in that place

Software Seams
Refactoring to isolate seams via interfaces
1.Know your subject
2.Identify responsibilities big picture
3.Study data structures
4.Break out huge functions
5.Break out giant classes iterative process
6.Encapsulate global references
7.Testing is everything

Software Seams
Refactoring to isolate seams via interfaces
1.Know your subject
2.Identify responsibilities big picture
3.Study data structures
4.Break out huge functions
5.Break out giant classes iterations
6.Encapsulate global references
7.Testing is everything

Software Seams
Refactoring to isolate seams via interfaces
•AI tools may help
with iterations

Software Seams
From interface comes abstraction
•SOLID principles
•SOA and (Micro)Services
•Database agnostic
•Testing/mocking

Today’s Special
•Technical Debt
•Software Seams
•Test Driven Design
•mormot2tests

Test Driven Design

Test Driven Design

Test Driven Design
Coding is an Iterativeprocess
•Even up to the management level
(projects)
•Ensure each step won’t break any
previous step
•Testing should be part of this process

Test Driven Design
Test Driven Design (TDD)
means “iterate from tests into tests”

Test Driven Design
TDD means “let tests pass”
1.Write the test
2.Fails the test
3.Implements the feature
4.Fails the test ? Drink a coffee and go to 3.
5.Pass the test and all previous tests
6.Continue to the next feature

Test Driven Design
Test Driven Designmain benefits
Ensure we didn’tbreak anything
Expect we won’tbreak anything

Test Driven Design
•Test Driven Design collateralbenefits
•Define the types and API early
•Refine the expectations ASAP
•Document the API before implementing
•Can mock the UI before implementing
•Tests as specification

Test Driven Design
•Mocking / Stubbing
"The Art of Unit Testing“
(Osherove, Roy -2009)
–The power of fake objects
Stubs and Mocks

Test Driven Design
•Mocking / Stubbing
"The Art of Unit Testing" (Osherove, Roy -2009)
–Stubsare fake objects
implementing a given contract
and returning pre-arranged responses
•They just let the test pass
•They “emulate” some behavior
(e.g. a database)

Test Driven Design
•Mocking / Stubbing
"The Art of Unit Testing" (Osherove, Roy -2009)
–Mocksare fake objects like stubs
which will verify if an interaction occurred
or not
•They help decide if a test failed or passed
•There should be only onemock per test

Mocks and
Stubs

Test Driven Design
TLoginController= class(TInterfacedObject, ILoginController)
protected
fUserRepository: IUserRepository;
fSmsSender: ISmsSender;
public
constructorCreate(const aUserRepository: IUserRepository;
const aSmsSender: ISmsSender);
procedureForgotMyPassword(const UserName: RawUtf8);
end;
constructorTLoginController.Create(const aUserRepository: IUserRepository; const
aSmsSender: ISmsSender);
begin // dependencies injection in constructor
fUserRepository:= aUserRepository;
fSmsSender:= aSmsSender;
end;

Test Driven Design
IUserRepository= interface(IInvokable)
['{B21E5B21-28F4-4874-8446-BD0B06DAA07F}']
functionGetUserByName(constName: RawUtf8): TUser;
procedureSave(constUser: TUser);
end;
ISmsSender= interface(IInvokable)
['{8F87CB56-5E2F-437E-B2E6-B3020835DC61}']
functionSend(constText, Number: RawUtf8): boolean;
end;

Test Driven Design
procedureTLoginController.ForgotMyPassword(
constUserName: RawUtf8);
varU: TUser;
begin
U := fUserRepository.GetUserByName(UserName);
U.Password:= Int32ToUtf8(Random31);
iffSmsSender.Send('Your new password is ' +
U.Password, U.MobilePhoneNumber) then
fUserRepository.Save(U);
end;

Expect –Run –Verify pattern
procedureTMyTest.ForgotMyPassword;
varsms: ISmsSender;
repo: IUserRepository;
begin
TInterfaceStub.Create(ISmsSender, sms).
Returns('Send', [true]);
TInterfaceMock.Create(IUserRepository, repo, self).
ExpectsCount('Save', qoEqualTo, 1);
withTLoginController.Create(repo, sms) do
try
ForgotMyPassword('toto');
finally
Free;
end;

Run –Verify (aka “Test spy”)
procedureTMyTest.ForgotMyPassword;
varsms: ISmsSender;
repo: IUserRepository;
spy: TInterfaceMockSpy;
begin
TInterfaceStub.Create(ISmsSender, sms).Returns('Send', [true]);
spy := TInterfaceMockSpy.Create(IUserRepository, repo, self);
withTLoginController.Create(repo, sms) do
try
ForgotMyPassword('toto');
finally
Free;
end;
spy.Verify('Save');

Test Driven Design
Mocking / Stubbing -another features
•Return complex values (e.g. a DTO)
•Use a delegate to create a stub/mock
•Using named or indexed variant parameters
•Using JSON array of values

Test Driven Design
Mocking / Stubbing -another features
•Access the test case when mocking
•Trace and verify the calls
•With a fluent interface
•Log all calls (as JSON)

Today’s Special
•Technical Debt
•Software Seams
•Test Driven Design
•mormot2tests

mormot2tests

mormot2tests

mormot2tests
Where I spend most of my time:
Write a new feature test
Implement the feature
Debug to let it pass
Run all other tests

mormot2tests
Console application
•Part of mORMot repository
•Delphi and FPC
•On all supported systems (LUTI)

mormot2tests
Several kind of tests
Unitary tests
Integration tests
Stability tests (threads, OS…)
Performance tests

mormot2tests
“LUTI” nightly integration tests
https://luti.tranquil.it/listfolder/b469
db22-f483-45c2-90a8-
f640c1eb8457

mormot2tests
SHOW ME THE CODE !

To Visit the marmots
https://cauterets.site

Questions?