| #+OPTIONS: ^:nil |
| #+TITLE: Triq |
| |
| * [[https://gitlab.com/triq/triq][Triq]] QuickCheck for Erlang |
| |
| ** Introduction |
| :PROPERTIES: |
| :CUSTOM_ID: introduction |
| :END: |
| |
| Triq (Term Reductive Invariant Questant) is an Apache licensed |
| QuickCheck library for Erlang. It is a continuation and community fork |
| of [[https://github.com/krestenkrab/triq][Trifork QuickCheck]]. Unlike the original project, this fork is in |
| *no way* affiliated with or a product of Trifork. |
| |
| By and large, the Triq API is modeled closely after QuviQ =eqc=, |
| except you want to replace any occurrence of =eqc= with =triq=. The |
| main supporting module is called =triq_dom=, corresponding to eqc's |
| =eqc_gen=. |
| |
| #+BEGIN_EXPORT html |
| <a href="https://gitlab.com/triq/triq/pipelines"><img src="https://gitlab.com/triq/triq/badges/master/pipeline.svg"></a> |
| #+END_EXPORT |
| |
| ** Writing QuickCheck properties with Triq |
| :PROPERTIES: |
| :CUSTOM_ID: writing-properties-with-triq |
| :END: |
| |
| To write properties with =triq=, include the =triq.hrl= header file: |
| |
| #+BEGIN_EXAMPLE erlang |
| -include_lib("triq/include/triq.hrl"). |
| #+END_EXAMPLE |
| |
| Modules compiled with the =triq.hrl= header auto-export all functions |
| named =prop_*=, and have a function added called =check/0= which runs |
| =triq:check/1= on all the properties in the module. Further, adding |
| the attribute =-triq(eunit)= will generate EUnit tests for all |
| properties, turning the module into a regular EUnit test suite. |
| |
| We highly recommend letting Triq generate EUnit tests, thus arriving |
| at a demo module like this: |
| |
| #+BEGIN_EXAMPLE erlang |
| -module(triq_demo). |
| -include_lib("triq/include/triq.hrl"). |
| -triq(eunit). |
| prop_append() -> |
| ?FORALL({Xs,Ys},{list(int()),list(int())}, |
| lists:reverse(Xs++Ys) |
| == |
| lists:reverse(Ys) ++ lists:reverse(Xs)). |
| #+END_EXAMPLE |
| |
| Now, all you have to do is run =rebar3 eunit=: |
| |
| #+BEGIN_EXAMPLE sh |
| $ rebar3 eunit -v |
| ===> Verifying dependencies... |
| ===> Compiling triq_demo |
| ===> Performing EUnit tests... |
| ======================== EUnit ======================== |
| file "triq_demo.app" |
| application 'triq_demo' |
| triq_demo:5: append_test_ (module 'triq_demo')...[0.262 s] ok |
| [done in 0.269 s] |
| [done in 0.274 s] |
| ======================================================= |
| Test passed. |
| #+END_EXAMPLE |
| |
| If you use =-triq({eunit, [{runs, N}]})=, then Triq will do =N= runs for each |
| property in the module, which is equivalent to calling =triq:check(Module, N)=. |
| This can be useful to make Triq try more (or less) cases than the default. |
| |
| For advanced features, please consult the API docs. |
| |
| ** Obtaining Triq |
| :PROPERTIES: |
| :CUSTOM_ID: obtaining-triq |
| :END: |
| |
| *** Installation via package manager |
| :PROPERTIES: |
| :CUSTOM_ID: installation-via-package-manager |
| :END: |
| |
| To use =triq=, you can add it as a project dependency and let your |
| package manager of choice handle it: |
| |
| rebar.config: ={deps, [triq]}= |
| |
| erlang.mk: =DEPS = triq= |
| |
| mix.exs: ={:triq, "~> 1.*"}= |
| |
| *** Installation from source into =$ERL_LIBS= |
| :PROPERTIES: |
| :CUSTOM_ID: installation-from-source-into-erl_libs |
| :END: |
| |
| If you want to make =triq= available globally, you can install it from |
| source into your Erlang installation by adding it in one of your |
| =$ERL_LIBS= paths. So, it's either somewhere like |
| =/usr/lib/erlang/lib= or =$HOME/.erl=. |
| |
| You can either download a [[https://gitlab.com/triq/triq/tags][tagged release]] |
| and extract that or clone the [[https://gitlab.com/triq/triq][git repo]] in the |
| target directory. Once that's done, cd into the directory and run =make=. |
| |
| Now, if you start =erl=, you should be able to call functions from the |
| =triq= module. |
| |
| #+BEGIN_EXAMPLE |
| $ erl |
| 1> code:which(triq). |
| "/usr/lib/erlang/lib/triq/ebin/triq.beam" |
| 2> |
| #+END_EXAMPLE |