Hacker News new | ask | show | jobs
by rectang 1536 days ago
> in many cases causing colleagues to skip certain obvious refactors because the thought of updating 300 unit tests is out of the question.

Good! They shouldn't do the refactor.

Because "obvious" refactors often introduce bugs (e.g. copy/paste errors), and if developers can't be bothered to write tests to catch them, they're going to screw over the other team members and users who will be forced to deal with their bugs in production.

> The holy grail is probably writing all your business logic inside pure functions, and then unit testing those, while integration testing the outer layers for happy and error paths.

So settle for half a loaf.

Write all the easy unit tests first. The coverage will be very incomplete, but something is better than nothing.

Write all the easy integration tests next.

Never write the hard tests if you can help it.

2 comments

> Good! They shouldn't do the refactor.

> Because "obvious" refactors often introduce bugs (e.g. copy/paste errors), and if developers can't be bothered to write tests to catch them, they're going to screw over the other team members and users who will be forced to deal with their bugs in production.

In my opinion, useful tests should be able to survive a refactor. That is the only sane way I've ever done refactoring.

If I'm doing a large refactor on a project and there are no tests, or if the tests will not pass after the refactor, the first thing I do is write tests at a level that will pass both before and after refactoring.

Rewriting tests during refactoring doesn't protect from regression on my experience.

Unit tests which can survive a refactor are a nice-to-have.

I would not rule out a refactor merely because I'd have to refactor some unit tests too. That's just part of the cost benefit analysis.

> Rewriting tests during refactoring doesn't protect from regression on my experience.

Your experience is completely at odds with mine. Every time I change code, there is the possibility for simple errors such as copy/paste mistakes. Trivial, cheap-to-write unit tests have saved me time and again from having to debug something down the line.

Overconfident devs who act as though they're above making such simple mistakes make for bad team members.

I couldn't disagree more.

Tests that will survive a refactor are the most important tests to have.

The other tests are, at best, a false sense of security and often an active detriment that slows down future development. They might sometimes catch actual mistakes, but just as often they fail when nothing is broken, leading to the tests not being trusted and broken tests being updated even when something was actually broken.

> I couldn't disagree more.

*sigh*

I know where you're coming from. This is the classic argument for limiting unit tests to black-box testing of public APIs exclusively, avoiding clear-box testing altogether.

I agree that it's possible to write absolutely wretched fragile clear-box tests. And I agree that if you have a black-box test and a clear-box test which provide equal validation of functionality, the black-box test is superior because it will survive a refactor.

I generally dislike absolutist rules of any kind when it comes to unit testing and prefer to think of things in terms of ROI. Sometimes you can add a lot of value with a clear-box test because the functionality is impossible to write a black-box test for without a ton of extra work and time.

But sometimes you may be in an environment where absolutist rules are the only way to go.

Yeah a refactor that changes how you expect the interfaces to work sounds like much more than a refactor.
>Good! They shouldn't do the refactor. Because "obvious" refactors often introduce bugs.

& if your tests arent catching those bugs and require extra maintenance to go green again you are doing them wrong.