(window.webpackJsonp=window.webpackJsonp||[]).push([[1216],{1624:function(t,a,s){"use strict";s.r(a);var e=s(31),n=Object(e.a)({},(function(){var t=this,a=t.$createElement,s=t._self._c||a;return s("ContentSlotsDistributor",{attrs:{"slot-key":t.$parent.slotKey}},[s("h1",{attrs:{id:"quickcheck"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#quickcheck"}},[t._v("#")]),t._v(" QuickCheck")]),t._v(" "),s("h2",{attrs:{id:"randomly-generating-data-for-custom-types"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#randomly-generating-data-for-custom-types"}},[t._v("#")]),t._v(" Randomly generating data for custom types")]),t._v(" "),s("p",[t._v("The "),s("code",[t._v("Arbitrary")]),t._v(" class is for types that can be randomly generated by QuickCheck.")]),t._v(" "),s("p",[t._v("The minimal implementation of "),s("code",[t._v("Arbitrary")]),t._v(" is the "),s("code",[t._v("arbitrary")]),t._v(" method, which runs in the "),s("code",[t._v("Gen")]),t._v(" monad to produce a random value.")]),t._v(" "),s("p",[t._v("Here is an instance of "),s("code",[t._v("Arbitrary")]),t._v(" for the following datatype of non-empty lists.")]),t._v(" "),s("div",{staticClass:"language-hs extra-class"},[s("pre",{pre:!0,attrs:{class:"language-hs"}},[s("code",[s("span",{pre:!0,attrs:{class:"token import-statement"}},[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" Test"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("QuickCheck"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Arbitrary")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token constant"}},[t._v("Arbitrary")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("..")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token import-statement"}},[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" Test"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("QuickCheck"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Gen")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token hvariable"}},[t._v("oneof")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token import-statement"}},[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" Control"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("Applicative")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<$>")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<*>")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("data")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token constant"}},[t._v("NonEmpty")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token hvariable"}},[t._v("a")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token constant"}},[t._v("End")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token hvariable"}},[t._v("a")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("|")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token constant"}},[t._v("Cons")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token hvariable"}},[t._v("a")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token constant"}},[t._v("NonEmpty")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token hvariable"}},[t._v("a")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("instance")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token constant"}},[t._v("Arbitrary")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token hvariable"}},[t._v("a")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=>")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token constant"}},[t._v("Arbitrary")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token constant"}},[t._v("NonEmpty")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token hvariable"}},[t._v("a")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("where")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token hvariable"}},[t._v("arbitrary")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token hvariable"}},[t._v("oneof")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("-- randomly select one of the cases from the list")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token constant"}},[t._v("End")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<$>")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token hvariable"}},[t._v("arbitrary")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("-- call a's instance of Arbitrary")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token constant"}},[t._v("Cons")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<$>")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token hvariable"}},[t._v("arbitrary")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("<*>")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("-- call a's instance of Arbitrary")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token hvariable"}},[t._v("arbitrary")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("-- recursively call NonEmpty's instance of Arbitrary")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n\n")])])]),s("h2",{attrs:{id:"using-implication-to-check-properties-with-preconditions"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#using-implication-to-check-properties-with-preconditions"}},[t._v("#")]),t._v(" Using implication (==>) to check properties with preconditions")]),t._v(" "),s("div",{staticClass:"language-hs extra-class"},[s("pre",{pre:!0,attrs:{class:"language-hs"}},[s("code",[s("span",{pre:!0,attrs:{class:"token hvariable"}},[t._v("prop_evenNumberPlusOneIsOdd")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("::")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token constant"}},[t._v("Integer")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token constant"}},[t._v("Property")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token hvariable"}},[t._v("prop_evenNumberPlusOneIsOdd")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token hvariable"}},[t._v("x")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("even")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token hvariable"}},[t._v("x")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==>")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("odd")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token hvariable"}},[t._v("x")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("+")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n")])])]),s("p",[t._v("If you want to check that a property holds given that a precondition holds, you can use the "),s("code",[t._v("==>")]),t._v(" operator. Note that if it's very unlikely for arbitrary inputs to match the precondition, QuickCheck can give up early.")]),t._v(" "),s("div",{staticClass:"language-hs extra-class"},[s("pre",{pre:!0,attrs:{class:"language-hs"}},[s("code",[s("span",{pre:!0,attrs:{class:"token hvariable"}},[t._v("prop_overlySpecific")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token hvariable"}},[t._v("x")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token hvariable"}},[t._v("y")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token hvariable"}},[t._v("x")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==>")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token hvariable"}},[t._v("x")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("*")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token hvariable"}},[t._v("y")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("0")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token hvariable"}},[t._v("ghci")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token hvariable"}},[t._v("quickCheck")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token hvariable"}},[t._v("prop_overlySpecific")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("***")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token constant"}},[t._v("Gave")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token hvariable"}},[t._v("up")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token constant"}},[t._v("Passed")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token hvariable"}},[t._v("only")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("31")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token hvariable"}},[t._v("tests")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("\n\n")])])]),s("h2",{attrs:{id:"declaring-a-property"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#declaring-a-property"}},[t._v("#")]),t._v(" Declaring a property")]),t._v(" "),s("p",[t._v("At its simplest, a "),s("strong",[t._v("property")]),t._v(" is a function which returns a "),s("code",[t._v("Bool")]),t._v(".")]),t._v(" "),s("div",{staticClass:"language-hs extra-class"},[s("pre",{pre:!0,attrs:{class:"language-hs"}},[s("code",[s("span",{pre:!0,attrs:{class:"token hvariable"}},[t._v("prop_reverseDoesNotChangeLength")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token hvariable"}},[t._v("xs")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("length")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("reverse")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token hvariable"}},[t._v("xs")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("length")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token hvariable"}},[t._v("xs")]),t._v("\n\n")])])]),s("p",[t._v("A property declares a high-level invariant of a program. The QuickCheck test runner will evaluate the function with 100 random inputs and check that the result is always "),s("code",[t._v("True")]),t._v(".")]),t._v(" "),s("p",[t._v("By convention, functions that are properties have names which start with "),s("code",[t._v("prop_")]),t._v(".")]),t._v(" "),s("h2",{attrs:{id:"checking-a-single-property"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#checking-a-single-property"}},[t._v("#")]),t._v(" Checking a single property")]),t._v(" "),s("p",[t._v("The "),s("code",[t._v("quickCheck")]),t._v(" function tests a property on 100 random inputs.")]),t._v(" "),s("div",{staticClass:"language-hs extra-class"},[s("pre",{pre:!0,attrs:{class:"language-hs"}},[s("code",[s("span",{pre:!0,attrs:{class:"token hvariable"}},[t._v("ghci")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token hvariable"}},[t._v("quickCheck")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token hvariable"}},[t._v("prop_reverseDoesNotChangeLength")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("+++")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token constant"}},[t._v("OK")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token hvariable"}},[t._v("passed")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("100")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token hvariable"}},[t._v("tests")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("\n\n")])])]),s("p",[t._v("If a property fails for some input, "),s("code",[t._v("quickCheck")]),t._v(" prints out a counterexample.")]),t._v(" "),s("div",{staticClass:"language-hs extra-class"},[s("pre",{pre:!0,attrs:{class:"language-hs"}},[s("code",[s("span",{pre:!0,attrs:{class:"token hvariable"}},[t._v("prop_reverseIsAlwaysEmpty")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token hvariable"}},[t._v("xs")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("reverse")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token hvariable"}},[t._v("xs")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("-- plainly not true for all xs")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token hvariable"}},[t._v("ghci")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token hvariable"}},[t._v("quickCheck")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token hvariable"}},[t._v("prop_reverseIsAlwaysEmpty")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("***")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token constant"}},[t._v("Failed")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("!")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token constant"}},[t._v("Falsifiable")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token hvariable"}},[t._v("after")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("2")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token hvariable"}},[t._v("tests")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),t._v(" \n"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n\n")])])]),s("h2",{attrs:{id:"checking-all-the-properties-in-a-file"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#checking-all-the-properties-in-a-file"}},[t._v("#")]),t._v(" Checking all the properties in a file")]),t._v(" "),s("p",[s("code",[t._v("quickCheckAll")]),t._v(" is a Template Haskell helper which finds all the definitions in the current file whose name begins with "),s("code",[t._v("prop_")]),t._v(" and tests them.")]),t._v(" "),s("div",{staticClass:"language-hs extra-class"},[s("pre",{pre:!0,attrs:{class:"language-hs"}},[s("code",[s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("{-# LANGUAGE TemplateHaskell #-}")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token import-statement"}},[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" Test"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("QuickCheck")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token hvariable"}},[t._v("quickCheckAll")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token import-statement"}},[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" Data"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("List")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("sort")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token hvariable"}},[t._v("idempotent")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("::")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token constant"}},[t._v("Eq")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token hvariable"}},[t._v("a")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=>")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token hvariable"}},[t._v("a")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token hvariable"}},[t._v("a")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token hvariable"}},[t._v("a")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token constant"}},[t._v("Bool")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token hvariable"}},[t._v("idempotent")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token hvariable"}},[t._v("f")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token hvariable"}},[t._v("x")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token hvariable"}},[t._v("f")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token hvariable"}},[t._v("f")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token hvariable"}},[t._v("x")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token hvariable"}},[t._v("f")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token hvariable"}},[t._v("x")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token hvariable"}},[t._v("prop_sortIdempotent")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token hvariable"}},[t._v("idempotent")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("sort")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token comment"}},[t._v("-- does not begin with prop_, will not be picked up by the test runner")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token hvariable"}},[t._v("sortDoesNotChangeLength")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token hvariable"}},[t._v("xs")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("length")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("sort")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token hvariable"}},[t._v("xs")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("length")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token hvariable"}},[t._v("xs")]),t._v("\n\n\n"),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("return")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token hvariable"}},[t._v("main")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("$")]),s("span",{pre:!0,attrs:{class:"token hvariable"}},[t._v("quickCheckAll")]),t._v("\n\n")])])]),s("p",[t._v("Note that the "),s("code",[t._v("return []")]),t._v(" line is required. It makes definitions textually above that line visible to Template Haskell.")]),t._v(" "),s("div",{staticClass:"language-hs extra-class"},[s("pre",{pre:!0,attrs:{class:"language-hs"}},[s("code",[s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("$")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token hvariable"}},[t._v("runhaskell")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token hvariable"}},[t._v("QuickCheckAllExample"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("hs")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("===")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token hvariable"}},[t._v("prop_sortIdempotent")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token hvariable"}},[t._v("from")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token hvariable"}},[t._v("tree")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),s("span",{pre:!0,attrs:{class:"token hvariable"}},[t._v("hs")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(":")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("7")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("===")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("+++")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token constant"}},[t._v("OK")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(",")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token hvariable"}},[t._v("passed")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("100")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token hvariable"}},[t._v("tests")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("\n\n")])])]),s("h2",{attrs:{id:"limiting-the-size-of-test-data"}},[s("a",{staticClass:"header-anchor",attrs:{href:"#limiting-the-size-of-test-data"}},[t._v("#")]),t._v(" Limiting the size of test data")]),t._v(" "),s("p",[t._v("It can be difficult to test functions with poor asymptotic complexity using quickcheck as the random inputs are not usually size bounded. By adding an upper bound on the size of the input we can still test these expensive functions.")]),t._v(" "),s("div",{staticClass:"language-hs extra-class"},[s("pre",{pre:!0,attrs:{class:"language-hs"}},[s("code",[s("span",{pre:!0,attrs:{class:"token import-statement"}},[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" Data"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("List")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token hvariable"}},[t._v("permutations")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token import-statement"}},[s("span",{pre:!0,attrs:{class:"token keyword"}},[t._v("import")]),t._v(" Test"),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(".")]),t._v("QuickCheck")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token hvariable"}},[t._v("longRunningFunction")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("::")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token hvariable"}},[t._v("a")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token constant"}},[t._v("Int")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token hvariable"}},[t._v("longRunningFunction")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token hvariable"}},[t._v("xs")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("length")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token hvariable"}},[t._v("permutations")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token hvariable"}},[t._v("xs")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token hvariable"}},[t._v("factorial")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("::")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token constant"}},[t._v("Integral")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token hvariable"}},[t._v("a")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=>")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token hvariable"}},[t._v("a")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("->")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token hvariable"}},[t._v("a")]),t._v("\n"),s("span",{pre:!0,attrs:{class:"token hvariable"}},[t._v("factorial")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token hvariable"}},[t._v("n")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("product")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("[")]),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("1")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("..")]),s("span",{pre:!0,attrs:{class:"token hvariable"}},[t._v("n")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("]")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token hvariable"}},[t._v("prop_numberOfPermutations")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token hvariable"}},[t._v("xs")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v("\n "),s("span",{pre:!0,attrs:{class:"token hvariable"}},[t._v("longRunningFunction")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token hvariable"}},[t._v("xs")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("==")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token hvariable"}},[t._v("factorial")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token builtin"}},[t._v("length")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token hvariable"}},[t._v("xs")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v("\n\n"),s("span",{pre:!0,attrs:{class:"token hvariable"}},[t._v("ghci")]),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v(">")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token hvariable"}},[t._v("quickCheckWith")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("(")]),s("span",{pre:!0,attrs:{class:"token hvariable"}},[t._v("stdArgs")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("{")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token hvariable"}},[t._v("maxSize")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token operator"}},[t._v("=")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token number"}},[t._v("10")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v("}")]),s("span",{pre:!0,attrs:{class:"token punctuation"}},[t._v(")")]),t._v(" "),s("span",{pre:!0,attrs:{class:"token hvariable"}},[t._v("prop_numberOfPermutations")]),t._v("\n\n")])])]),s("p",[t._v("By using "),s("code",[t._v("quickCheckWith")]),t._v(" with a modified version of "),s("code",[t._v("stdArgs")]),t._v(" we can limit the size of the inputs to be at most 10. In this case, as we are generating lists, this means we generate lists of up to size 10. Our permutations function doesn't take too long to run for these short lists but we can still be reasonably confident that our definition is correct.")])])}),[],!1,null,null,null);a.default=n.exports}}]);