Hacker News new | ask | show | jobs
by Jtsummers 1604 days ago
That stretches the idea of a refactor, though. If a refactor changes the external behavior it's not really a refactor, which is a structural change. Unit tests when applied at an API level (which may be a very small unit or up to the level of a library, but that also stretches the definition of "unit test" depending on the size of the library) are there to ensure that changes to the internals don't impact the behavior.

As soon as you start changing the behavior, you have to change the unit tests. If you're adding behavior, you have to add tests. If you're removing behavior, you remove tests. If you're changing the way a procedure works, you change the related unit tests.

Really, any behavior change requires changes to the tests (whatever level they may be, if you want a high degree of test coverage).

2 comments

And without relatively comprehensive tests, you can't ever tell if a 'refactor' (in the structural sense of the word) actually worked. Did you change internal implementation code without affecting the consumer output? Without tests, you can't reliably tell with a high degree of confidence.
Units by definition are not external behavior. sometimes they change external behavior, but there are a lot of changes that make code cleaner without changing external behavior. All too often I've discovered after a few years that I really need to split some unit into two.
To clarify, the unit's own behavior is indeed not external to itself. But the way it behaves from the perspective of a user of the unit is external behavior. Changing the behavior, from that perspective, of a unit will necessarily invalidate its tests (some at least) and is not a refactor. That was my point, if you are changing an API you are not refactoring, you are changing its external behavior.

But this isn't just a problem with unit tests, it's a problem with all tests. And really, it's not a problem. It's the cost of doing business. Anything in flux (where that change changes its behavior) will force you to change anything that depends on it, whether it's a test or a user/client. If you aren't willing to discard the tests then the tests "freeze" the system in place, regardless of their level or kind (unit, integration, end to end).