• Stars
    star
    843
  • Rank 54,052 (Top 2 %)
  • Language
    Elixir
  • Created over 7 years ago
  • Updated 8 months ago

Reviews

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

Repository Details

Data generation and property-based testing for Elixir. ๐Ÿ”ฎ

StreamData

hex.pm badge CI Coverage Status

StreamData is an Elixir library for data generation and property-based testing.

Read the announcement on the Elixir website.

Installation

Add stream_data to your list of dependencies:

defp deps() do
  [{:stream_data, "~> 0.5", only: :test}]
end

and run mix deps.get. StreamData is usually added only to the :test environment since it's used in tests and test data generation. To also import StreamData's formatter configuration, add the :dev environment as well as :test for stream_data and add :stream_data to your .formatter.exs:

[
  import_deps: [:stream_data]
]

Usage

The documentation is available online.

StreamData is made of two main components: data generation and property-based testing. The StreamData module provides tools to work with data generation. The ExUnitProperties module takes care of the property-based testing functionality.

Data generation

All data generation functionality is provided in the StreamData module. StreamData provides "generators" and functions to combine those generators and create new ones. Since generators implement the Enumerable protocol, it's easy to use them as infinite streams of data:

StreamData.integer() |> Stream.map(&abs/1) |> Enum.take(3)
#=> [1, 0, 2]

StreamData provides all the necessary tools to create arbitrarily complex custom generators:

require ExUnitProperties

domains = [
  "gmail.com",
  "hotmail.com",
  "yahoo.com",
]

email_generator =
  ExUnitProperties.gen all name <- StreamData.string(:alphanumeric),
                           name != "",
                           domain <- StreamData.member_of(domains) do
    name <> "@" <> domain
  end

Enum.take(StreamData.resize(email_generator, 20), 2)
#=> ["[email protected]", "[email protected]"]

Property testing

Property testing aims at randomizing test data in order to make tests more robust. Instead of writing a bunch of inputs and expected outputs by hand, with property-based testing we write a property of our code that should hold for a set of data, and then we generate data in this set, in attempt to falsify that property. To generate this data, we can use the above-mentioned StreamData module.

use ExUnitProperties

property "bin1 <> bin2 always starts with bin1" do
  check all bin1 <- binary(),
            bin2 <- binary() do
    assert String.starts_with?(bin1 <> bin2, bin1)
  end
end

To know more about property-based testing, read the ExUnitProperties documentation. Another great resource about property-based testing in Erlang (but with most ideas that apply to Elixir as well) is Fred Hebert's website propertesting.com.

The property-based testing side of this library is heavily inspired by the original QuickCheck paper (which targeted Haskell) as well as Clojure's take on property-based testing, test.check.

Differences from other property-based testing frameworks

There are a handful of property-based testing frameworks for the BEAM ecosystem (Erlang, Elixir, and so on). For Elixir, the main alternative to StreamData is PropCheck. PropCheck is a wrapper around PropEr, which is a property-based testing framework for Erlang. There are a few fundamental differences between StreamData and PropEr. They are listed below to help you choose between the two.

PropEr (via PropCheck):

  • It provides stateful property-based testing. If you need to test a system with state by building a model of the system to test against, you'll have to go with PropCheck since StreamData doesn't support this yet.

  • It can store counter-examples: StreamData doesn't support storing counter-examples in a file (you have to reuse the seed that caused the failure in order to reproduce it).

StreamData:

  • Provides functionality for generating data as the base for property-based testing. StreamData generators can be used outside of property-based testing as normal Elixir streams that produce random data.

  • It is native to Elixir. It's written entirely in Elixir and has an idiomatic Elixir API (for example, all generators are Elixir enumerables).

License

Copyright 2017 Andrea Leopardi and Josรฉ Valim

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

  http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

More Repositories

1

vim-gotham

Code never sleeps in Gotham City. ๐ŸŒƒ
Vim Script
1,215
star
2

redix

