This is a bit of a philosophical question.
Let’s say I’m implementing a new feature for the account page of my app. Similar to LinkedIn, I want to show what percentage of a user’s account has been filled out to let the user know if there is still stuff to do. There are a couple dozen things that could be filled out that contribute to getting to 100%.
From a TDD best-practices perspective, do you feel it would be best to create a single integration test that test for the presence of the percent complete message, then tease out all the various percentages in unit tests, or do you feel that multiple integration tests is the way to go. Is there another option that I might be missing?
Eager to hear everyone’s thoughts.
You’re right that this is a bit philosophical. I don’t think there’s a “right” answer here so much, but let me lay out a couple things for you to consider:
- Integration tests tend to be thorough but slow. Optimize for what you care about more.
- Integration tests give more confidence that your app works, but are brittle (susceptible to breakage when changing any one of many pieces). Optimize for what you care about more.
- Unit tests can help you isolate issues quickly but cannot prove the app works. Optimize for what you care about more.
- Unit tests with mocks are extremely fast but might hide breakage like an out-of-date method name on a dependency. Optimize for what you care about more.
- Just about every decision you make in software development comes with pros and cons. What to do? Optimize for what you care about more.
As for me, I try to write just a few integration tests to verify the big pieces are plugged together correctly. I drive out the majority of the details with unit tests. Fast ones.
Works pretty well, but others make different choices, and neither side is necessarily wrong.
I think it’s a balancing act where you’ll know how far to go in scenarios like this.
Like Ben said though, the lower you can get towards unit (more isolation) testing has worked best for me, with the (generally) happy path(s) covered in an integration test. I built something similar to what you detail above and I made a service object that I could test the various permutations against. It worked out just fine.
One final note, your exception notifier (airbrake, exceptional, errbit, etc) will help you tease out the areas that might be troublesome and need further test coverage on the integration level. You might end up having more than one happy path you didn’t anticipate.
Thanks for the input.
@benorenstein: Agreed, most of what we do is a balancing act.
@joel: Your implementation sounds a lot like what I’m thinking about - some intermediate object dedicated to expressing the feature.