Here is a quick email I threw together for a friend who has started writing automated tests and asked if there is a reason to have lots of different kinds of tests covering the same area. Yes, it's simplistic and I'm sure a bunch of ThoughtWorkers would kick me and say it is better explained in other ways but I think this is a good summary. In case it helps others, here it is...
OK, this is the way I structure testing of an application. This works when the tests are written retrospectively or if the application is written in a test driven manner.
There are three types of tests:
- Functional tests - UI testing that uses the terms of the users/business. You'll see tools like Selenium with junit/nunit/rspec used at this level. Functional areas of the application are tested in a similar workflow to what I user would use. Happy path comes in here for primary workflows. Deliberate error (validation and business logic) and exception testing at the highest level occur now;
- Integration tests - these tests are used when you are plugging all the bits of your system together. Bits can mean layers, components within a layer, or dependencies outside of your system (third party web services, etc...). The point of this is a test interfaces and APIs that are public to the component or application parts. You test input and output in a black box way. Again, with all good data and then causing errors and exceptions;
- Unit tests - These tests are the very specific low level tests that check that a unit of functionality is working. This can be at a class level, library or component. You'll see mocking frameworks used here to imitate data sources or connecting systems. At this point, you do not want to be distracted by the possibility of functionality external to this unit causing issues so it doesn't talk to anything and gets all input or directs all output to mocked objects.
This is a starting point and written at a high-level. Ask me if you need it clarified further.