Everyone’s favorite test type – it is fast, small, sleek, the perfect companion. Ideally these tests will test pieces of logic in isolation – both from the rest of the software being developed and from the external services the software depends on.
These days, most everyone is on the “write tests” bandwagon, so most languages will have some form of testing framework built in. If the built in framework is not your cup of tea, there are usually many others out there to choose from!
As you can see in our test pyramid above, unit tests occupy the base of the pyramid. The rule of thumb with these tests is “If it fits, it is a unit test!” If you can test something in the unit layer without creating complicated tests to deal with dependencies, this is where this test goes!
For those things you want to test which will require complicated setup or has a heavy reliance on dependencies, there are many other test types which fit your needs better. (See Integration Tests for an introduction to tests which excel at handling other dependencies). The biggest reason to keep these things in a separate test type is to keep your unit tests fast and reliable enough they are not painful to run. These are the tests which you want to run before you check-in and act as your base “nothing is initially broken” tests.
There are many great resources out there for unit tests and many people have taken the concept of unit tests and created many innovative tools (eg, koans) with them!
Something to note with unit tests is the debate between isolated tests (where the test touches nothing beyond the class under test and even things from the same code base are mocked) vs social tests (just worry about mocking external affairs). I personally fall on the social side – if a class uses a class under it to implement its purpose, I feel like that interaction should not be mocked as it can create a brittle and not accurate test. Mocks should be used to increase the stability (eg, external dependencies) and speed of a test. If a method under tests has an undue reliance on other objects which slows it down, think about potential refactors or redesign before you reach for mocking.
- Isolation means you can’t test everything
- Test your business logic
- Create tests which require external services or the software running to pass
If there exists a method:
Int add(int a, int b)
Assert add(2, 2) == 4
Assert add(-1, -3) == -4
Assert add(0, 0) == 0
Assert add(10000000000000, 30000000000000) == 40000000000000
Assert add(1e14, 3e14) throws Exception(“Too Damn Big”)