如何用玩笑测试随机颜色生成器
How to test a random color generator with jest
我这里有一个函数returns一个随机十六进制颜色
function randomHex() {
return `#${Math.floor(Math.random() * 0xffffff).toString(16).padEnd(6, "0")}`;
}
我怎样才能开玩笑地测试它?
我想知道它是否真的 returns 随机十六进制
也许是这样的
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);
})
})
引用我自己,来自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).
在这种情况下,property-based 测试可能如下所示:
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
});
});
我这里有一个函数returns一个随机十六进制颜色
function randomHex() {
return `#${Math.floor(Math.random() * 0xffffff).toString(16).padEnd(6, "0")}`;
}
我怎样才能开玩笑地测试它? 我想知道它是否真的 returns 随机十六进制
也许是这样的
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);
})
})
引用我自己,来自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).
在这种情况下,property-based 测试可能如下所示:
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
});
});