• Stars
    star
    316
  • Rank 132,587 (Top 3 %)
  • Language
    Elixir
  • License
    MIT License
  • Created about 11 years ago
  • Updated about 6 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Property-based testing library for Elixir (QuickCheck style).

ExCheck Build Status Coverage Status Inline docs

Property-based testing for Elixir (QuickCheck style). It uses Erlang's triq library for underlying checking engine, and ExCheck's modules provide wrapper macros for ExUnit tests.

Installation

First add ExCheck and triq to your project's dependencies in mix.exs.

  defp deps do
    [
      {:excheck, "~> 0.6", only: :test}
    ]
  end

You need to have erlang-eunit installed in order to build triq.

and add the following to test_helper.exs:

ExCheck.start
# ... other helper functions
ExUnit.start

Configuration

You can also specify the amount of tests that you want to run for each property by adding the following to your config.exs:

use Mix.Config
# import "#{Mix.env}.exs"  # If you want to specify different amount for each environment

# And then in this file (or different amount in each config file):
config :excheck, :number_iterations, 200

Usage

The following is an testing example. ExCheck.SampleTest is the testing code for ExCheck.Sample.

Test

defmodule ExCheck.SampleTest do
  use ExUnit.Case, async: false
  use ExCheck
  alias ExCheck.Sample

  property :square do
    for_all x in int(), do: x * x >= 0
  end

  property :implies do
    for_all x in int() do
      #implies skip samples that does not satisfy the predicate. Also, it prints x when skip a sample
      implies x >= 0 do
        x >= 0
      end
    end
  end

  property :such_that do
    for_all {x, y} in such_that({xx, yy} in {int(), int()} when xx < yy) do
      x < y
    end
  end

  property :concat_list do
    for_all {xs, ys} in {list(int()), list(int())} do
      Enum.count(Sample.concat(xs, ys)) == Enum.count(xs) + Enum.count(ys)
    end
  end

  property :push_list do
    for_all {x, y} in {int(), list(int())} do
      result = Sample.push(x, y)
      Enum.at(result, 0) == x and Enum.count(result) == Enum.count(y) + 1
    end
  end

  # specify iteration count for running test
  @tag iterations: 30
  property :square_with_iteration_count do
    for_all x in int(), do: x * x >= 0
  end
end

Code

defmodule ExCheck.Sample do
  @moduledoc """
  Sample logic to be tested by ExCheck (refer to sample_test.exs for tests)
  """

  @doc "concatenate the list"
  def concat(x, y) do
    x ++ y
  end

  @doc "push element in the list"
  def push(x, y) do
    [x|y]
  end
end

Run

 mix test test/sample_test.exs
..................................................................................................................................................................................................................xxx....x.xx..xxx.x.xx.xx..x...x..x..xx.xx..xx.xx.x..x.x..x..x......x.xx............x.x..x..x...xxx..x..x..xx.x..xx.xx.x......x.xxx.xx..xx.x.x.x.xx.x.xx......xx..xxxx..x....xxx.xxxxx.xxxxx..xx...........................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................

Finished in 0.2 seconds (0.1s on load, 0.08s on tests)
948 tests, 0 failures

You can also add the optional flag --trace to get additional output

mix test test/sample_test.exs --trace

ExCheck.SampleTest
  * implies_property........xx.x.x..x..xx.xxx..x.x.x.x..x..x..xx....x.x.xx.xxxxxx..xx...x...xx.x...x.x..xxxxx..x...x......xxxxx.x.x..xxx.x..x.xx..xx..xxxx.x.x..xx.......x..xx.xx...x...x...xxx.xxx.x.xx.xx  * implies_property (14.7ms)
  * square_property........................................................................................................................................................................................  * square_property (4.1ms)
  * push_list_property.....................................................................................................................................................................................  * push_list_property (14.7ms)
  * square_with_iteration_count_property (0.7ms)......................
  * such_that_property.....................................................................................................................................................................................  * such_that_property (4.8ms)
  * concat_list_property...................................................................................................................................................................................  * concat_list_property (25.4ms)


Finished in 0.1 seconds (0.1s on load, 0.06s on tests)
942 tests, 0 failures

There are some more examples at test directory.

Generators

The following generators defined in :triq are imported through "use ExCheck" statement.

  • list/1, tuple/1, int/0, int/1, int/2, byte/0, real/0, sized/1, elements/1, any/0, atom/0, atom/1, choose/2, oneof/1, frequency/1, bool/0, char/0, return/1, vector/2, binary/1, binary/0, non_empty/1, resize/2, non_neg_integer/0, pos_integer/0,
  • unicode_char/0, unicode_string/0, unicode_string/1, unicode_binary/0, unicode_binary/1, unicode_binary/2, unicode_characters/0, unicode_characters/1,
  • bind/2, bindshrink/2, suchthat/2, pick/2, shrink/2, sample/1, sampleshrink/1, seal/1, open/1, peek/1, domain/3, shrink_without_duplicates/1

Notes

  • It's a trial implementation, and has limited functionalities yet.
  • Files in test folder contains some more property examples.

More Repositories

1

excoveralls

Coverage report tool for Elixir with coveralls.io integration.
Elixir
819
star
2

exvcr

HTTP request/response recording library for elixir, inspired by VCR.
Elixir
721
star
3

extwitter

Twitter client library for elixir.
Elixir
411
star
4

exprof

A simple code profiler for Elixir using eprof.
Elixir
178
star
5

exfirebase

An elixir library for accessing the Firebase REST API.
Elixir
88
star
6

oauth2ex

An OAuth 2.0 client library for elixir.
Elixir
57
star
7

kindle-your-highlights

Scrape highlights from kindle.amazon.com
Ruby
48
star
8

exprintf

A printf / sprintf library for Elixir. It works as a wrapper for :io.format.
Elixir
35
star
9

http_server

A simple and self-contained HTTP Server for elixir.
Elixir
12
star
10

spawn_viewer

Trial implementation to visualize process spawning.
Elixir
8
star
11

dynamo_angular

Sample AngularJS scaffolding with dynamo and angular-resource backend.
Elixir
5
star
12

dynamo_firebase

Sample dynamo project for implementing rails-like scaffold page with Firebase backend.
Elixir
4
star
13

ruboto_flickr

Flickr search sample app using Ruboto
Java
4
star
14

chef-cookbook-elixir

Chef cookbook for installing elixir (elixir-lang)
Ruby
4
star
15

big_query

[WIP] Elixir + Google BigQuery Sample
Elixir
4
star
16

dynamo_scaffold

Sample dynamo project for implementing rails-like scaffold page with REST API backend.
Elixir
3
star
17

coverage_sample

sample code for excoveralls
Elixir
3
star
18

chef-cookbook-dynamo

Chef cookbook for deploying dynamo application (elixir-lang)
Ruby
3
star
19

exfuture

A trial implementation of future
Elixir
2
star
20

docker-poxa

Dockerfile for poxa installation.
Shell
2
star
21

mono_timer

Pomodoro-style 25 minutes timer rails-app with notification feature.
Ruby
2
star
22

circle_sample

A test project for CircleCI and Elixir.
Elixir
2
star
23

exrtm

An elixir library for remember the milk API.
Elixir
2
star
24

angularjs_samples

Angular JS sample
JavaScript
1
star
25

excov

testing for coverage
Elixir
1
star
26

sample_future

Sample parallel map program for Future on elixir
Elixir
1
star
27

dynamo_sample

Just a sample for deployment trial
Elixir
1
star
28

pogo

simple tool for starting/stopping erlang nodes via the command line
Elixir
1
star
29

ruboto_spinner

An ruboto example for Android spinner widget.
Java
1
star
30

readline

(experimental) A readline wrapper for Elixir. It's experimental and may not work well.
C
1
star
31

angularjs_sample_rails

angularjs sample with angular-resource and rails backend.
Ruby
1
star
32

ereadline

(WIP) A readline wrapper for Erlang.
C
1
star
33

thought_mapper

[WIP] Thinking assistant tool on comparing options.
Ruby
1
star
34

rtmgo

Remember the milk api client for golang
Go
1
star
35

excoveralls_umbrella

Sample project for excoveralls on umbrella elixir projects.
Elixir
1
star