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);
})
})