#+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. If you use erlang.mk, you will typically want to use [[https://erlang.mk/guide/triq.html][the built-in Triq plugin]] to check properties. Otherwise 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