parroty / excheck

Property-based testing library for Elixir (QuickCheck style).
MIT License
316 stars 26 forks source link

Unclear how to ensure x is not in ys #39

Open jeremytregunna opened 7 years ago

jeremytregunna commented 7 years ago

I have a property that takes a string and a list of strings, and part of this property is that the string is not in the list of strings. I can't seem to find a predicate for this, is there some way of accomplishing this in a single property?

Basically what I'm after is something like:

for_all {x, ys} in such_that({xx, yys} in {binary(), list(binary())} when not_in(xx, yys)) do
  ...
end
devstopfix commented 5 years ago

You can use the bind function to modify generated values:

defmodule NotInTest do
  use ExUnit.Case
  use ExCheck

  def gen_x_yys do
    [:triq_dom.int(), list(:triq_dom.int())]
    |> bind(fn [x, ys] ->
      {x, Enum.filter(ys, fn y -> x != y end)}
    end)
  end

  property :not_in do
    for_all {x, ys} in gen_x_yys() do
      assert Enum.member?(ys, x) == false
    end
  end

end

A sample of the generator:

  {-4, [-7, 0, 4]},
  {-2, [7, 0, 8, 0, -3, -4, 7, -6, -11, 4, -11, 5]},
  {-9, [11, 10, 0, -3, 1, 7, 11, -3, 7, 13, -1, -3, -4, -2]},
  {-5, [1, -2, 3, 7, 7, 7, 4, -1, 1, -9, -9, -7, -3, 9, -7]},
  {-2, [1]},
  {-1, [10, -13, -5, -10]},
  {-1, [10, 5]}
devstopfix commented 5 years ago
property :not_in_suchthat do
    for_all {x, ys} in such_that({x_, ys_} in {int(), list(int())} when !Enum.member?(ys_, x_)) do
      assert Enum.member?(ys, x) == false
    end
  end
jeremytregunna commented 5 years ago

cool thanks that helps