Fast, pipelined, resilient Redis driver for Elixir. ๐Ÿ›
Elixir
1,062
star
3

corsica

Elixir library for dealing with CORS requests. ๐Ÿ–
Elixir
513
star
4

xandra

Fast, simple, and robust Cassandra/ScyllaDB driver for Elixir.
Elixir
392
star
5

gotham-contrib

Ports of the Gotham colorscheme for common editors and terminal emulators ๐ŸŒƒ
Shell
242
star
6

guide_async_processing_in_elixir

A Livebook-based guide to async processing in Elixir. ๐Ÿƒ
127
star
7

vim-lengthmatters

Highlight the flooding part of an overly long line ๐Ÿ“
Vim Script
82
star
8

short_maps

โš ๏ธRetiredโš ๏ธ library that provided a ~m sigil for ES6-like map destructuring in Elixir.
Elixir
76
star
9

vim-textobj-xmlattr

A vim text object for XML/HTML attributes.
Vim Script
74
star
10

saul

Data validation and conformation library for Elixir.
Elixir
67
star
11

redix_pubsub

Deprecated Redis Pub/Sub client for Elixir. Now built-in into Redix.
Elixir
64
star
12

protohackers_in_elixir

Code for a video series I'm making on solving protohackers.com challenges in Elixir. ๐Ÿ“บ
Elixir
55
star
13

plug_heartbeat

A plug for responding to heartbeat requests.
Elixir
36
star
14

nimble_lz4

LZ4 compression for Elixir using Rust NIFs. ๐Ÿ—œ
Elixir
25
star
15

vim-textobj-erb

A Vim text object for ERB blocks.
Vim Script
20
star
16

dotfiles

My dotfiles ๐Ÿฅ‘
Shell
19
star
17

from_zero_to_hero_with_elixir

Elixir 101 training. Done by @ericmj and me.
Elixir
19
star
18

convertat

An Elixir library for converting from and to arbitrary bases.
Elixir
17
star
19

workshop-parallel-computation-with-elixir

Elixir
16
star
20

emacs.d

My Emacs config. โš™๏ธ (buuuuut I don't use Emacs anymore)
Emacs Lisp
15
star
21

training_otp_in_elixir

"OTP in Elixir" training done at Elixir Club Kyiv in ~2020. ๐Ÿ‘ฉโ€๐Ÿซ
Elixir
12
star
22

testing_aws_in_elixir

Support code for the blog post "Testing AWS in Elixir" ๐Ÿ•โ€๐Ÿฆบ
Elixir
12
star
23

small_ints

varint and ZigZag encoding/decoding for Erlang
Erlang
11
star
24

ecto_unix_timestamp

Ecto type for datetimes stored and cast as Unix timestamps. ๐Ÿ•ฐ๏ธ
Elixir
11
star
25

bases

A Ruby gem to convert from and to any base.
Ruby
10
star
26

concurrent_data_processing_in_elixir

Material for the "Concurrent Data Processing in Elixir" training.
10
star
27

connected-web-with-elixir-and-phoenix

Code for my Elixir/Phoenix workshop (currently at FunctionalConf India 2019).
Elixir
5
star
28

whatyouhide.github.io

My personal website. ๐Ÿ‘จโ€๐Ÿ’ป
SCSS
4
star
29

.vim

Vim configuration. Left to oblivion. โšฐ๏ธ
Vim Script
3
star
30

.atom

Atom configuration โš›๏ธ (buuut I don't use Atom anymore)
CSS
2
star
31

rack-domain

Rack middleware for dispatching to Rack apps based on the request domain.
Ruby
2
star
32

vim-tmux-syntax

Vim syntax for tmux configuration files.
Vim Script
2
star
33

advent_of_code_2022

Solutions to Advent of Code 2022, in Rust. ๐Ÿฆ€
Rust
1
star
34

intro-to-git-ingegneria

Git talk @ Univaq.
CSS
1
star
35

whatyouhide

Special repository for my GitHub homepage. ๐Ÿ›‹๏ธ
1
star