Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test: rewrite mersenne tests #480

Merged
merged 12 commits into from
Feb 14, 2022
2 changes: 1 addition & 1 deletion src/mersenne.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export class Mersenne {
}

/**
* Generates a random number between min and max (inclusive).
* Generates a random number between [min, max)'.
*
* @param max The maximum number. Defaults to `0`.
* @param min The minimum number. Defaults to `32768`. Required if `max` is set.
Expand Down
211 changes: 211 additions & 0 deletions test/mersenne.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,211 @@
import { beforeAll, beforeEach, describe, expect, it } from 'vitest';
import { Mersenne } from '../src/mersenne';

type SeededRun = {
seed: number | number[];
expectations: SeededRunExpectations;
};
type SeededRunExpectations = {
rand: {
noArgs: number;
minMax: { max?: number; min?: number; expected?: number; skip?: boolean }[];
};
};
Shinigami92 marked this conversation as resolved.
Show resolved Hide resolved

const seededRuns: SeededRun[] = [
{
seed: 42,
expectations: {
rand: {
noArgs: 12272,
minMax: [
{ max: 100, min: 0, expected: 37 },
{ max: undefined, min: 0, expected: 12272 },
{ max: 100, min: undefined, expected: 37, skip: true },
],
},
},
},
{
seed: 1337,
expectations: {
rand: {
noArgs: 8586,
minMax: [
{ max: 100, min: 0, expected: 26 },
{ max: undefined, min: 0, expected: 8586 },
{ max: 100, min: undefined, expected: 26, skip: true },
],
},
},
},
{
seed: 1211,
expectations: {
rand: {
noArgs: 30425,
minMax: [
{ max: 100, min: 0, expected: 92 },
{ max: undefined, min: 0, expected: 30425 },
{ max: 100, min: undefined, expected: 92, skip: true },
],
},
},
},
{
seed: [42, 1, 2],
expectations: {
rand: {
noArgs: 28056,
minMax: [
{ max: 100, min: 0, expected: 85 },
{ max: undefined, min: 0, expected: 28056 },
{ max: 100, min: undefined, expected: 85, skip: true },
],
},
},
},
{
seed: [1337, 1, 2],
expectations: {
rand: {
noArgs: 5895,
minMax: [
{ max: 100, min: 0, expected: 17 },
{ max: undefined, min: 0, expected: 5895 },
{ max: 100, min: undefined, expected: 17, skip: true },
],
},
},
},
{
seed: [1211, 1, 2],
expectations: {
rand: {
noArgs: 29217,
minMax: [
{ max: 100, min: 0, expected: 89 },
{ max: undefined, min: 0, expected: 29217 },
{ max: 100, min: undefined, expected: 89, skip: true },
],
},
},
},
];

const functionNames = ['rand'];

const NON_SEEDED_BASED_RUN = 25;

describe('mersenne twister', () => {
let mersenne: Mersenne;

beforeEach(() => {
mersenne = new Mersenne();
});

for (const { seed, expectations } of seededRuns) {
describe(`seed: ${JSON.stringify(seed)}`, () => {
beforeEach(() => {
if (Array.isArray(seed)) {
mersenne.seed_array(seed);
} else {
mersenne.seed(seed);
}
});

for (const functionName of functionNames) {
it(`${functionName}()`, () => {
const actual = mersenne[functionName]();

expect(actual).toEqual(expectations[functionName].noArgs);
});
}

for (const { min, max, expected } of expectations.rand.minMax.filter(
(x) => !x.skip
)) {
it(`should return ${expected} for rand(${max}, ${min})`, () => {
const actual = mersenne.rand(max, min);

expect(actual).toEqual(expected);
});
}

// TODO @piotrekn 2022-02-13: There is a bug: https://github.com/faker-js/faker/issues/479
// remove minMax.skip when fixed
for (const { min, max, expected } of expectations.rand.minMax.filter(
(x) => x.skip
)) {
it.todo(`should return ${expected} for rand(${max}, ${min})`, () => {
const actual = mersenne.rand(max, min);

expect(actual).toEqual(expected);
});
}

it.todo(`should return 0 for rand(1)`, () => {
const actual = mersenne.rand(1);

expect(actual).toEqual(0);
});
});
}

// Create and log-back the seed for debug purposes
const seeds = [
Math.ceil(Math.random() * 1_000_000_000),
[
Math.ceil(Math.random() * 1_000_000_000),
Math.ceil(Math.random() * 1_000_000_000),
],
];

for (const seed of seeds) {
describe(`random seeded tests ${JSON.stringify(seed)}`, () => {
beforeAll(() => {
if (Array.isArray(seed)) {
mersenne.seed_array(seed);
} else {
mersenne.seed(seed);
}
});

for (let i = 1; i <= NON_SEEDED_BASED_RUN; i++) {
Shinigami92 marked this conversation as resolved.
Show resolved Hide resolved
describe('rand', () => {
it('should return a random number without given min / max arguments', () => {
const randomNumber = mersenne.rand();
expect(typeof randomNumber).toBe('number');
});

it('should return random number from interval [min, max)', () => {
const actual = mersenne.rand(0, 2);

expect(actual).toBeGreaterThanOrEqual(0);
expect(actual).toBeLessThan(2);
});
});
}
});
}

it('should throw an error when attempting to seed() a non-integer', () => {
expect(() =>
mersenne.seed(
// @ts-expect-error: non-integer error
'abc'
)
).toThrowError(Error('seed(S) must take numeric argument; is string'));
});

it('should throw an error when attempting to seed() a non-integer', () => {
expect(() =>
mersenne.seed_array(
// @ts-expect-error: non-integer error
'abc'
)
).toThrowError(
Error('seed_array(A) must take array of numbers; is string')
);
});
ST-DDT marked this conversation as resolved.
Show resolved Hide resolved
});
22 changes: 0 additions & 22 deletions test/random.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -252,26 +252,4 @@ describe('random.js', () => {
spy_console_log.mockRestore();
});
});

describe('mersenne twister', () => {
it('returns a random number without given min / max arguments', () => {
const randomNumber = mersenne.rand();
expect(typeof randomNumber).toBe('number');
});

it('throws an error when attempting to seed() a non-integer', () => {
expect(() =>
mersenne.seed(
// @ts-expect-error
'abc'
)
).toThrowError(Error('seed(S) must take numeric argument; is string'));
});

it('throws an error when attempting to seed() a non-integer', () => {
expect(() => mersenne.seed_array('abc')).toThrowError(
Error('seed_array(A) must take array of numbers; is string')
);
});
});
});