Prenons un use case : SignUp
La post-condition qu'on veut c'est :
👉 L'utilisateur peut s'authentifier
👉 👉 Donc son compte utilisateur existe en DB [1]
👉 Un email de bienvenue lui a été envoyé
👉 Il est inscrit à la newsletter s'il y consent
Le code associé, pour être compréhensible donc maintenable, devrait ressembler à ceci :
class SignUp
[...]
def run
create_user_account
send_welcome_email
if newsletter_consent?
subscribe_to_newsletter
end
end
[...]
end
Et il n'y a que deux tests fonctionnels à écrire, parce qu'il n'y a qu'une seule condition.
Si vous avez introduit un bus, des événements, des ports, des adapters et plein d'injection de services pour rendre votre code testable unitairement, grand bien vous fasse.
Il y a de grandes chances que vous ayez :
👉 rendu le code impigeable pour les suivants
👉 complexifié en introduisant des abstractions accidentelles
👉 écrit des tests rapides certes, mais qui passent trivialement
👉 déplacé la découverte de bugs vers la prod
Perso, je défends :
💡 qu’un use case n'est PAS testable en unitaire, par nature.
💡que la complexité est mieux placée dans l’infra de tests que dans la logique business.
💡qu’il faut plutôt investir dans des tests d'intégration et une CI convenables
#SoftwareEngineering
dire "the database is a detail" c’est soutenir que la postcondition "l'utilisateur peut s'authentifier après s'être inscrit" n'a pas d'importance. En effet, c’est nier la POST-condition la plus importante du use case. ↩︎