whatyouhide

whatyouhide

Elixir Core Team

StreamData: data generation and property testing for Elixir

Hello folks,

I am super excited to finally share what I’ve been working on in the last few months: StreamData, an Elixir library for data generation and property testing. StreamData is a candidate to be included in Elixir itself but we wanted to start off with a library to first give people the chance to give it a try and to get the interface right (we did something similar with GenStage, which ended up remaining outside of Elixir core).

StreamData is still in its infancy but it’s ready to be tested by a wider audience (let’s say it’s exiting alpha and entering beta), so I invite the Elixir community to give it a try. Open issues, send PRs, and spread the word!

Andrea

Edit - I just published a blog post that talks about the inner workings of this library for those of you who might be interested:

First Post!

josevalim

josevalim

Creator of Elixir

Most Liked

whatyouhide

whatyouhide

Elixir Core Team

I just published:

which is a post where I describe in detail the inner workings of StreamData for those of you who might be interested. :slight_smile:

whatyouhide

whatyouhide

Elixir Core Team

Thanks so much for all the links, they were very interesting reads! :slight_smile: The Hypothesis approach is indeed both elegant and powerful but as far as I can tell, it’s not more powerful than the StreamData approach (which as I mention in the README is really Clojure’s test.check approach, credit where credit is due :smiley:).

One thing to note: StreamData is not type-based in any way. It just happens that I defined a bunch of type-ish generators because they are useful :slight_smile:.

I’ll write a blog post about it because it’s very interesting IMO, but the gist is:

  • all StreamData generators take seed as the argument and can use that seed to produce whatever they want. This is analogous to the randomness of the byte stream in Hypothesis.
  • a StreamData generator (which is substantially a function) generates a “lazy tree” when generating a value: a lazy tree is basically a tree where the root is realized (that is, eager, not lazy) and the children are a lazy stream of lazy trees. In StreamData, the root is the generated values and the child subtrees are the shrinks of that value. An easy example is integers: int/0 returns a tree where the root might be 4, and the children might be 0, 2, 3 and 2 might have the child 1 and so on. Shrinking becomes a matter of a somewhat fancy depth-first search in this tree. This also solves exactly the problem that the author of Hypothesis highlights in Hypothesis.
  • The seed that generators accept as argument can be “split”, meaning we can get two seeds from one seed in a deterministic way. So generators just split seeds when they need to pass down the seed. Since everything is deterministic, to “replay” a run you can just pass the same seed (this is already done to integrate with ExUnit where we use ExUnit’s seed).

Last but not least, binary/0 does not have any problem in shrinking both bytes and the length of the binary. There is actually more work done in order to make it shrink like it does today. Whether it’s the right API or not, it’s a different discussion but I’m very much interested in it so please open up an issue in the StreamData repo and we can discuss with everyone else as well :slight_smile:

Hope this made it somehow clearer, as I said I’ll try to put together a blog post because this is interesting and I spent the last months grokking it so I’d be very happy to share the insights!

whatyouhide

whatyouhide

Elixir Core Team

Sorry I forgot to answer the original 3 questions:

  1. StreamData is pure Elixir, shrinks like Hypothesis/test.check (so the “good” way), it has a chance of getting merged into Elixir core, is integrated with ExUnit
  2. There are many functions in StreamData to create custom generators. The basics are bind/2, map/2, filter/3, but there’s also StreamData.gen all which is syntactic sugar to create really easy to read generators.
  3. The values are completely random but the testing is driven by a “generation size” (mentioned in the docs) which guarantees we start with smaller values which makes the chance of an empty list very very high

Let me know if you have more questions :slight_smile:

Last Post!

LostKobrakai

LostKobrakai

José announced in his Elixir Conf keynote that it’ll stay a separate project and not being included into the core.

Where Next?

Popular in News Top

josevalim
Official announcement: Elixir v1.6 released - The Elixir programming language Thanks everyone who gave the release candidate a try and g...
New
josevalim
Hi everyone, We have just released v1.7.0-rc.0. The CHANGELOG and precompiled files are here: Release v1.7.0-rc.0 · elixir-lang/elixir ...
New
josevalim
moderators note: A conclusion by @josevalim has been drawn in Proposal: Private modules (general discussion) - #143 by josevalim While...
320 14557 157
New
Elixir
Release: Release v1.9.0 · elixir-lang/elixir · GitHub Releases The main feature in Elixir v1.9 is the addition of releases. A release is...
New
Elixir
Release: Release v1.13.0-rc.0 · elixir-lang/elixir · GitHub The focus behind Elixir v1.13 has been on tooling, mainly tooling related to...
New
Elixir
This release requires Erlang/OTP 24 and later. Elixir v1.15 is a smaller release with focused improvements on compilation and boot time...
New
Elixir
1. Enhancements Elixir [Code] Add :emit_warnings for Code.string_to_quoted/2 [File] Add :offset option to File.stream!/2 [Kernel] Auto i...
New

Other popular topics Top

jononomo
I am trying to figure out how Mix knows whether the environment is test, dev, or prod – where is this set? Thanks.
New
chrismccord
Phoenix 1.4.0 released Phoenix 1.4 is out! This release ships with exciting new features, most notably with HTTP2 support, improved deve...
688 31525 112
New
sen
Hi All, I set a environment variables in dev.exs , like below code. when i start server, how can i set the ${enable} value? thanks. d...
New
AstonJ
Seen any cool LiveView demos, sample apps or examples? Please post them here! :003:
New
bsollish-terakeet
Credo is smart enough to check for (something like) this: assert length(the_list) == 0 with this response: Checking if an enum is empt...
New
jason.o
In the code below, if the create action is not set to accept “extra_key” as an input, it errors out with a message shown above. Is there ...
New

We're in Beta

About us Mission Statement