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:

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 http://hypothesis.works/articles/integrated-shrinking/.
  • 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:

LostKobrakai

LostKobrakai

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

josevalim

josevalim

Creator of Elixir

Since it is being considered for inclusion in Elixir itself then it should be written in Elixir - so it fits with everything else provided by the language and with a matching license. Also note that we decided to build on top of the Stream functionality we provide as part of Elixir, so they work both as data generators and as property testing - they are related but independent. However, the other solutions are more mature and they also provide state checking - something we don’t plan to explore at the moment.

Where Next?

Popular in News Top

Elixir
Release: https://github.com/elixir-lang/elixir/releases/tag/v1.11.2 1. Bug fixes Elixir [Code] Do not crash when getting docs for missi...
New
Elixir
Elixir v1.18 is an impressive release with improvements across the two main efforts happening within the Elixir ecosystem right now: set-...
New
josevalim
The goal of private modules is to define a module that cannot be trivially accessed by other modules where they are not visible to. In t...
New
Elixir
Release: https://github.com/elixir-lang/elixir/releases/tag/v1.11.0 Over the last releases, the Elixir team has been focusing on the com...
New
josevalim
This is a small release with important bug fixes for those using Cover and Dialyzer on Erlang 19. See the release notes for more info: ...
New
josevalim
Release: https://github.com/elixir-lang/elixir/releases/tag/v1.13.3 1. Enhancements Mix [mix format] Supply file and line to formatter ...
New
Elixir
1. Enhancements Elixir [Code] Emit :defmodule tracing event on module definition Mix [Mix] Add Mix.install_project_dir/0 [Mix] Add env...
New
Elixir
Release: https://github.com/elixir-lang/elixir/releases/tag/v1.9.3 This release deprecates the use of URLs on mix archive.install, mix e...
New
jola
Hey everyone! It’s my enormous pleasure to present Hex Diff, an official hex.pm service for generating web-based diffs between package ve...
New
Elixir
Announcement: Elixir v1.13 released - The Elixir programming language 1. Enhancements EEx [EEx] Add :parser_options to EEx functions E...
New

Other popular topics Top

vonH
In asking this question I am more interested about the expressiveness of the language itself and less concerned about the availability of...
New
William
I would like to know that is there any online source for learning Phoenix Framework for building E-Commerce Store? Any advantage on build...
New
JorisKok
I have a server on AWS, and was running a load test using artillery. When looking at the Phoenix dashboard I see the Ports going to 100% ...
New
mgjohns61585
Could someone help me? I'm making my first elixir program, number guessing game. I can't figure out how to convert the user's guess from ...
New
rms.mrcs
Hi, I need to transform a list of numbers into a map where the keys are the indexes and the values are the original values of the list....
New
qwerescape
Is there a way to get the call stack or stack trace at any point in the code? Not from exceptions, but an expression that returns how the...
New
beno
I will often find my self writing things similar to: case some_value do nil -> something() "" -> something() _ -> someth...
New
Nvim
Elixir appears to be a superior language to Python. I don’t see any advantage of Python over Elixir. Are there any?
New
siddhant3030
Hi, I have to write a raw query for one of my project. But till now I have used ecto queries and don’t have much experience writing raw ...
New
vrod
I am using the Starship cross-shell prompt – it seems pretty nice, but I get some errors: [WARN] - (starship::utils): Executing command ...
New

We're in Beta

About us Mission Statement