Skip to main content

Is there such a thing as too much unit testing?

Testing, Unit Tests, TDD (Test Driven Development) are one of the first thing that we learn when we are in university and study computer science. A part of us might be lucky enough to have a specific course for TDD.

Code is written by people for machines that needs to resolve problems. People do mistakes and this is why it is so important to test our code. I didn’t have the opportunity to see until now a working application, without bug or issues from the beginning.

I would say that a complex application that is not covered by unit tests and without a testing process will end up in the trash. At the beginning of each project there is a classical discussion related to unit tests and code coverage.

- Do we need unit tests? 
- Yes.

- What is the code coverage target?
- 80%, 60%, 20%, 100%....

It is pretty clear that we need unit test. An engineer needs to be able to test his code and check if what we develop is working as expect or not. The response for the first question is pretty clear. But when we jump to the next question – the discussions can take hours and hours.
The development team will try to push the value as high as possible. In contrast, management might push back. Constraints like time, budget, complexity or quality level might impact the decision.
In situations like this, both parts might have good arguments to sustain their point of view. We are in a gray zone, where people can easily fall in a defense mode. I was very often in situations like this and unfortunately, managers will win. They are the one that takes the final decision.

What we shall do in this situations?

The first thing that we need to do is to map all the risks that might appear if there are no tests or if the code coverage is too low. Once we done this, we need to stay with all the team and identify how this cases could be mitigated.
Mitigation for this kind of problem could be strange, but acceptable at project level. Solution like increase the number of testers, bugs will be solved in production or accept quality level to go down are strange solutions for technical people, but this can be acceptable at project level.
The most important thing is to create the risk map. In this way people that can take a decision can have the whole picture in front of them.

The second thing that we need to do is to try to identify what are the components where complexity is high and the risk to have issues are imminent. Once we identify them we can requests that at least these components to be covered by tests.
In this way we can ensure that the most complex part of the system will be testeed and the development team can write good and working code from the beginning.

The 3rd things that can be done is to try to focus to write tests that covers custom logic (business logic). It is more likely to have an issues on custom code that calculates the discount level than in the one that save the results in a database or make a remote request. Of course also at persistence level we might have a bug, but because this layer is used by many other components also, the risk of having issues there without detecting it at development level is much lower.
When the available time for writing tests is not as much as we want we shall focus to cover the most important stuff with tests. Cover the part of the systems where you know that you will have issue.

Conclusion
In the end, there is trade-off. Getting enough time to have 100% coverage is not often. Even with 100% code coverage, you will still have bugs in production.
Don’t forget that we write code that runs on machines, but needs to be read by people.

Is there such a thing as too much unit testing?
No, but taking into account time, scope and quality, the quantity of unit tests can be impacted, even if there is a direct impact on this triangle (time, scope, quality).

Comments

  1. I think the questions are misleading. What is to have unit testing? Is it an obligation to have the code testable? Is it to have x% coverage (like half of project fully tested and the other not)? Is it related in any way to the possibility of future refactoring? How are the tests checked? Automatically when submitting or occasionally when someone decides they need to check?

    The first thing I realized about unit testing is that it forces you to write things a certain way. Having coverage may be nice, but also not representative. What I would push for is testable code, not tested code. And how do you "test" this? Just define a minimum requirement for one unit test and make every class that has any public methods or code properties have mandatory at least one.

    I've read once that intelligence seems to emerge naturally from attempts to keep as many options open. Without testable code you cannot have unit tests, with it, the choice remains yours.

    ReplyDelete

Post a Comment

Popular posts from this blog

Windows Docker Containers can make WIN32 API calls, use COM and ASP.NET WebForms

After the last post , I received two interesting questions related to Docker and Windows. People were interested if we do Win32 API calls from a Docker container and if there is support for COM. WIN32 Support To test calls to WIN32 API, let’s try to populate SYSTEM_INFO class. [StructLayout(LayoutKind.Sequential)] public struct SYSTEM_INFO { public uint dwOemId; public uint dwPageSize; public uint lpMinimumApplicationAddress; public uint lpMaximumApplicationAddress; public uint dwActiveProcessorMask; public uint dwNumberOfProcessors; public uint dwProcessorType; public uint dwAllocationGranularity; public uint dwProcessorLevel; public uint dwProcessorRevision; } ... [DllImport("kernel32")] static extern void GetSystemInfo(ref SYSTEM_INFO pSI); ... SYSTEM_INFO pSI = new SYSTEM_INFO(

Azure AD and AWS Cognito side-by-side

In the last few weeks, I was involved in multiple opportunities on Microsoft Azure and Amazon, where we had to analyse AWS Cognito, Azure AD and other solutions that are available on the market. I decided to consolidate in one post all features and differences that I identified for both of them that we should need to take into account. Take into account that Azure AD is an identity and access management services well integrated with Microsoft stack. In comparison, AWS Cognito is just a user sign-up, sign-in and access control and nothing more. The focus is not on the main features, is more on small things that can make a difference when you want to decide where we want to store and manage our users.  This information might be useful in the future when we need to decide where we want to keep and manage our users.  Feature Azure AD (B2C, B2C) AWS Cognito Access token lifetime Default 1h – the value is configurable 1h – cannot be modified

What to do when you hit the throughput limits of Azure Storage (Blobs)

In this post we will talk about how we can detect when we hit a throughput limit of Azure Storage and what we can do in that moment. Context If we take a look on Scalability Targets of Azure Storage ( https://azure.microsoft.com/en-us/documentation/articles/storage-scalability-targets/ ) we will observe that the limits are prety high. But, based on our business logic we can end up at this limits. If you create a system that is hitted by a high number of device, you can hit easily the total number of requests rate that can be done on a Storage Account. This limits on Azure is 20.000 IOPS (entities or messages per second) where (and this is very important) the size of the request is 1KB. Normally, if you make a load tests where 20.000 clients will hit different blobs storages from the same Azure Storage Account, this limits can be reached. How we can detect this problem? From client, we can detect that this limits was reached based on the HTTP error code that is returned by HTTP