One of the first things you learn as a software engineer is to avoid code duplication whenever possible. But this same learned aversion to duplication is what causes many software engineers to fill their unit tests with logic and abstractions that cause the tests to become unreliable.
On a scale from duplication to abstraction, your code and its corresponding unit tests should almost never be on the same level. Unit tests are not the place for clever logic, abstractions, and code reuse. Logic and abstractions eventually cause your unit tests to become fragile and difficult to understand. If you’re starting to feel like your unit tests need unit tests, then you’re probably doing it wrong.
In your production code, it often makes sense to treat duplication like an enemy to be vanquished everywhere it rears its ugly head. But you’re much better off treating duplication like a friend in your unit tests. In other words, while you favor abstraction over duplication in your code, you should simultaneously favor duplication over abstraction in your unit tests.