I'm trying to generate a series of actions, where the actions that should be generated depend on what the previous actions were.
Let's say my state is a set of numbers stored as an array:
[1, 2]
And there are the following actions:
{ type: "add", value: number }
{ type: "remove", value: number }
I want to generate a series of actions to dispatch before checking properties of the state. If a remove action is generated, I want to ensure that it's value is in the state.
Valid Examples:
initial state: [1, 2]
[{ type: "remove", value: 1 }, { type: "remove", value: 2 }]
[{ type: "add", value: 3 }, { type: "remove", value: 3 }]
Invalid Examples:
initial state: [1, 2]
[{ type: "remove", value: 3 }]
[{ type: "remove", value: 2 }, { type: "remove", value: 2 }]
Is this something that is possible using a property based testing library, and if so how would I accomplish it?
I am using https://github.com/dubzzz/fast-check, but if this is easier using another library I'm open to examples from others.
Yes, this is perfectly suited for property-based testing. From a quick skimming of the docs of fast-check, I can see three approaches to this:
Command
, all commands would simply apply their respective action, and in their check
method you would validate whether the action is eligible.Set
of occurring numbers or a Map
of their counts, not an ordered array.letrec
or memo
help here, whether you might need to use chain
, or ask the library author to provide an extra function for this use case. (Maybe even as part of model-based testing, where Command
instances could be dynamically derived from the current model?)[add(x)]
and [add(y), remove(y)]
lists, merge these in arbitrary order but keeping the respective order between the elements of each sublist.Arbitrary
for the randomMerge
function - maybe ask the library author for help with this or request a new feature.