Skip to content

Instantly share code, notes, and snippets.

@dubzzz
Created April 14, 2021 19:36
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dubzzz/c26b20d2695410eb871177decd197d87 to your computer and use it in GitHub Desktop.
Save dubzzz/c26b20d2695410eb871177decd197d87 to your computer and use it in GitHub Desktop.
pbt.ts
import fc from 'fast-check';
// Characteristics independent of the inputs
test('for any floating point number d, Math.floor(d) is an integer', () => {
fc.assert(fc.property(fc.double(), (d) => Number.isInteger(Math.floor(d))));
});
test('for any floating point number d, Math.abs(d) ≥ 0', () => {
fc.assert(fc.property(fc.double(), (d) => Math.abs(d) >= 0));
});
// Characteristics derived from the inputs
test('for any a and b integers, the average of a and b is between a and b', () => {
fc.assert(
fc.property(fc.integer(), fc.integer(), (a, b) => {
const r = average(a, b);
if (a <= b) return a <= r && r <= b;
else return b <= r && r <= a;
})
);
});
test("for any n positive integer, its square root multiplied by itself 'is' n", () => {
fc.assert(
fc.property(fc.nat(), (n) => {
const s = Math.sqrt(n);
const nNew = s * s;
return n - n * Number.EPSILON <= nNew && nNew <= n + n * Number.EPSILON;
})
);
});
test('for any n, the product of all numbers in the prime factor decomposition of n equals n', () => {
fc.assert(
fc.property(fc.nat(), (n) => {
let acc = 1;
for (const d of decompPrime(n)) {
acc *= d;
}
return acc === n;
})
);
});
test('for any n, the decomposition in prime factors of its own prime factors are themselves', () => {
fc.assert(
fc.property(fc.nat(), (n) => {
for (const d of decompPrime(n)) {
expect(decompPrime(d)).toEqual([d]);
}
})
);
});
test('for any a and b, such as n = a * b, the decomposition in prime factors be the merge of primes of a and primes of b', () => {
fc.assert(
fc.property(fc.integer({ min: 2, max: 10000 }), fc.integer({ min: 2, max: 10000 }), (a, b) => {
const decompA = decompPrime(a);
const decompB = decompPrime(b);
const decompN = decompPrime(a * b);
expect(sort(decompN)).toEqual(sort([...decompA, ...decompB]));
})
);
});
test('for any tab array of integers, the sorted tab is sorted', () => {
fc.assert(
fc.property(fc.array(fc.integer()), (tab) => {
const sorted = sort(tab);
for (let idx = 1; idx < sorted.length; ++idx) {
expect(sorted[idx - 1]).toBeLessThanOrEqual(sorted[idx]);
}
})
);
});
test('for any tab arrays of integers, the sorted tab contains the same elements as tab', () => {
fc.assert(
fc.property(fc.array(fc.integer()), (tab) => {
const sorted = sort(tab);
for (const item of new Set(sorted)) {
expect(sorted.filter((v) => v == item).length).toBe(tab.filter((v) => v == item).length);
}
for (const item of new Set(tab)) {
expect(sorted.filter((v) => v == item).length).toBe(tab.filter((v) => v == item).length);
}
})
);
});
// Restricted set of inputs with useful characteristics
test('for any array data without duplicates, the result of removing duplicates from data is data itself', () => {
fc.assert(
fc.property(fc.set(fc.integer()), (tab) => {
expect(noDuplicates(tab)).toEqual(tab);
})
);
});
test('for any a, b and c strings, the concatenation of a, b and c always contains b', () => {
fc.assert(fc.property(fc.string(), fc.string(), fc.string(), (a, b, c) => contains(b, a + b + c)));
});
// Characteristics on combination of functions
test('for any JSON object, parsing its string representation results in a clone of itself', () => {
fc.assert(
fc.property(fc.jsonObject(), (obj) => {
expect(JSON.parse(JSON.stringify(obj))).toEqual(obj);
})
);
});
// Comparison with a simpler implementation
// Helpers
const average = (a: number, b: number) => (a + b) / 2;
const decompPrime = (n: number): number[] => {
const decomp: number[] = [];
let current = n;
let currentLimit = Math.floor(Math.sqrt(current));
for (let dividerCandidate = 2; dividerCandidate <= currentLimit; ++dividerCandidate) {
if (current % dividerCandidate === 0) {
current = current / dividerCandidate;
currentLimit = Math.floor(Math.sqrt(current));
decomp.push(dividerCandidate);
--dividerCandidate; // otherwise we will fail to have n = m^3
}
}
return [...decomp, current];
};
const sort = (tab: number[]): number[] => {
return [...tab].sort((a, b) => a - b);
};
const noDuplicates = (tab: number[]): number[] => {
return [...new Set(tab)];
};
const contains = (pattern: string, text: string): boolean => {
return text.includes(pattern);
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment