My post from yesterday talked about the biggest class I have come across in my lifetime. Turns out, thanks to C#'s partial keyword, the class is even bigger. I have some code metrics from Visual Studio to share. Here they are:
Maintainability Index
Cyclomatic Complexity
Depth of Inheritance
Class Coupling
Lines of Source code
49
9529
2
3617
61900
Code metrics covering the class in aggregate.
Here are the metrics for the 3 longest methods in the class:
Maintainability Index
Cyclomatic Complexity
Depth of Inheritance
Class Coupling
Lines of Source code
0
152
77
786
0
215
62
1181
0
284
27
1238
Code metrics covering the 3 longest methods in the class.
The class itself has 1,314 methods! That is insane!
Yep, I think you are gonna have a hard time unit testing this monster.
Have you come across a bigger monstrosity? If so, leave a comment!
I was working with a new codebase today and I was working on wrapping some unit tests around a section of code in a class. While working, I realized I had come across the BIGGEST class I have ever seen in my life. So big in fact that Visual Studio's IntelliSense was lagging.
The purpose behind unit testing is to help ensure the code you have written performs as expected. The running of unit tests can be more effective when it is automated on a developers machine and as part of your CI/CD pipeline. Automated unit tests can also take the load off of limited QA resources by letting them focus on higher level testing (i.e. integration testing, regression testing, and acceptance testing).
Nowadays, when I'm handed a new code base to work on, I treat it as suspect. I have no idea if the code base will even run. If it does run, how do I know that it runs correctly? Unit tests will help me determine what shape the code base is in.
In general, I follow the red-green-refactor approach when writing unit tests. I write my tests in this order typically:
Cover the happy paths through the code you are testing.
Cover the upper and lower ends of inputs to your code.
Cover any know edge cases known at the time.
As a follow on to this process, if and when bugs are reported against code that I'm maintaining, I can then write a unit test to reproduce the bug and it will also tell me when it is fixed satisfactorily.
What unit testing framework do you like the best and why?
xUnit.net hands down. xUnit.net requires fewer attributes to set your tests up (i.e. Fact and Theory). Another feature I think is neat is using a class's constructor (w/o any attributes) as a setup method for your unit tests. This is great because it follows the way classes work naturally.
What other unit testing frameworks have you used?
I have used NUnit and Visual Studio Unit Testing Framework (aka MSTest). I prefer NUnit to MSTest though.
What is the right amount of code coverage?
If I have to give a number, I would say between 70% and 80%. I would have a higher number for code that is heavily used and relied upon by other parts of the solution.
How would you go about writing unit tests?
I like using TDD on more complicated/intricate code because it let's you work your way through the code step by step. I prefer a Given-When-Then (GWT) approach over Arrange-Act-Assert (AAA). The GWT approach allows you to write more human-readable unit tests. The AAA approach works, but is not as easily readable. In general, writing clear and understandable code is the goal. Here are a couple links that talk about GWT vs AAA:
What other tools can be used to improve unit tests?
NCrunch - This tool is an automated concurrent testing tool for Visual Studio. It automatically runs your unit tests while you are working to reduce the amount of time it takes for the feedback loop.
JetBrains dotCover - This tool is similar to NCrunch but seems to run slower. However, it does tie in to ReSharper, dotPeek, dotTrace, and dotMemory which is handy when trying to look at performance issues.
Testing the wrong thing - Software development teams need to make sure they are writing unit tests to cover code that they have written.
Getting lost in setup hell - This occurs when the setup for your unit tests starts to become tedious and takes a lot of time to get right. Using a GWT style seems to help with this.
"I'll just comment out this unit test to get things working so I can check in my changes." - I think this is just developers being lazy and apathetic about the changes being made to the solution. It is not a behavior I would encourage on my software development team.
So that's my current philosophy on unit testing. What do you think? Am I wrong? Did I miss something? Feel free to post a comment or send me an email.