Testing stack in qcheck


I am exploring qcheck and i am not sure the way i test stack like below is correct or not.
Appreciate your suggestion. Thanks.

let test_fun ~name = QCheck2.(Test.make ~name
~print:Print.(list int)
Gen.(list int)) in
let create_stack l = Stack.of_seq (List.to_seq l) in
let flist = [
   ("length", (fun l -> Stack.length (create_stack l) = List.length l)) ;
   ("pop", (fun l -> try Stack.pop (create_stack l) = List.hd (List.rev l) with Failure _ -> true)) ;
   ("top", (fun l -> try Stack.top (create_stack l) = List.hd (List.rev l) with Failure _ -> true)) ;
   ("clear", (fun l -> let st = create_stack l in Stack.clear st; Stack.length st = 0)) ;
   ("push", (fun l -> let st = create_stack l in Stack.push 101 st; Stack.pop st = 101)) ;
] in
let tests = flist |> List.map (fun (n,f) -> test_fun ~name:n f) in
QCheck_runner.run_tests ~verbose:true tests ;;


Your tests look reasonable to me. It seems that what you are doing is comparing the result of each stack operation with a model of what it should be, in the form of a list.

You can push that testing principle further by testing sequences of operations—e.g. a push, two pops, and another push— and verifying that the result still coincides with the list model. This possibly covers more scenarios than testing each operation individually.

Such model-based testing can be automated using qcstm: you provide a list of operations and describe what their effect should be, and qcstm generates sequences of such operations and verifies their result.


Thank you for your suggestion @otini.
qcstm is interesting.