Module eqc

This module defines functions for writing and testing QuickCheck properties.

Version: 1.0.1

Description

This module defines functions for writing and testing QuickCheck properties. Much of the interface is provided via macros (defined in eqc.hrl). These are documented below:

?FORALL(X,Gen,Prop)

Property that holds if Prop holds for all values X that can be generated by Gen. For example,
 prop_reverse() ->
   ?FORALL(Xs,list(int()),
      lists:reverse(lists:reverse(Xs)) == Xs).
 
Generators are defined using the module eqc_gen.

?IMPLIES(Pre,Prop)

Property that holds if Prop holds whenever the precondition Pre is true. The precondition must be a boolean, but Prop can be any QuickCheck property. An implication is tested by discarding test cases which do not satisfy the precondition. This can make testing slow, since many more test cases may need to be generated to find 100 which satisfy the precondition. In the worst case, QuickCheck may not be able to find enough test cases that do satisfy the precondition, in which case the number actually found is reported. Some preconditions may also skew the test data badly--for example, a precondition that a list is sorted skews the test data towards short lists, since random longer lists are extremely unlikely to be sorted just by chance. ?IMPLIES works well for preconditions which are true with a high probability, but if the precondition is unlikely to hold, then it is better to write a custom generator which generates test cases where the precondition is true.

?WHENFAIL(Action,Prop)

Property that is equivalent to Prop, but performs Action (for its side effects) when Prop fails. This can be used to print additional information when a test case fails.

Data Types

counterexample()

abstract datatype: counterexample()

A counter-example to a QuickCheck property, which can be obtained using counterexample/0 or counterexample/1, and used to repeat a test, or test a different property in the same case. Counterexamples are represented by the values bound by ?FORALL--for the counterexample to make sense independently, it's important that these were generated without side-effects.

print_method()

print_method() = (list(term())) -> any()

A function for printing statistics, which is passed a list of samples and is expected to print statistical information about them. Print methods are used by collect/3 and aggregate/3.

property()

abstract datatype: property()

QuickCheck properties, which can either be boolean expressions, or constructed using the functions in this module. QuickCheck properties are tested using quickcheck/1.

Function Index

aggregate/2A property logically equivalent to Prop, but which collects a list of values in each test, and displays the distribution of these values once testing is complete.
aggregate/3Like aggregate/2, but allows the user to specify how the collected values should be printed.
backtrace/0Displays a stack backtrace from the last exception QuickCheck caught.
check/2Tests the property in the case given.
classify/3Property which is logically equivalent to Prop, but also classifies test cases and displays the distribution of test case classes when testing is complete.
collect/2Equivalent to aggregate([S], Prop).
collect/3Equivalent to aggregate(PrintMethod, [S], Prop).
counterexample/0Returns the last counter-example found.
counterexample/1Tests the property in the same way as quickcheck/1, but if a test fails, then the failing test case is returned as a counterexample.
counterexamples/0Returns a list of the counterexamples found by the last call of eqc:module, paired with the name of the property that failed.
current_counterexample/0Returns the most recent counterexample found by QuickCheck.
equals/2A property which holds if X and Y are equal...
fails/1A property which succeeds when its argument fails.
measure/3Collects the values of X while testing Prop, and if all tests pass, displays statistics such as the minimum, average, and maximum values, identified by the name Name.
module/1Tests all the properties exported from a module, given the module name.
numtests/2Property which is logically equivalent to Prop, but is tested N times rather than 100.
on_output/2Supplies an output function to be used instead of io:format when QuickCheck generates output.
on_test/2Attaches a function to a property which is called every time a test passes or fails.
quickcheck/1Tests the property in 100 random cases, printing a counter-example if one is found.
recheck/1Tests the property with the same random number seed as the last failing call of quickcheck/1.
start/0Equivalent to start(true).
start/1Starts the QuickCheck server.
stop/0Stops the QuickCheck server.
version/0
with_title/1A printing method for collected data, which displays a title before the percentages of each value in the data.

Function Details

aggregate/2

aggregate(L::list(term()), Prop::property()) -> property()

