I have a situation where I have different forms, each with 4 or 5 steps (components), and I decided to write one unit test per step.

After doing it, I noticed they were very similar and I could just loop through them, changing some values based on the loop index. All good and worked fine, until one of the forms failed and I couldn't figure out which step was failing . I could provide another generic solution for it, but this failure made me wonder if it really makes sense to reuse code for tests like this.

Well... as developers, we always want to reduce code duplicates, but I think for unit/snapshot tests, it's a best practice to have every test explicit. The advantage I see by duplicating code in this situation is that it makes it more clear, easy to debug when a failure happens and also, once it's test code, it doesn't impact production code. What are your thoughts on it? Does it worth to have generic code to test several similar components, or is it better and safer to have it more explicit, even if you have to duplicate the code?

I also read this article on twitter, a few days ago that opened my mind for this approach even more: https://www.sandimetz.com/blog/2016/1/20/the-wrong-abstraction WDYT?


There's no general answer whether duplicating test code is sensible or not – it really depends on the circumstances.

But quite often you will be able to extract a recurring step into a separate function. So instead of this, which involves code duplication:

test("Component A", () => {
  ... // lots of code

test("Component B", () => {
  ...  // lots of duplicate code

or this, which makes it difficult to tell which component failed:

test("All Components", () => {
  for (let component of [ComponentA, ComponentB]) {
    ...  // lots of code

you can extract the test details like this:

test("Component A", () => testComponent(ComponentA));
test("Component B", () => testComponent(ComponentB));

function testComponents(component) {
  ... // lots of code

This gives you the best of both worlds: little code duplication in your tests, but detailed test feedback.

  • this is exactly my situation.. but I have mixed feelings of adding two for loops to iterate over 7 form components that have each of them 5 or 4 steps (also components), and I feel that if I wrap it into one single test, I could easily have to refactor it in the future and extract it once conditions change... so I'm not sure if this will happen, but I'm afraid I'd have to refactor this in the future, when I might not have the requirements as fresh as I have it now... Aug 8 '19 at 13:23
  • 1
    @Periback I'm NOT suggesting the loop solution, but extracting test code into helper functions. In my experience, extracting helper functions does not lead to excessive coupling when you extract based on shared goals, not based on incidental similarity of the extracted code. Because goals are less likely to change than implementation details. This also makes the code more self-documenting.
    – amon
    Aug 8 '19 at 14:06

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.