misunderstanding the tool - too much work defining properties #4015
-
I maybe misunderstanding how to use fast-check because I'm finding it rather time consuming define properties such as a malformed zip code or po box lines to test a normalize function. Perhaps a property runner is not right for string transformers? What is a right way to define properties the produces strings such as:
The assertions also seem a bit tricky and the way I have been thinking about it I need to filter out runs and use non-trivial regex that might be flawed. Here's an example that might how I am doing multiple things wrong: it("should remove punctuation except the zip code's hyphen", () => {
const digitArbitrary = fc.integer({ min: 0, max: 9 }).map(String);
const zipCodeArbitrary = fc
.stringOf(digitArbitrary, { minLength: 5, maxLength: 5 })
.map((digits) => `${digits.slice(0, 5)}-${digits.slice(5)}`);
const sentenceArbitrary = fc.array(fc.string(), { minLength: 1, maxLength: 10 }).map((words) => words.join(" "));
fc.assert(
fc.property(zipCodeArbitrary, sentenceArbitrary, (zip, sentence) => {
const insertPos = Math.floor(Math.random() * sentence.length);
const input = sentence.slice(0, insertPos) + zip + sentence.slice(insertPos);
const output = removePunctuationWithZipcode(input);
output.includes("-")
? expect(output).toMatch(/^(?:\d{5}-\d{4}|(?!\d{5}-\d{4})\d*-\d*)*$/)
: input.includes("-")
? expect(input).not.toMatch(/\d{5}-\d{4}/)
: expect(output).toBe(input);
})
);
}); Its not "bad" and I am exposing some edges I had missed with example based testing, but it seems to take quite a bit of effort on this cases that I thought would be simple so I think I'm using it wrong. Thank you. |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 2 replies
-
Generating strings close to a given pattern After re-reading through your message I'm not sure it's what you are looking for but as I already had the message ready let's keep it! This feature is coming soon: https://twitter.com/ndubien/status/1673573855342755841?s=20 For now, maybe something like But defining string not-matching something is not trivial as most of the time it should not match but should barely match and even with the helper in this tweet nothing prevent the generated string from matching except you. I think these examples might help you to get some examples of proper usages of property based testing:
Asserting the right things When building properties for the first time, the most challenging part is to find what to assert. Generally, as we all think in an example-based testing manner, we want to assess the full input but that's often not what we want to do. In property based, I think the key is to know that we will rarely be able to write As an example always express itself better than anything else, let's take one:
If we wanted to check that algorithm here how you could think in a property based manner:
Our property would work as follow: fc.assert(fc.property(
fc.string(), // the name for the start point
fc.array(fc.record({to: fc.string(), distance: fc.nat())), // the next stops in our known path
fc.array(fc.record({from: fc.string(), to: fc.string(), distance: fc.nat())), // extra links
(start, pathStops, extraLinks) => {
const links = [...extraLinks];
let lastStop = start;
let knownDistance = 0;
for (const stop of pathStops) {
links.push({from: lastStop, ...stop});
lastStop = stop.to;
knownDistance += stop.distance;
}
// we know for sure a path from start to lastStop with distance being knownDistance
// we expect to find it or better!
expect(shortest(links, start, lastStop)).toLowerThanOrEqualTo(knownDistance);
}
)) |
Beta Was this translation helpful? Give feedback.
Generating strings close to a given pattern
After re-reading through your message I'm not sure it's what you are looking for but as I already had the message ready let's keep it!
This feature is coming soon: https://twitter.com/ndubien/status/1673573855342755841?s=20
For now, maybe something like
fc.stringMatching
might help you but you need to somehow be able to express what string you are waiting for in terms of a regex.But defining string not-matching something is not trivial as most of the time it should not match but should barely match and even with the helper in this tweet nothing prevent the generated string from matching except you.
I think these examples might help you to get s…