Home > Net >  How to test a random color generator with jest
How to test a random color generator with jest

Time:05-27

I have here a function that returns a random Hex color

function randomHex() {
  return `#${Math.floor(Math.random() * 0xffffff).toString(16).padEnd(6, "0")}`;
}

how can i test it with jest? i want to know if it really returns a random hex or not

CodePudding user response:

To quote myself, from this post:

So we can think about how to test it, here's a basic implementation of a coin flip:

const flipCoin = () => Math.random() < 0.5 ? "heads" : "tails";

We can be pretty confident that if we call this function a large number of times we'll get roughly half of each outcome:

> Array(10).fill(null).map(() => flipCoin());
[ "tails", "heads", "heads", "tails", "tails", "tails", "heads", "heads", "tails", "tails" ]

but for a given call we can't be sure which it will be. So how can we write a test for that? We could reach for the facade pattern again, extract const random = () => Math.random() and replace that with a test double. This would work fine, but be very tightly coupled to the implementation:

describe("flipCoin", () => {
  it("returns 'heads' when the random number is less than 0.5", () => {
    random.mockReturnValue = 0.3;

    expect(flipCoin()).toEqual("heads");
  });
});

One alternative is to write tests based on the properties of the implementation we want. For example, although we don't know the specific values, we do know:

  • It should always give one of the expected outcomes; and
  • It shouldn't always give the same outcome (otherwise () => "heads" would be a valid implementation).

In this case, a property-based test might look like:

describe("randomHex", () => {
  it("always returns a colour", () => {
    const colours = Array(100).fill(null).map(() => randomHex());

    colours.every((colour) => expect(colour).toMatch(/^#[\da-f]{6}$/));
  });

  it("doesn't always return the same colour", () => {
    const colours = Array(100).fill(null).map(() => randomHex());
   
    expect(new Set(colours).size).toBeGreaterThan(1);
    // or a higher number, but e.g. `.toEqual(colours.length)` can fail due to collisions
  });
});

CodePudding user response:

Maybe something like

const { randomHex } = require('../../../');

describe('', () => {
  it('', () => {
    const firstRandomColor = randomHex();
    const secondRandomColor = randomHex();
    const hexRegex = /^#(?:[0-9a-fA-F]{3}){1,2}$/;

    expect(firstRandomColor).toMatch(hexRegex);
    expect(secondRandomColor).toMatch(hexRegex);
    expect(firstRandomColor).not.toBe(secondRandomColor);
  })
})
  • Related