Ok! But what is a unit test?
A unit test is an automated piece of code that invokes the method being
tested and then checks some assumptions about the logical behavior of
It can be written easily and runs quickly.
It’s fully automated, trustworthy, readable, isolated, and maintainable.
What are they good for?
Unit tests prove that your code actually works (at a function/method level).
You get some kind of “low-level regression-test” suite.
You can improve the design without breaking it.
They demonstrate concrete progress.
Unit tests are a form of sample code.
It forces you to plan before you code.
It reduces the cost of bugs.
It's even better than code inspections.
What are they not for?
It's not for testing correct inter-operation of multiple subsystems.
It should be a stand-alone test which is not related to other
Test against external resources (data base, LDAP, third party libraries, etc).
Introducing dependencies on external resources or data turns unit tests
into integration tests.
In many cases you can't write a unit test to reproduce bug appeared in
It's not regression testing.
Big time investment.
For the simple case you lose about 20% of the actual implementation, but for
complicated cases you lose much more.
Sometimes the high-level design is not clear at the start and evolves as you go
along - this will force you to completely redo your test which will generate a big
Make sure your tests test one thing and one thing only.
Each unit test should be independent from the other.
Keep consistent conventions (e.g. AAA). Readability is important for tests.
Name your unit tests clearly and consistently.
Separate you concerns. Extract layers to improve the design.
Avoid unnecessary preconditions.
Fake behavior with mocks or stubs to concentrate on test scenario.
Check code coverage during testing.
Don’t unit-test configuration settings.
Tests should run automatically to provide continuous feedback. Keep the bar green to
keep the code clean!
State testing asserts properties on an object.
Interaction testing is testing how an object sends input to or receives input from other
objects — how that object interacts with other objects.
Stub is a controllable replacement for an existing dependency in the system. By using a
stub, you can test your code without dealing with the dependency directly.
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.
Naming by Unit Of Work
Arrange-Act-Assert (AAA) Pattern
Arrange: setup everything needed for the running the tested code. This includes any
initialization of dependencies, mocks and data needed for the test to run.
Act: Invoke the code under test.
Assert: Specify the pass criteria for the test, which fails it if not met.
Bad Practices and anti-patterns
Static methods. Static methods are death to unit testability because they cannot
be mocked or stubbed.
Relying on external resources.
Unit test for GUI.
Constrained test order.
Hidden test call.
Test fixture (Harness)
Test fixture refers to the fixed state used as a baseline for running tests. The
purpose of a test fixture is to ensure that there is a well known and fixed
environment in which tests are run so that results are repeatable.
When do you write the test?
Focus on code.
Thinking about algorithm.
When do you write the test?
Before coding (TDD, BDD)
Focus on requirements.
Thinking about how code will be
Stop coding when reqs met.
Test driven development (TDD)
“TDD is a design process, not a testing process.”
Acceptance vs Unit testing
ATs and UTs are the same though, right?
Both can be written before implementation.
Both should be automated by containing assertions for validating expected
Both typically use fixture setup and teardown code to run before and after the
execution of the tests.
Both can be implemented using a framework.
Careful - They are NOT the same!
Acceptance test is owned and defined by the customer to verify that a
story is complete and correct.
ATs must be defined in a language familiar to the customer:
Generic enough to capture requirements
Abstract enough to be maintainable
Simple enough to be easily understood
ATs should be defined and run using a tool accessible to the customer.
ATs encourage the customer to consider the all aspects of user
ATs test interaction of all layers in the system.
ATs require external systems to be operating correctly.
Acceptance and Unit testing relation
Acceptance Test Client