Why it's Time to Stop Using Meaningless Test Values by@prplcode

Why it's Time to Stop Using Meaningless Test Values

image
Simon Egersand 🎈 HackerNoon profile picture

Simon Egersand 🎈

Programming Enthusiast • Sr. Software Engineer @Spotify • Find My Content At https://prplcode.dev

Did you ever find a test where the mock data was a bunch of meaningless "test" strings and 123 integer values? Yeah, me too — and it sucks.

Meaningless Test Values 😿

Consider this JavaScript test.

test('should return children of parent', () => {

  // mock some data
  const mockedParent = {
    name: "test",
    age: 123,
    interests: [
      "test",
      "test",
    ],
  };
  const mockedChildren = [
    {
      name: "test",
      parentName: "test",
    },
    {
      name: "test",
      parentName: "test",
    },
  ];

  // run the code
  const actual = getChildrenForParent(mockedParent, mockedChildren);
  const expected = [
    {
      name: "test",
    },
    {
      name: "test",
    },
  ];

  // assert the results
  expect(actual).toBe(expected);
});

This is a standard unit test that consists of

  • Setup
  • Execution
  • Assertion

It looks fine, why are you saying it sucks?

If I found this test in a codebase I would not understand what data is relevant for the test to pass. If I change the name of the parent from "test" to "some-name" , would the test still pass? I don’t know. The name of the test might help, but as with other documentation, it will eventually change and be out of sync with the code.

Meaningful Test Values 😻

What if we use meaningful test data, how would our test look then?

test('should return children of parent', () => {

  // mock some data
  const irrelevantAge = 123;
  const mockedParent = {
    name: "specific-parent-name",
    age: irrelevantAge,
    interests: [
      "irrelevant",
      "irrelevant",
    ],
  };
  const mockedChildren = [
    {
      name: "child-name-1",
      parentName: "specific-parent-name",
    },
    {
      name: "child-name-2",
      parentName: "specific-parent-name",
    },
  ];

  // run the code
  const actual = getChildrenForParent(mockedParent, mockedChildren);
  const expected = [
    {
      name: "child-name-1",
    },
    {
      name: "child-name-2",
    },
  ];

  // assert the results
  expect(actual).toBe(expected);
});

By reading this test, I can see that "specific-parent-name" is found both in the parent and in the children and has the prefix specific, which tells me that this value is important for the test to pass. Irrelevant values on the other hand have the value "irrelevant", which tells me I can safely ignore these in this test.

For numbers and booleans, you can extract the value to a constant and give the constant a meaningful name.

⚠️ Disclaimer ️

Using strings as IDs is bad practice — use integers instead! I used strings to have a clear example.

Conclusion

  • Using "test" and other meaningless values in your tests is bad practice because it does not convey any meaning. This makes the test take a longer time to understand and will slow down your development time, e.g. when you need to refactor or extend your code

  • Instead, use meaningful values. E.g. "specific-something" and "irrelevant"

  • Extract number and boolean values to constants with a meaningful name

Do you agree or disagree? Let’s discuss this in the comments section 😊


Also published here


Did you ever find a test where the mock data was a bunch of meaningless "test" strings and 123 integer values? Yeah, me too — and it sucks.

Meaningless Test Values 😿

Consider this JavaScript test.

test('should return children of parent', () => {

  // mock some data
  const mockedParent = {
    name: "test",
    age: 123,
    interests: [
      "test",
      "test",
    ],
  };
  const mockedChildren = [
    {
      name: "test",
      parentName: "test",
    },
    {
      name: "test",
      parentName: "test",
    },
  ];

  // run the code
  const actual = getChildrenForParent(mockedParent, mockedChildren);
  const expected = [
    {
      name: "test",
    },
    {
      name: "test",
    },
  ];

  // assert the results
  expect(actual).toBe(expected);
});

This is a standard unit test that consists of

  • Setup
  • Execution
  • Assertion

It looks fine, why are you saying it sucks?

If I found this test in a codebase I would not understand what data is relevant for the test to pass. If I change the name of the parent from "test" to "some-name" , would the test still pass? I don’t know. The name of the test might help, but as with other documentation, it will eventually change and be out of sync with the code.

Meaningful Test Values 😻

What if we use meaningful test data, how would our test look then?

test('should return children of parent', () => {

  // mock some data
  const irrelevantAge = 123;
  const mockedParent = {
    name: "specific-parent-name",
    age: irrelevantAge,
    interests: [
      "irrelevant",
      "irrelevant",
    ],
  };
  const mockedChildren = [
    {
      name: "child-name-1",
      parentName: "specific-parent-name",
    },
    {
      name: "child-name-2",
      parentName: "specific-parent-name",
    },
  ];

  // run the code
  const actual = getChildrenForParent(mockedParent, mockedChildren);
  const expected = [
    {
      name: "child-name-1",
    },
    {
      name: "child-name-2",
    },
  ];

  // assert the results
  expect(actual).toBe(expected);
});

By reading this test, I can see that "specific-parent-name" is found both in the parent and in the children and has the prefix specific, which tells me that this value is important for the test to pass. Irrelevant values on the other hand have the value "irrelevant", which tells me I can safely ignore these in this test.

For numbers and booleans, you can extract the value to a constant and give the constant a meaningful name.

⚠️ Disclaimer ️

Using strings as IDs is bad practice — use integers instead! I used strings to have a clear example.

Conclusion

  • Using "test" and other meaningless values in your tests is bad practice because it does not convey any meaning. This makes the test take a longer time to understand and will slow down your development time, e.g. when you need to refactor or extend your code

  • Instead, use meaningful values. E.g. "specific-something" and "irrelevant"

  • Extract number and boolean values to constants with a meaningful name

Do you agree or disagree? Let’s discuss this in the comments section 😊


Also published here

Simon Egersand 🎈 HackerNoon profile picture
by Simon Egersand 🎈 @prplcode.Programming Enthusiast • Sr. Software Engineer @Spotify • Find My Content At https://prplcode.dev
Support Me on Coil

Comments

Signup or Login to Join the Discussion

Tags

Related Stories