Deep down we all love utopian ideologies and visions, they sound great, but they don't often work. Getting 100% code coverage of your tests is one these same situations.
Don't get me wrong, testing as much as your functional code is important but striving towards 100% code coverage is driven by the utopian vision of perfection in our minds and not by any practical and rational reasoning.
Striving towards 100% code coverage is a false economy. It's not a precise measure of how secure and robust your code and business logic is; it's only a measure of if any given line in your code has a test or not. I.e. each line of code ends up with a binary outcome. Yes it has a test or no it does not.
In real life though, a small portion of your code, let's hypothesise and say 15%, might be used for several user journeys. Within these user journeys there could be many scenarios that need testing. Taking 100% code coverage as the holy grail measure misses the point that actually there needs to far more tests for the various scenarios on this 15% than on the other 85%.
The best solution is to plan out in advance, before writing any code, the user stories (scenarios) that will take place in the product. Not just the high level desires of a type of user who will use your product, those are important, but the expectation of what should and should not happen when a user takes an action. Sometimes these involves writing out, for example, 5 scenarios for one action in a user journey.
This may sound cumbersome, however it is the only way to truly achieve 100% "coverage", not of your code, but of your user stories. Let's look at some examples:
As a Buyer, when I return back to the checkout after previously having paid for an order, I want my card details to be there so I can make another purchase without having to enter them again
As a Buyer, when I return back to the checkout after previously having paid for an order, If my card has expired I want to clearly see an error in the payment details area so I can add my new card details
As a Supplier, when an order is paid for by a Buyer, I want to receive an email with the order details containing the product information and customer address so I can quickly package and ship the product
Writing out scenarios for developers to follow provides them with a clear framework to follow with minimum ambiguity. It allows developers to write out tests according to the structure of the codebase that they have built regardless of the technology they have chosen. This methodology is well known, it's called "Test-Driven Development".
The ideology is that you write a test first, which will fail, and then the functional code after to satisfy the test; somewhat utopian. The reality is, regardless of when the test is written - ideally before or just after the functional code has been written, the test ensures the real-life use case is covered and the code is resilient.
The irony is, if 100% user story coverage is achieved, 100% code coverage will certainly not be - but the code will be more resilient and secure. If you were to run a test coverage report, using the various tools such as SonarQube, you'd see far less than 100% code coverage and you'd simply be uncovering which code has the most tests against it.
This completely pivots the reason why we should run code coverage scans and the value we get out of running the scans; not necessarily to try and push that number close to 100% but to observe which are the most important parts of our code.
Aduro can work with you to discover these kind of requirements. We produce detailed technical specifications including user stories, the best technology for the job, database schema, api architecture and much more.