- Always Ask for examples. (not only you will need them for tests but also they clarify details and estimates)
- Always Challenge examples. (it is never enough details)
- Always precise obvious cases, express them with examples.
- Never forget edge cases. (don't make decisions instead of your client)
- Never forget exceptions.
- Use Hexagonal Architecture principles. This enables unit reliable testing without bothering with mocking tools that (if used in a wrong way) may turn your project into a real broken-as-you-touch-it real mess.
- Public methods are ruled by contracts, they need carefull design and communication.
- Coding by wishful thinking.
- Fake it till you make it.
- YAGNI: You Are Not Gonna Need It !
- BoyScout Principle: “Try and leave the world a little better than you found it”.[Robert Baden-Powell]
- DRY: Don't Repeat Yourself.
- KISS: Keep It Simple(Stupid).
- Tell don't ask.
SRP: Single Responsibility Principle
- A class, a function, a variable should have a unique functional reason to change.
- Always think about functional responsibility within an abstraction layer.
- How to be sure that I am not getting it wrong: Within a given abstraction layer, name the element by its functional responsibilities (Aggregate and hide details). => If the name contains OR | AND then SRP is violated.
OCP: Open Closed Principle
- Each public class or function should be closed to modification and opened for extension:
- Changing details requirements should remain in the details (private utilities methods or dependencies)
- Adding a new case of the same rule should'nt push you to modify the signature or the implementation of your exposed methods.
LSP: Liskov substitution principle
- If S is a subtype of T, then objects of type T in a program may be replaced with objects of type S without altering any of the desirable properties of that program
ISP: Interface segregation principle
- Clients shouldn't be forced to depend on methods they do not use.
DIP: Dependency Inversion Principle
- The use case doesn't instantiate its dependencies, but it only defines them (contracts).
- High-level modules should not depend on low-level modules. Both should depend on abstractions(contracts).
- Abstractions should not depend on details. Details should depend on abstractions.
-
NEVER TEST TECHNICAL DETAILS
-
NEVER TEST PRIVATES
-
Tests are independent and isolated. One test should never influence a second one.
-
Stub Never Mock:
Why should you avoid mocking ?
- It validates functional specifications.
- It captures behaviors and no technical details.
- It allow Algorithm discovery.
- Those tests provide immediate feedback when developing existing or new features.
- They are extremely fast. (~1second)
- It stubs dependencies.
- It is framework independent.
- It grants functional non regression as a consequence.
- It validates that dependencies behave as expected.
- In general, it tests what we stubbed in unit tests.
- It is a test that crosses all layers (UI, Config, Service, UseCase...) and grants the expected behaviour from the point of view of the user.
- No mocks, no stubs, no fakes...they are system tests.
- We do little E2E testing because they are fragile and can break easily.
- UI details can change easily so you can do snapshot testing (happy and failure scenarios) to capture accidental regressions.
- We do Baby Steps and discover design by following what the tests need incrementally.
red -> green -> refactor -> red...
red: I dont write any production code unless I have a failing unit test that require it.
green: I write minimum code that strictly satisfies the test.
refactor: I make the code S.O.L.I.D.
- Broken SRP: After naming correctly, the name contains OR or AND keywords.
- BAD Design: Changing method visibility only to be able to test it.
- Tests are not UNIT: Test suite passes some time, some times not.
- Test FOCUS: changing technical details break one or more tests.