Skip to content

Commit

Permalink
Do not force explicitly one parameter in constantFrom
Browse files Browse the repository at this point in the history
Related to #122
  • Loading branch information
dubzzz committed Jun 19, 2018
1 parent f013120 commit cb860dc
Show file tree
Hide file tree
Showing 4 changed files with 18 additions and 12 deletions.
2 changes: 1 addition & 1 deletion documentation/Arbitraries.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ Strings that mimic real strings, with words and sentences:
## Combinors of arbitraries (:T)

- `fc.constant<T>(value: T): Arbitrary<T>` constant arbitrary only able to produce `value: T`
- `fc.constantFrom<T>(...values: T[]): Arbitrary<T>` randomly chooses among the values provided. It considers the first value as the default value so that in case of failure it will shrink to it
- `fc.constantFrom<T>(...values: T[]): Arbitrary<T>` randomly chooses among the values provided. It considers the first value as the default value so that in case of failure it will shrink to it. It expects a minimum of one value and throws whether it receives no value as parameters. It can easily be used on arrays with `fc.constantFrom(...myArray)` (or `fc.constantFrom.apply(null, myArray)` for older versions of TypeScript/JavaScript)
- `fc.oneof<T>(...arbs: Arbitrary<T>[]): Arbitrary<T>` randomly chooses an arbitrary at each new generation. Should be provided with at least one arbitrary. All arbitraries are equally probable and shrink is still working for the selected arbitrary. `fc.oneof` is able to shrink inside the failing arbitrary but not accross arbitraries (contrary to `fc.constantFrom` when dealing with constant arbitraries)
- `fc.option<T>(arb: Arbitrary<T>): Arbitrary<T | null>` or `fc.option<T>(arb: Arbitrary<T>, freq: number): Arbitrary<T | null>` arbitrary able to nullify its generated value. When provided a custom `freq` value it changes the frequency of `null` values so that they occur one time over `freq` tries (eg.: `freq=5` means that 20% of generated values will be `null` and 80% would be produced through `arb`). By default: `freq=5`
- `fc.array<T>(arb: Arbitrary<T>): Arbitrary<T[]>`, `fc.array<T>(arb: Arbitrary<T>, maxLength: number): Arbitrary<T[]>` or `fc.array<T>(arb: Arbitrary<T>, minLength: number, maxLength: number): Arbitrary<T[]>` array of random length containing values generated by `arb`. By setting the parameters `minLength` and/or `maxLength`, the user can change the minimal (resp. maximal) size allowed for the generated array. By default: `minLength=0` and `maxLength=10`
Expand Down
15 changes: 10 additions & 5 deletions src/check/arbitrary/ConstantArbitrary.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,17 @@ function constant<T>(value: T): Arbitrary<T> {
}

/**
* For one of `v0` or `...values` values - all equiprobable
* @param v0 One of the value to produce (all values shrink to this one)
* @param values Other possible values
* For one `...values` values - all equiprobable
*
* **WARNING**: It expects at least one value, otherwise it should throw
*
* @param values Constant values to be produced (all values shrink to the first one)
*/
function constantFrom<T>(v0: T, ...values: T[]): Arbitrary<T> {
return new ConstantArbitrary<T>([v0, ...values]);
function constantFrom<T>(...values: T[]): Arbitrary<T> {
if (values.length === 0) {
throw new Error('fc.constantFrom expects at least one parameter');
}
return new ConstantArbitrary<T>([...values]);
}

export { constant, constantFrom };
4 changes: 1 addition & 3 deletions test/e2e/GenerateAllValues.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,7 @@ describe(`Generate all values (seed: ${seed})`, () => {
describe('fc.constantFrom()', () => {
it('Should be able to produce all the constants', () =>
fc.assert(
fc.property(fc.set(fc.string(), 0, 40), csts =>
lookForMissing(fc.constantFrom(csts[0], ...csts.slice(1)), csts.length)
)
fc.property(fc.set(fc.string(), 1, 40), csts => lookForMissing(fc.constantFrom(...csts), csts.length))
));
});
});
9 changes: 6 additions & 3 deletions test/unit/check/arbitrary/ConstantArbitrary.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,19 +22,22 @@ describe('ConstantArbitrary', () => {
});
});
describe('constantFrom', () => {
it('Should throw when no parameters', () => {
assert.throws(() => constantFrom());
});
it('Should always return one of the constants', () =>
fc.assert(
fc.property(fc.array(fc.string(), 1, 10), fc.integer(), (data, seed) => {
const mrng = stubRng.mutable.fastincrease(seed);
const g = constantFrom(data[0], ...data.slice(1)).generate(mrng).value;
const g = constantFrom(...data).generate(mrng).value;
return data.indexOf(g) !== -1;
})
));
it('Should be able to produce all the constants', () =>
fc.assert(
fc.property(fc.array(fc.string(), 1, 10), fc.integer(), fc.nat(), (data, seed, idx) => {
const mrng = stubRng.mutable.fastincrease(seed);
const arb = constantFrom(data[0], ...data.slice(1));
const arb = constantFrom(...data);
for (let id = 0; id != 10000; ++id) {
const g = arb.generate(mrng).value;
if (g === data[idx % data.length]) return true;
Expand All @@ -46,7 +49,7 @@ describe('ConstantArbitrary', () => {
fc.assert(
fc.property(fc.set(fc.string(), 1, 10), fc.integer(), (data, seed) => {
const mrng = stubRng.mutable.fastincrease(seed);
const shrinkable = constantFrom(data[0], ...data.slice(1)).generate(mrng);
const shrinkable = constantFrom(...data).generate(mrng);
if (data.indexOf(shrinkable.value) === 0) assert.deepStrictEqual([...shrinkable.shrink()], []);
else assert.deepStrictEqual([...shrinkable.shrink()].map(s => s.value), [data[0]]);
})
Expand Down

0 comments on commit cb860dc

Please sign in to comment.