whatyouhide / stream_data

Data generation and property-based testing for Elixir. 🔮

Home Page:https://hexdocs.pm/stream_data

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Is this a bug or am I using list_of wrong?

dewyze opened this issue · comments

With the following example:

property "last list_of doesn’t work" do
  check all list1 <- list_of(integer()),
            list2 <- list_of(integer()), initial_size: 5 do
    assert false
  end
end

list1 will have sizes ranging fro 0 to 5, but list2 is always empty. This seems to always be the case if list_of is the last clause. I.e. if I add a list3, then list2 is populated, but list3 is empty.

It seems to be a bug. I'll take a look, thanks for reporting. :)

Hey @dewyze, I am looking into this and I cannot reproduce it. This is the code I'm using:

defmodule RegressionTest do
  use ExUnit.Case
  use ExUnitProperties

  property "regression #128" do
    check all list1 <- list_of(integer()),
              list2 <- list_of(integer()),
              initial_size: 5,
              max_shrinking_steps: 0 do
      IO.inspect(list1, label: "list1")
      IO.inspect(list2, label: "list2")
      assert false
    end
  end
end

Using this code, the lists are always populated very randomly with list2 often being larger than an empty list. Can you provide the code you used to verify that list2 is always empty?

I am using this and it never passes.

property "regression #128" do
  check all list1 <- list_of(integer()),
            list2 <- list_of(integer()),
            initial_size: 5,
            max_shrinking_steps: 0 do
    assert length(list2) > 0
  end
end

Here is some more system info:

# mix.exs
defp deps do                                     
  [                                              
    {:stream_data, "~> 0.1", only: [:dev, :test]}
  ]
endcat mix.lock 
%{
  "stream_data": {:hex, :stream_data, "0.4.3", "62aafd870caff0849a5057a7ec270fad0eb86889f4d433b937d996de99e3db25", [:mix], [], "hexpm"},
}elixir -v
Erlang/OTP 22 [erts-10.4] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [hipe]

Elixir 1.8.2 (compiled with Erlang/OTP 22)

Here is a repo with my exact setup, fails every time I run mix test: https://github.com/dewyze/stream_data_test

The example I pasted before I realize is not a good example, because sometimes the list will be empty, and often it would say "failed after 19 runs" or something. I pushed a better example to the repo:

property "regression #128" do
  check all list1 <- list_of(integer()),
            list2 <- list_of(integer()),
            initial_size: 100,
            max_shrinking_steps: 0 do
    assert false
  end
end

When that fails, at least on my machine, the results always look something like this:

1) property regression #128 (StreamDataTestTest)
   test/stream_data_test_test.exs:5
   Failed with generated values (after 0 successful runs):

       * Clause:    list1 <- list_of(integer())
         Generated: [-61, 91, -51, -66, 11, 0, -71, -5, -59, 27, 54, 62, 74, 1, 56, 79, 28, 18, 55, -10, 90, 32, -39, 58, 99, 14, -40, 29, -28, 66, 33, -12, -87, 91, -2, -15, -90, -11, -43, -68, -55, -92, -51, 97, 58, -5, 50, 64, 64, 84, ...]

       * Clause:    list2 <- list_of(integer())
         Generated: []

   Expected truthy, got false
   code: assert false
   stacktrace:
     test/stream_data_test_test.exs:10: anonymous fn/1 in StreamDataTestTest."property regression #128"/1
     (stream_data) lib/stream_data.ex:2114: StreamData.shrink_failure/6
     (stream_data) lib/stream_data.ex:2078: StreamData.check_all/7
     test/stream_data_test_test.exs:6: (test)

Is it possible that just on the first run, the last list_of always produced an empty list first?

Ok I know what was happening. There was a bug until earlier today where max_shrinking_steps: 0 wouldn't work (see ebf5b2a). This meant that when you did assert false and the test failed, we shrunk the generated inputs and stopped when list2 was completely shrunk to [] (whether this behaviour is correct is out of scope and very hard to fix anyways). The generated values that are printed are always shrunk, not the actually generated ones. Let me know if you have questions, but the morale is that it was never a bug and your reproducing repo only behaves like that because of the bug that's fixed in master.

Thanks for the clarification!