The greatest benefit you will gain by writing good unit
tests is the quality of your code design. Good unit tests put a high
pressure on refactoring your code to be testable, resulting
maintainable, extensible and reusable code. This will increase your
team efficiency. In this talk I will show what good unit tests mean,
how to write them and I will briefly exemplify how unit tests ask for
better code
1. Good Unit Tests Ask For
Quality Code
Florin Coroş
Software Architect, ISDC
2. Code Design Qualities
• Quality attributes for good code design:
• Maintainability,
• Extensibility,
• Reusability
• This is reached by:
• OOD Principles, like SOLID principles, IoC, SoC…
• Design Patterns: GoF
• Experienced Developers
• Main benefits:
• Reduced cost of change
• Reduced accidental complexity
• Reduced cost of operation
2
3. Good Unit Tests
• Definition:
• A unit test is an automated piece of code that invokes the method or
class being tested and then checks some assumptions about the
logical behavior of that method or class.
• A unit test is almost always written using a unit-testing framework.
• It can be written easily and runs quickly.
• It’s fully automated, trustworthy, readable, and maintainable.
• Quality Attributes of Good Unit Tests
• Readable
• Maintainable
• Trustworthy
3
4. Good Unit Tests - Properties
A unit test should have the following properties:
• It should be automated and repeatable.
• It should be easy to implement.
• Once it’s written, it should remain for future use.
• Anyone should be able to run it.
• It should run at the push of a button.
• It should run quickly
• It should run in isolation
• It should test ONE thing
• If it fails you should know exactly where the bug is
4
5. Integration Tests
Definition
• Integration testing means testing two or more dependent
software modules as a group.
Conclusion:
• An integration test exercises many units of code that work
together to evaluate one or more expected results from the
software
• An unit test exercises and tests only a single unit in isolation.
5
6. External Dependencies,
Stubs, Mocks
• An external dependency is an object in your system that your code
under test interacts with, and over which you have no control.
(Common examples are file systems, threads, memory, time, and so
on.)
• A stub is a controllable replacement for an existing dependency (or
collaborator) in the system. By using a stub, you can test your code
without dealing with the dependency directly.
• A mock object is a fake object in the system that decides whether
the unit test has passed or failed. It does so by verifying whether the
object under test interacted as expected with the fake object. There’s
usually no more than one mock per test.
6
7. Coding – Testing Cycle
Code First:
1. Implement small chunk of functionality (a function)
2. Write unit tests for it
3. After all tests pass refactor the code, both production and test. Do it
with small changes and check that all the tests are still passing after
each change
Tests First (TDD)
1. You may not write production code until you have written a failing
unit test.
2. You may not write more of a unit test than is sufficient to fail, and not
compiling is failing.
3. You may not write more production code than is sufficient to pass the
current failing test.
4. When all tests pass refactor the code. Do it with small changes and
check that all the tests are still passing after each change. 7
8. Practices To Remember
• There is no object-oriented problem that cannot be
solved by adding a layer of indirection, except, of
course, too many layers of indirection.
• Don’t treat your unit test code as second class
citizen
• Refactor by removing duplicates (DRY principle)
8