code testability
TRANSCRIPT
Code TestabilityYury Kisliak @ EIS Group
Objectives:
- how to write a code which is easy to unit-test
Out of scope:
- why unit-testing is important
- how to write good unit-tests
- TDD and other bullcrap interesting things
Design flaws
- Constructor does Real Work
- Digging into Collaborators
- Brittle Global State & Singletons
- Class Does Too Much
Constructor does Real Work
Warning signs:
- constructor arguments initialization
- conditions and cycles
- transferring a part of the constructor into the other methods of the class (init methods)
- getting knowledge from arguments
- creating class variables using “new”
- calling any static methods
Constructor arguments initialization
Constructor arguments initialization
Single Responsibility Principle violation.Inflexible and prematurely coupled design.
Constructor arguments initialization
Single Responsibility Principle violation.Inflexible and prematurely coupled design.
Conditions and cycles
Conditions and cycles
The test is bound up with some flag. A priori it is possible to test only two engines.
Conditions and cycles
The test is bound up with some flag. A priori it is possible to test only two engines.
init method
Single Responsibility Principle violation."init" is not tested.
init method
Single Responsibility Principle violation."init" is not tested.
init method
Digging into Collaborators
Warning signs:
- a method goes through more than one point (.) within an object
- a method does not use its argument directly (though uses it to obtain other information)
- suspicious names: context, environment, principal, container, or manager
a method does not use its argument directly
Test setup overhead.You should study UserContext class.
a method does not use its argument directly
Test setup overhead.You should study UserContext class.
a method does not use its argument directly
a method does not use its argument directly
a method does not use its argument directly
SalesTaxCalculator is coupled to User and Invoice. Reusability suffers.[Class “cashier” needs the method input of the class “money”, not “wallet”]
a method does not use its argument directly
SalesTaxCalculator is coupled to User and Invoice. Reusability suffers.[Class “cashier” needs the method input of the class “money”, not “wallet”]
Global State & Singletons
Warning signs:
- global state (mutable statics)
- singletons
● The problem in using singletons is that they form strong cohesion within the code. By creating a singleton you claim that your classes can only work with a single realization which is provided by a singleton. You do not provide the opportunity to replace it.
● The presence of singletons makes your classes be inaccurate about their dependencies as far as it introduces “invisible” dependencies.
Global State & Singletons
Global State & Singletons
Global State & Singletons
Global State & Singletons
Global State & Singletons
Global State & Singletons
Global State & Singletons
Class Does Too Much
Hard to understand, maintain, debug and test.
Warning signs:
- Ambiguous name
- Excessive scrolling
- Many fields
- Many methods
- Clumping of unrelated/related methods
- Many collaborators
- It’s hard to hold in your head at once and understand it as a single chunk of behavior.
Class Does Too Much
Fixing the Flaw
- rewrite / throw away
- cover with tests and refactor
- leave as it is, observe as it becomes even uglier as time goes by, suffer.
The end!
References:
Full version:
http://misko.hevery.com/
Light version:
http://geekandseek.com/web-development/how-to-write-testable-code/
(https://habrahabr.ru/company/mailru/blog/267277/#a4 in Russian)