1[![Github Actions][github badge]][github] 2[![CodeCov][codecov badge]][codecov] 3[![Erlang Versions][erlang versions badge]][erlang] 4[![License][license badge]][license] 5[![Latest Release][release badge]][release] 6[![Hex PM][hex pm badge]][hex] 7[![Last Commit][commit badge]][commit] 8 9Contact information and license 10------------------------------- 11 12PropEr (PROPerty-based testing tool for ERlang) is a QuickCheck-inspired 13open-source property-based testing tool for Erlang, developed by Manolis 14Papadakis, Eirini Arvaniti, and Kostis Sagonas. The base PropEr system was 15written mainly by Manolis Papadakis, and the stateful code testing subsystem 16by Eirini Arvaniti. Kostis Sagonas has been actively maintaining its code 17base since 2012. 18 19You can reach PropEr's developers in the following ways: 20 21* on the web: at [the project's home page](http://proper-testing.github.io) 22 or [the project's github page](https://github.com/proper-testing/proper) 23* by email: take the tool's name (all lowercase), add a @ followed by 24 softlab dot ntua dot gr 25 26We welcome user contributions and feedback (comments, suggestions, feature 27requests, bug reports, patches, etc.). 28 29Copyright 2010-2021 by Manolis Papadakis, Eirini Arvaniti, and Kostis Sagonas. 30 31This program is distributed under the [GPL](http://www.gnu.org/licenses/gpl.html), 32version 3 or later. Please see the [COPYING][license] file for details. 33 34 35Introduction 36------------ 37 38Traditional testing methodologies essentially involve software testers writing a 39series of test inputs for their programs, along with their corresponding 40expected outputs, then running the program with these inputs and observing 41whether it behaves as expected. This method of testing, while simple and easy to 42automate, suffers from a few problems, such as: 43 44* Writing test cases by hand is tedious and time consuming. 45* It is hard to know whether the test suite covers all aspects of the software 46 under test. 47 48Property-based testing is a novel approach to software testing, where the tester 49needs only specify the generic structure of valid inputs for the program under 50test, plus certain properties (regarding the program's behaviour and the 51input-output relation) which are expected to hold for every valid input. 52A property-based testing tool, when supplied with this information, should randomly 53produce progressively more complex valid inputs, then apply those inputs to the 54program while monitoring its execution, to ensure that it behaves according to 55its specification, as outlined in the supplied properties. 56 57Here are a few examples of simple properties a user may wish to test, expressed 58in natural language: 59 60* The program should accept any character string and convert all lowercase 61 letters inside the string to uppercase. 62* The program should accept any list of integers. If the input list is at 63 least 4 elements long, the program should return the 4th largest integer in 64 the list, else it should throw an exception. 65 66PropEr is such a property-based testing tool, designed to test programs written 67in the Erlang programming language. Its focus is on testing the behaviour of 68pure functions. On top of that, it is equipped with two library modules that can 69be used for testing stateful code. The input domain of functions is specified 70through the use of a type system, modeled closely after the type system of the 71language itself. Properties are written using Erlang expressions, with the help 72of a few predefined macros. 73 74PropEr is also tightly integrated with Erlang's type language: 75 76* Types expressed in the Erlang type language can be used instead of 77 generators written in PropEr's own type system as input data specifications. 78* Generators for ADTs can be constructed automatically using the ADTs' API 79 functions. 80* PropEr can test functions automatically, based solely on information 81 provided in their specs. 82 83 84Quickstart guide 85---------------- 86 87* Obtain a copy of PropEr's sources. You can either get a tagged version of 88 the tool (look under `Tags` on github) or you can clone the current code 89 base: 90 91 ```shell 92 git clone git://github.com/proper-testing/proper.git 93 ``` 94* Compile PropEr: Simply run `make` if you just want to build PropEr. 95 If you want to do some changes to PropEr or submit some pull request you 96 most likely will want to issue a `make test` to run its unit tests and 97 a `make dialyzer` call to also run dialyzer on PropEr's code base. 98 To do the above but also build PropEr's documentation issue a `make all` 99 call; in that case, you are going to need the `syntax_tools` application 100 and a recent version of `EDoc`). 101* If you are using [Homebrew](https://brew.sh), you can simply: 102 103 ```shell 104 brew install proper 105 ``` 106 and continue following the instructions below. 107* Add PropEr's base directory to your Erlang library path, using one of the 108 following methods: 109 1. `ERL_LIBS` environment variable: Add the following line to your shell 110 startup file (`~/.bashrc` in the case of the Bash shell): 111 112 ```shell 113 export ERL_LIBS=/full/path/to/proper 114 ``` 115 2. Erlang resource file: Add the following line to your `~/.erlang` file: 116 117 ```erlang 118 code:load_abs("/full/path/to/proper"). 119 ``` 120* Add the following include line to all source files that contain properties: 121 122 ```erlang 123 -include_lib("proper/include/proper.hrl"). 124 ``` 125 126* Compile those source files, preferably with `debug_info` enabled. 127* For each property, run: 128 129 ```erlang 130 proper:quickcheck(your_module:some_property()). 131 ``` 132 See also the section common problems below if you want to run 133 PropEr from EUnit. 134 135 136Where to go from here 137--------------------- 138 139To get started on using PropEr, see the tutorials and testing tips provided on 140[PropEr's home page](http://proper-testing.github.io). On the same site you can 141find a copy of PropEr's API documentation (you can also build this from source 142if you prefer, by running `make doc`), as well as links to more resources on 143property-based testing. 144 145 146Common problems 147--------------- 148 149### Using PropEr in conjunction with EUnit 150 151The main issue is that both systems define a **`?LET`** macro. To avoid a 152potential clash, simply include PropEr's header file before EUnit's. That 153way, any instance of **`?LET`** will count as a PropEr **`?LET`**. 154 155Another issue is that [EUnit captures standard output][eunit stdout], 156so normally PropEr output is not visible when `proper:quickcheck()` is 157invoked from EUnit. You can work around this by passing the option 158`{to_file, user}` to `proper:quickcheck/2`. For example: 159```erlang 160?assertEqual(true, proper:quickcheck(your_mod:some_prop(), [{to_file, user}])). 161``` 162This will make PropEr properties visible also when invoked from EUnit. 163 164 165Incompatibilities with QuviQ's QuickCheck 166----------------------------------------- 167 168PropEr's notation and output format has been kept quite similar to that of 169QuviQ's QuickCheck in order to ease the reuse of existing testing code written 170for that tool. However, incompatibilities are to be expected, since we never 171run or owned a copy of QuviQ's QuickCheck and the two programs probably bear 172little resemblance under the hood. Here we provide a nonexhaustive list of 173known incompatibilities: 174 175* **`?SUCHTHATMAYBE`** behaves differently in PropEr. 176* `proper_gen:pick/1` differs from `eqc_gen:pick/1` in return value format. 177* PropEr handles `size` differently from QuickCheck. 178* `proper:module/2` accepts options in the second argument instead of the 179 first; this is for consistency with other `module/2` functions in Erlang/OTP. 180 181All the above are from circa 2010. Most likely, there exist many more 182incompatibilities between the two tools by now. 183 184 185<!-- Links (alphabetically) --> 186[codecov]: https://codecov.io/gh/proper-testing/proper 187[commit]: https://github.com/proper-testing/proper/commit/HEAD 188[erlang]: http://www.erlang.org 189[eunit stdout]: http://erlang.org/doc/apps/eunit/chapter.html#Running_EUnit 190[hex]: https://hex.pm/packages/proper 191[license]: ./COPYING 192[release]: https://github.com/proper-testing/proper/releases/latest 193[github]: https://github.com/proper-testing/proper/actions 194 195<!-- Badges (alphabetically) --> 196[codecov badge]: https://codecov.io/gh/proper-testing/proper/branch/master/graph/badge.svg 197[commit badge]: https://img.shields.io/github/last-commit/proper-testing/proper.svg?style=flat-square 198[erlang versions badge]: https://img.shields.io/badge/erlang-20.0%20to%2024.0-blue.svg?style=flat-square 199[hex pm badge]: https://img.shields.io/hexpm/v/proper.svg?style=flat 200[license badge]: https://img.shields.io/github/license/proper-testing/proper.svg?style=flat-square 201[release badge]: https://img.shields.io/github/release/proper-testing/proper.svg?style=flat-square 202[github badge]: https://github.com/proper-testing/proper/workflows/CI/badge.svg 203