A property logically equivalent to Prop, but which collects a list of values in each test, and displays the distribution of these values once testing is complete. A typical use would be to aggregate the list of command names generated by eqc_statem:commands/1, in order to see how often each individual command appeared in generated tests:

aggregate(command_names(Cmds), ...) 

See also aggregate/3.

aggregate/3

aggregate(PrintMethod::(list(term())) -> any(), L::list(term()), Prop::property()) -> property()

Like aggregate/2, but allows the user to specify how the collected values should be printed. The PrintMethod parameter is called with a sorted list of the collected data as an argument, and is expected to print some statistics. A predefined printing methods is provided to add a title to the statistics:

aggregate(with_title(T),L,Prop)
. This is useful when a property contains several calls to aggregate or collect.

backtrace/0

backtrace() -> ok

Displays a stack backtrace from the last exception QuickCheck caught. Note that this is only possible if the exception is raised in the process in which the test case starts. If a test case fails because of an exception in another, linked, process, then no backtrace is available. Calls to functions in the implementation of QuickCheck itself are not included in the backtrace.

If you really need to see a backtrace from a linked process, then you can do so by catching the exception yourself in that process, using erlang:get_stacktrace() to obtain the backtrace, and printing it yourself.

check/2

check(P::property(), Values::counterexample()) -> bool()

Tests the property in the case given. Counterexamples are generated by testing a property using counterexample/1 or counterexample/0, and contain a list of the values bound by ?FORALL. A property tested by check should begin with the same sequence of ?FORALL s as the property from which the counterexample was generated, otherwise the results will be unpredictable. In particular, there is no check that the values in the counterexample could actually have been generated by the ?FORALL s in the property under test.

check/2 can be used without a QuickCheck licence, allowing anyone to run tests that a licenced user has generated.

classify/3

classify(B::bool(), S::term(), Prop::property()) -> property()

Property which is logically equivalent to Prop, but also classifies test cases and displays the distribution of test case classes when testing is complete. If the boolean is true then the current test case is labelled with the term S, and, after testing is complete, QuickCheck prints out the percentage of test cases carrying each label. This can be used to check that the space of possible test cases has been covered reasonably well. For example, classifying test cases according to the length of a list enables one to see whether unreasonably many lists were short. Classifying test cases is a way to discover skewed distributions, such as can arise from using ?IMPLIES. It is good practice to check the distribution of test data using classify or collect/2, at least while properties are being developed.

Each test case can be labelled with any number of labels: QuickCheck then displays the percentage of each label in the generated test data.

Calls of classify or collect can be nested, in which case each call generates its own table of distributions.

collect/2

collect(S::term(), Prop::property()) -> property()

Equivalent to aggregate([S], Prop).

collect/3

collect(PrintMethod::(list(term())) -> any(), S::term(), Prop::property()) -> property()

Equivalent to aggregate(PrintMethod, [S], Prop).

counterexample/0

counterexample() -> undefined | counterexample()

Returns the last counter-example found. See counterexample/1.

counterexample/1

counterexample(P::property()) -> true | counterexample()

Tests the property in the same way as quickcheck/1, but if a test fails, then the failing test case is returned as a counterexample.

counterexamples/0

counterexamples() -> list({atom(), counterexample()})

Returns a list of the counterexamples found by the last call of eqc:module, paired with the name of the property that failed.

current_counterexample/0

current_counterexample() -> counterexample()

Returns the most recent counterexample found by QuickCheck. This can be used while QuickCheck is shrinking a failed test case to follow progress, or if shrinking must be interrupted, to recover the last failed test case that QuickCheck had found. The counterexample is fetched from a file in the current directory.

equals/2

equals(X::any(), Y::any()) -> property()

A property which holds if X and Y are equal... and displays their values when a test fails.

fails/1

fails(P::property()) -> property()

A property which succeeds when its argument fails. Sometimes it is useful to write down properties which do not hold (even though one might expect them to). This can help prevent misconceptions. fails(P) is tested in the same way as P, but fails only if P succeeds 100 times. Thus fails(P) declares that QuickCheck should be able to find a counter-example to property P.

