I'm writing a specification for a lottery function that should create an array of seven (random) numbers between 1 and 49. The numbers in the array must be unique, a result like [1, 2, 3, 4, 5, 6, 6]
would be invalid.
How can I make sure that the test is not green by chance?
One of my tests checks if the numbers in the array are unique. Now it seems like I have a "flaky" spec, because it can be red or green (randomly).
I "solved" the problem by just running the test case multiple times but I'm wondering if there is a more elegant solution. I want a secure way to check whether lottery()
is reliably avoiding duplicates.
The test case (with test repetition):
it('TC05 - lottery() each array item must be a unique number', () => {
// function to check if an array has duplicates
const hasDuplicates = arr => {
return (new Set(arr)).size !== arr.length;
}
// run check for duplicates x times
const REPETITIONS = 32
let seriesOfTests = []
for (let i = 0; i < REPETITIONS; i++) {
if (hasDuplicates(lottery())) {
seriesOfTests.push(true)
} else {
seriesOfTests.push(false)
}
}
// check series to ensure each single test passed
let seriesSummery = seriesOfTests.includes(true)
// test case
expect(seriesSummery).must.be.false()
})
The lottery function (with if statement to avoid duplicates):
// lottery returns an array consists of 7 random numbers between 1 and 49
const lottery = () => {
let result = []
for (let i = 0; i < 7; i++) {
const newNbr = randomNbr(49)
if (result.find(el => el === newNbr) === undefined) {
result.push(newNbr)
} else {
i -= 1
}
}
return result
}