CI License Version Docs

MoreStreamData

MoreStreamData is a small collection of extra generators for StreamData, Elixir's most widely used property-based testing library.

Use it when you need generators for common application data: IP addresses, domains, URLs, email addresses, decimals, durations, datetimes, bounded integers and floats, random samples, or strings that match a regular expression.

Install

Add more_stream_data to your mix.exs:

def deps do
  [
    {:more_stream_data, "~> 0.8", only: :test}
  ]
end

Usage

MoreStreamData returns regular StreamData.t() generators, so it works with ExUnitProperties and with StreamData combinators.

defmodule AccountTest do
  use ExUnit.Case
  use ExUnitProperties

  import MoreStreamData

  property "accepts valid signup emails" do
    check all email <- email() do
      assert MyApp.Accounts.valid_email?(email)
    end
  end
end

Generate Strings From a Regex

Use from_regex/2 when your production code validates with a regex and your test should exercise matching strings.

property "accepts valid product codes" do
  regex = ~r/^[A-Z]{3}-\d{4}$/

  check all code <- MoreStreamData.from_regex(regex) do
    assert Regex.match?(regex, code)
  end
end

Network Values

ip_address/1 generates IPv4 and IPv6 strings. Without options it includes random addresses and IANA special ranges for better edge-case coverage.

check all ip <- MoreStreamData.ip_address(version: 4) do
  assert {:ok, _} = :inet.parse_address(String.to_charlist(ip))
end

Constrain generation to a CIDR range with :network:

check all ip <- MoreStreamData.ip_address(network: "10.0.0.0/8") do
  assert String.starts_with?(ip, "10.")
end

Generate Web Identifiers

Use domain/1, url/0, and email/1 for practical web-facing values.

check all domain <- MoreStreamData.domain(max_length: 80),
          email <- MoreStreamData.email(domains: StreamData.constant(domain)) do
  assert String.ends_with?(email, "@" <> domain)
end

email/1 intentionally targets common provider-compatible addresses rather than the full RFC-5322 grammar.

Extend Existing StreamData Tests

Import MoreStreamData beside ExUnitProperties:

defmodule BillingTest do
  use ExUnit.Case
  use ExUnitProperties

  import MoreStreamData

  property "invoice totals are never negative" do
    check all amount <- decimal(min: Decimal.new("0"), allow_nan?: false) do
      assert Decimal.compare(amount, 0) in [:eq, :gt]
    end
  end
end

Because each function returns a StreamData generator, you can compose it with your own domain-specific generators:

def user_gen do
  StreamData.fixed_map(%{
    email: MoreStreamData.email(),
    homepage: MoreStreamData.url(),
    last_seen_at: MoreStreamData.datetime(max: DateTime.utc_now())
  })
end

Refer to the Documentation for a list of all the generators with their corresponding options an examples.

Regex Support

from_regex/2 is useful for many validation-style regexes, especially anchored ASCII patterns. Supported features include:

  • literals, concatenation, alternation, groups, character classes, ranges, and common repetition operators
  • \d, \D, \w, \W, \s, \S, blank and vertical-space classes
  • anchors such as ^, $, \A, and \z
  • case-insensitive, extended, dotall, multiline, firstline, ungreedy, and export modifiers where they affect generated strings
  • negative lookahead and negative lookbehind
  • hex escapes such as \xHH and \x{HHH}

Some regex features are not implemented yet, including word boundaries, positive lookahead, positive lookbehind, Unicode mode, and newline mode settings such as (*ANYCRLF).

The project aims to port useful strategies from Python Hypothesis to Elixir ecosystem.