measure/3

measure(Name::atom() | string(), X::number() | list(number()), Prop::property()) -> property()

Collects the values of X while testing Prop, and if all tests pass, displays statistics such as the minimum, average, and maximum values, identified by the name Name. X can also be a list of values, in which case all of them are included in the measurements.

module/1

module(Mod::atom()) -> list(atom())

Tests all the properties exported from a module, given the module name. Any function with arity zero whose name begins with "prop_" is treated as a property. The result is a list of the names of the properties that failed. See also module/2.

numtests/2

numtests(N::int(), Prop::property()) -> property()

Property which is logically equivalent to Prop, but is tested N times rather than 100. If numtests appears more than once in a property, then the outermost use takes precedence.

on_output/2

on_output(Fun::(string(), list(term())) -> any(), Prop::property()) -> property()

Supplies an output function to be used instead of io:format when QuickCheck generates output. All output generated by QuickCheck is passed to Fun, in the form of a format string and a list of terms--the same arguments expected by io:format. By supplying a function which does nothing, QuickCheck can be run silently. By supplying a function which writes to a file, all QuickCheck output can be saved.

Note that output generated by user code is not passed to this output function. For example, calls to io:format in the property, or in the code under test, will generate output in the shell as usual. This applies even to calls inside a ?WHENFAIL. If you want to redirect such output also, then you need to modify your own code appropriately.

The reason that Fun is passed a format string and arguments, rather than an already formatted string, is to make it easier to extract information from the output without parsing it. However, there is no guarantee that different versions of QuickCheck will use the same format strings and term lists--you use this information at your own risk, in other words.

on_test/2

on_test(Fun::(counterexample(), bool()) -> any(), Prop::property()) -> property()

Attaches a function to a property which is called every time a test passes or fails. The arguments are the test case (a list of values), and a boolean indicating whether or not the test passed. Tests which are skipped (because of an ?IMPLIES(false,...)) are not included.

quickcheck/1

quickcheck(P::property()) -> bool()

Tests the property in 100 random cases, printing a counter-example if one is found. Initially small test cases are generated, then the size increases as testing progresses (see eqc_gen, ?SIZED, eqc_gen:resize/2 for the way size affects test data generation). The result is true if all tests succeeded (or if one failed, and failure was expected). On success, quickcheck analyses the distribution of test case labels. On failure, quickcheck tries to simplify the counter-example found as far as possible (see shrinking, described in eqc_gen).

recheck/1

recheck(Prop::property()) -> bool()

Tests the property with the same random number seed as the last failing call of quickcheck/1. If the property is the same as in that last call, then the same test case will be generated. Note that recheck repeats the test and its shrinking. This can be used to adjust the shrinking strategy in the property, then reshrink the same counterexample, perhaps to a better result. If you just want to repeat the shrunk test, then use

eqc:check(Prop,eqc:counterexample())
instead.

Note: the type and behaviour of recheck changed in version 1.19.

start/0

start() -> any()

Equivalent to start(true).

start/1

start(Force::bool()) -> pid()

Starts the QuickCheck server. If it is already running on this node, nothing is done.

Each user can run only one instance of the QuickCheck server at a time. If the server is already running on another Erlang node, it will be terminated automatically if Force is true. If another instance is running, and Force is false, then the new instance will not start.

stop/0

stop() -> any()

Stops the QuickCheck server. QuickCheck properties are tested in the QuickCheck server process, which is spawned automatically when quickcheck is first called. Usually there is no need to stop the QuickCheck server explicitly, but if a need does arise then this function can be used. For example, if the shell process crashes and is restarted, then the QuickCheck server should be stopped and restarted too, since otherwise the server will crash when it attempts to write to the console.

version/0

version() -> any()

with_title/1

with_title(Title::atom() | string()) -> print_method()

A printing method for collected data, which displays a title before the percentages of each value in the data. It is intended to be passed to collect/3 or aggregate/3.


Generated by EDoc, Jun 13 2010, 13:15:30.