I completely recognize, that just trying to write tests for something, makes the code way better.
As much as developers should be urged towards unit testing, your expectation is a bit off. Unit tests do not improve code. They improve maintainability of the code.
if (IsMenuItemOpen(ID))
OpenExistingMenuItem(ID);
else
OpenNewMenuItem(ID);
But now i dont see much point in testing this part anymore. What is there to test? Its a bunch of assignments and a simple condition.
What you're doing now is trying to write tests based on the code you have in front of you. What you should be doing is writing tests based on the purpose of the code.
In this case, the purpose is to decide whether a new item should be opened or an existing item should be reused. The test criteria become quite clear:
- Does the code open a new item under the right conditions?
- Does the code open an existing item under the right conditions?
Notice how I did not need to know what the actual code is to create these test conditions, I simply needed to know the functionality that the code seeks to provide.
And then you write those tests. At the moment, your feeling that the tests are effectively rewriting the same logic again is correct, but that is not an argument for not writing the tests.
This is why I pointed out that unit tests improve maintainability. Trivial as the code may be today, it may become more complex tomorrow, or the day after. But your tests remain the same. And no matter how often this function is refactored, the tests ensure that the end result will always be correctly achieved even after refactoring the code.
Unit tests do not help you write better code. Unit tests make sure you don't break something when making alterations in the future.
Write Code -> write test, if i feel the method is complex enough -> fail to easily write test code -> improve the code -> now methods dont seem complex enough anymore to "test".
What you're doing here is not the main purpose of unit testing. What you're doing here is refactoring your code to make it test-friendly, which has the added side effect of making things more readable and less entangled.
Having clear and concise code is a bonus on top of having testable code. Don't use it as a reason to not test the code you just made testable. It defeats the purpose.
At extremes, it can even be a slippery slope into wondering why you'd even need to make your code testable if you're not going to be writing tests for it anyway.
Developers thinking "I don't need to write tests for something I already understand" is THE obstacle in getting capable developers to actually write unit tests. Many developers unintentionally succumb to the arrogant notion that if they understand it today, that must mean that everyone will always understand it.
And the counterevidence is abundant: Developers who have to look at their own code after months of doing something else will struggle to get into the flow of things again. Developers who review other developers' code will immediately notice that understanding someone else's code is not as obvious as the author of the code often thinks.
Unit tests lower the threshold on having to understand code written by others (or by you in the distant past) by only alerting you when an actual problem emerges. And when a problem emerges, the unit test immediately tells you which specific part has failed, which makes it a lot easier to immerse yourself in a precise part of the application instead of having to look at everything altogether.
As soon as i change something about this method, maybe i want to supply a MenuItem directly instead of finding it via ID, it would break the test anyway.
Back to programming basics, there are three steps to every algorithm: input, processing and output. Input and output are the behavior to an external consumer (I press the gas pedal => the car moves forward). Processing is the implementation detail (the combustion engine of the car).
Unit tests only care about behavior. Their main purpose is to ensure that the behavior is maintained when the implementation is altered.
So, yes, if you change your input or output variables, your unit tests will have to be adapted. That is something you cannot avoid.
But if you're spending more time changing the behavior of your solution than you are changing its implementation, something is very off about your development methodology. Taking a stab in the dark, I'd guess that your tasks haven't been properly analyzed before starting on them, thus requiring you to remodel everything as you go.
What is there to test? Its a bunch of assignments and a simple condition.
I assume the listed methods (OpenNewMenuItem
etc) are private methods.
Unit tests are written from the point of view of the consumer of your class, and they are only interested in the public behavior of your class. Whether your method has submethods (such as OpenNewMenuItem
) or not is irrelevant to the unit test.
So to rephrase your statement, you do not unit test methods, you unit test public behavior (which is generally initiated via public methods).
I would hardly come back to this method and "refactor" it in a way that doesnt change any of the outcomes.
You may not see the point of rewriting it today. But you might in the future. Unit tests are not written so that they help you today, they are written so that they help you in the future.