.TH ct_property_test 3erl "common_test 1.19.1" "Ericsson AB" "Erlang Module Definition" .SH NAME ct_property_test \- Support in Common Test for running property-based tests. .SH DESCRIPTION .LP This module helps running property-based tests in the \fICommon Test\fR\& framework\&. One (or more) of the property testing tools .RS 2 .TP 2 * QuickCheck, .LP .TP 2 * PropEr or .LP .TP 2 * Triq .LP .RE .LP is assumed to be installed\&. .LP The idea with this module is to have a \fICommon Test\fR\& test suite calling a property testing tool with special property test suites as defined by that tool\&. The tests are collected in the \fItest\fR\& directory of the application\&. The \fItest\fR\& directory has a subdirectory \fIproperty_test\fR\&, where everything needed for the property tests are collected\&. The usual Erlang application directory structure is assumed\&. .LP A typical \fICommon Test\fR\& test suite using \fIct_property_test\fR\& is organized as follows: .LP .nf -module(my_prop_test_SUITE). -compile(export_all). -include_lib("common_test/include/ct.hrl"). all() -> [prop_ftp_case]. init_per_suite(Config) -> ct_property_test:init_per_suite(Config). %%%---- test case prop_ftp_case(Config) -> ct_property_test:quickcheck( ftp_simple_client_server:prop_ftp(), Config ). .fi .LP and the the property test module (in this example \fIftp_simple_client_server\&.erl\fR\&) as almost a usual property testing module (More examples are in the User\&'s Guide): .LP .nf -module(ftp_simple_client_server). -export([prop_ftp/0...]). -include_lib("common_test/include/ct_property_test.hrl"). prop_ftp() -> ?FORALL( .... .fi .SH EXPORTS .LP .B init_per_suite(Config) -> Config | {skip, Reason} .br .RS .LP Initializes and extends \fIConfig\fR\& for property based testing\&. .LP This function investigates if support is available for either QuickCheck, PropEr or Triq and compiles the properties with the first tool found\&. It is supposed to be called in the \fIinit_per_suite/1\fR\& function in a CommonTest test suite\&. .LP Which tools to check for, and in which order could be set with the option \fI{prop_tools, list(eqc|proper|triq)}\fR\& in the CommonTest configuration \fIConfig\fR\&\&. The default value is \fI[eqc, proper, triq]\fR\& with \fIeqc\fR\& being the first one searched for\&. .LP If no support is found for any tool, this function returns \fI{skip, Explanation}\fR\&\&. .LP If support is found, the option \fI{property_test_tool,ToolModule}\fR\& with the selected tool main module name (\fIeqc\fR\&, \fIproper\fR\& or \fItriq\fR\&) is added to the list \fIConfig\fR\& which then is returned\&. .LP The property tests are assumed to be in a subdirectory named \fIproperty_test\fR\&\&. All found Erlang files in that directory are compiled with one of the macros \fI\&'EQC\&'\fR\&, \fI\&'PROPER\&'\fR\& or \fI\&'TRIQ\&'\fR\& set, depending on which tool that is first found\&. This could make parts of the Erlang property tests code to be included or excluded with the macro directives \fI-ifdef(Macro)\&.\fR\& or \fI-ifndef(Macro)\&.\fR\&\&. .LP The file(s) in the \fIproperty_test\fR\& subdirectory could, or should, include the ct_property_test include file: .LP .nf -include_lib("common_test/include/ct_property_test.hrl"). .fi .LP This included file will: .RS 2 .TP 2 * Include the correct tool\&'s include file .LP .TP 2 * Set the macro \fI\&'MOD_eqc\&'\fR\& to the correct module name for the selected tool\&. That is, the macro \fI\&'MOD_eqc\&'\fR\& is set to either \fIeqc\fR\&, \fIproper\fR\& or \fItriq\fR\&\&. .LP .RE .RE .LP .B quickcheck(Property, Config) -> true | {fail, Reason} .br .RS .LP Calls the selected tool\&'s function for running the \fIProperty\fR\&\&. It is usually and by historical reasons called quickcheck, and that is why that name is used in this module (\fIct_property_test\fR\&)\&. .LP The result is returned in a form suitable for \fICommon Test\fR\& test suites\&. .LP This function is intended to be called in test cases in test suites\&. .RE .LP .B present_result(Module, Cmds, Triple, Config) -> Result .br .RS .LP Same as \fIpresent_result(Module, Cmds, Triple, Config, [])\fR\& .RE .LP .B present_result(Module, Cmds, Triple, Config, Options) -> Result .br .RS .LP Types: .RS 3 Module = module() .br .RS 2 .RE Cmds = .br .RS 2 the list of commands generated by the property testing tool, for example by proper:commands/1 or by proper:parallel_commands/1 .RE Triple = .br .RS 2 the output from for example proper:run_commands/2 or proper:run_parallel_commands/2 .RE Config = .br .RS 2 the Common Test Config in test cases\&. .RE Options = [present_option()] .br present_option() = {print_fun, fun(Format,Args)} .br | {spec, StatisticsSpec} .br .RS 2 The \fIprint_fun\fR\& defines which function to do the actual printout\&. The default is ct:log/2\&. The \fIspec\fR\& defines what statistics are to be printed .RE Result = boolean() .br .RS 2 Is \fIfalse\fR\& if the test failed and is \fItrue\fR\& if the test passed .RE .RE .RE .RS .LP Presents the result of \fIstateful (statem) property testing\fR\& using the aggregate function in PropEr, QuickCheck or other similar property testing tool\&. .LP It is assumed to be called inside the property called by quickcheck/2: .LP .nf \&... RunResult = run_parallel_commands(?MODULE, Cmds), ct_property_test:present_result(?MODULE, Cmds, RunResult, Config) \&... .fi .LP See the User\&'s Guide for an example of the usage and of the default printout\&. .LP The \fIStatisticsSpec\fR\& is a list of the tuples: .RS 2 .TP 2 * \fI{Title::string(), CollectFun::fun/1}\fR\& .LP .TP 2 * \fI{Title::string(), FrequencyFun::/0, CollectFun::fun/1}\fR\& .LP .RE .LP Each tuple will produce one table in the order of their places in the list\&. .RS 2 .TP 2 * \fITitle\fR\& will be the title of one result table .LP .TP 2 * \fICollectFun\fR\& is called with one argument: the \fICmds\fR\&\&. It should return a list of the values to be counted\&. The following pre-defined functions exist: .RS 2 .TP 2 * \fIct_property_test:cmnd_names/1\fR\& returns a list of commands (function calls) generated in the \fICmnd\fR\& sequence, without Module, Arguments and other details\&. .LP .TP 2 * \fIct_property_test:num_calls/1\fR\& returns a list of the length of commands lists .LP .TP 2 * \fIct_property_test:sequential_parallel/1\fR\& returns a list with information about sequential and parallel parts from \fITool:parallel_commands/1,2\fR\& .LP .RE .LP .TP 2 * \fIFrequencyFun/0\fR\& returns a fun/1 which is supposed to take a list of items as input, and return an iolist wich will be printed as the table\&. Per default, the number of each item is counted and the percentage is printed for each\&. The list [a,b,a,a,c] could for example return .LP .nf ["a 60%\\n","b 20%\\n","c 20%\\n"] .fi which will be printed by the \fIprint_fun\fR\&\&. The default \fIprint_fun\fR\& will print it as: .LP .nf a 60% b 20% c 20% .fi .LP .RE .LP The default \fIStatisticsSpec\fR\& is: .RS 2 .TP 2 * For sequential commands: .LP .nf [{"Function calls", fun cmnd_names/1}, {"Length of command sequences", fun print_frequency_ranges/0, fun num_calls/1}] .fi .LP .TP 2 * For parallel commands: .LP .nf [{"Distribution sequential/parallel", fun sequential_parallel/1}, {"Function calls", fun cmnd_names/1}, {"Length of command sequences", fun print_frequency_ranges/0, fun num_calls/1}] .fi .LP .RE .RE