### StreamData.list_of/StreamData.bind_filter Example Source: https://hexdocs.pm/stream_data/StreamData.html Example demonstrating how to create a generator for two-element tuples using `StreamData.list_of` and `StreamData.bind_filter`. ```APIDOC ## StreamData.list_of / StreamData.bind_filter Example ### Description This example shows how to create a generator that produces two-element tuples. The first element is a list of integers with an even number of members, and the second element is a member of that list. It utilizes `StreamData.list_of` to generate lists and `StreamData.bind_filter` to conditionally process lists based on their length. ### Method N/A (Illustrative Example) ### Endpoint N/A ### Parameters N/A ### Request Example ```elixir require Integer list_data = StreamData.list_of(StreamData.integer(), min_length: 1) data = StreamData.bind_filter(list_data, fn list when Integer.is_even(length(list)) -> inner_data = StreamData.bind(StreamData.member_of(list), fn member -> StreamData.constant({list, member}) end) {:cont, inner_data} _odd_list -> :skip end) Enum.at(data, 0) ``` ### Response #### Success Response (Example Output) ```elixir #=> {[-6, -7, -4, 5, -9, 8, 7, -9], 5} ``` ``` -------------------------------- ### StreamData.list_of/1 with bind_filter Example Source: https://hexdocs.pm/stream_data/index.html An example demonstrating how to create a generator that produces two-element tuples. The first element is a list of integers with an even number of members, and the second element is a member of that list. This is achieved using `StreamData.list_of/1` and `StreamData.bind_filter/2`. ```APIDOC ## StreamData.list_of/1 with bind_filter Example ### Description This example demonstrates creating a generator that yields two-element tuples. The first element of the tuple is a list of integers with an even length, and the second element is a member of that list. It utilizes `StreamData.list_of/1` to generate lists and `StreamData.bind_filter/2` to conditionally process these lists. ### Method N/A (Illustrative Example) ### Endpoint N/A ### Parameters N/A ### Request Example ```elixir require Integer list_data = StreamData.list_of(StreamData.integer(), min_length: 1) data = StreamData.bind_filter(list_data, fn list when Integer.is_even(length(list)) -> inner_data = StreamData.bind(StreamData.member_of(list), fn member -> StreamData.constant({list, member}) end) {:cont, inner_data} _odd_list -> :skip end) Enum.at(data, 0) ``` ### Response #### Success Response (Example Output) - **tuple** (tuple) - A tuple where the first element is a list of integers with even length, and the second element is a member of that list. #### Response Example ```elixir #=> {[-6, -7, -4, 5, -9, 8, 7, -9], 5} ``` ### Shrinking Behavior Values that are skipped by the filter are not used for shrinking, similar to how `filter/3` works. ``` -------------------------------- ### Generate binary trees Source: https://hexdocs.pm/stream_data/index.html Example of generating binary trees using a custom struct and integer leaves. ```elixir tree_data = StreamData.tree(StreamData.integer(), fn child_data -> StreamData.map({child_data, child_data}, fn {left, right} -> %Branch{left: left, right: right} end) end) Enum.at(StreamData.resize(tree_data, 10), 0) #=> %Branch{left: %Branch{left: 4, right: -1}, right: -2} ``` -------------------------------- ### Test starts_with?/2 manually Source: https://hexdocs.pm/stream_data/ExUnitProperties.html A traditional unit test example for the starts_with?/2 function using manual input cases. ```elixir test "starts_with?/2" do assert starts_with?("foo", "f") refute starts_with?("foo", "b") assert starts_with?("foo", "") assert starts_with?("", "") refute starts_with?("", "something") end ``` -------------------------------- ### Use check all in doctests Source: https://hexdocs.pm/stream_data/ExUnitProperties.html Integrate property-based testing into documentation examples by ensuring the module uses ExUnitProperties. ```elixir @doc """ Tells if a term is an integer. iex> check all i <- integer() do ...> assert int?(i) ...> end :ok """ def int?(i), do: is_integer(i) ``` -------------------------------- ### Generate unique lists Source: https://hexdocs.pm/stream_data/index.html Example of generating a list of unique integers. ```elixir data = StreamData.uniq_list_of(StreamData.integer()) Enum.take(data, 3) #=> [[1], [], [2, 3, 1]] ``` -------------------------------- ### Generate tuples Source: https://hexdocs.pm/stream_data/index.html Example of generating tuples with specific element types. ```elixir data = StreamData.tuple({StreamData.integer(), StreamData.binary()}) Enum.take(data, 3) #=> [{-1, <<170>>}, {1, "<"}, {1, ""}] ``` -------------------------------- ### Test starts_with?/2 with property-based testing Source: https://hexdocs.pm/stream_data/ExUnitProperties.html A property-based test using the check/3 macro to verify that the concatenation of two binaries always starts with the first binary. ```elixir test "starts_with?/2" do check all a <- StreamData.binary(), b <- StreamData.binary() do assert starts_with?(a <> b, a) end end ``` -------------------------------- ### Generate UTF-8 Codepoints Source: https://hexdocs.pm/stream_data/StreamData.html Shows how to generate UTF-8 codepoints using the `codepoint/1` function. Examples include generating random codepoints and specifically ASCII codepoints, demonstrating the output format for each. ```elixir Enum.take(StreamData.codepoint(), 3) #=> [889941, 349615, 1060099] ``` ```elixir Enum.take(StreamData.codepoint(:ascii), 3) #=> ~c"Kk:" ``` -------------------------------- ### Generate nested lists Source: https://hexdocs.pm/stream_data/index.html Example of generating nested lists using the tree generator. ```elixir data = StreamData.tree(StreamData.integer(), &StreamData.list_of/1) Enum.at(StreamData.resize(data, 10), 0) #=> [[], '\t', '\a', [1, 2], -3, [-7, [10]]] ``` -------------------------------- ### Generate dates with StreamData Source: https://hexdocs.pm/stream_data/StreamData.html Examples of generating dates using various constraints like origin, range, or date ranges. ```elixir Enum.take(StreamData.date(), 3) #=> [~D[2023-11-24], ~D[2023-11-25], ~D[2023-11-23]] Enum.take(StreamData.date(origin: ~D[2025-09-01]), 3) #=> [~D[2025-08-31], ~D[2025-08-31], ~D[2025-09-04]] Enum.take(StreamData.date(min: ~D[2025-01-01], max: ~D[2025-01-31]), 3) #=> [~D[2025-01-27], ~D[2025-01-21], ~D[2025-01-16]] Enum.take(StreamData.date(Date.range(~D[2025-01-01], ~D[2025-01-31])), 3) #=> [~D[2025-01-29], ~D[2025-01-03], ~D[2025-01-15]] ``` -------------------------------- ### Generate JSON-like structures Source: https://hexdocs.pm/stream_data/index.html Example of generating complex data structures representing a JSON document. ```elixir scalar_generator = StreamData.one_of([ StreamData.integer(), StreamData.boolean(), StreamData.string(:ascii), nil ]) json_generator = StreamData.tree(scalar_generator, fn nested_generator -> StreamData.one_of([ StreamData.list_of(nested_generator), StreamData.map_of(StreamData.string(:ascii, min_length: 1), nested_generator) ]) end) Enum.at(StreamData.resize(json_generator, 10), 0) #=> [%{"#" => "5"}, true, %{"4|B" => nil, "7" => true, "yt(3y" => 4}, [[false]]] ``` -------------------------------- ### Generate JSON-like Structures with StreamData.tree Source: https://hexdocs.pm/stream_data/StreamData.html This example demonstrates generating data structures resembling JSON by combining `StreamData.tree/2` with generators for scalars, lists, and maps. It uses `StreamData.one_of/1` to choose between different structure types. ```elixir scalar_generator = StreamData.one_of([ StreamData.integer(), StreamData.boolean(), StreamData.string(:ascii), nil ]) json_generator = StreamData.tree(scalar_generator, fn nested_generator -> StreamData.one_of([ StreamData.list_of(nested_generator), StreamData.map_of(StreamData.string(:ascii, min_length: 1), nested_generator) ]) end) Enum.at(StreamData.resize(json_generator, 10), 0) ``` -------------------------------- ### Test properties with custom generators Source: https://hexdocs.pm/stream_data/ExUnitProperties.html Example of using custom generators within an ExUnit property test. ```elixir describe "noon?/1" do test "returns true for noon" do assert noon?(~T[12:00:00]) == true end property "returns false for other times" do check all time <- non_noon_generator() do assert noon?(time) == false end end end ``` -------------------------------- ### Create an unshrinkable byte generator Source: https://hexdocs.pm/stream_data/index.html Use `unshrinkable/1` to create a generator for bytes (0-255) that will not shrink. This example demonstrates its usage with `integer/1` and `Enum.take/2`. ```elixir byte = StreamData.unshrinkable(StreamData.integer(0..255)) Enum.take(byte, 3) #=> [190, 181, 178] ``` -------------------------------- ### Generating Custom Structs with StreamData Source: https://hexdocs.pm/stream_data/ExUnitProperties.html Demonstrates how to create custom generators for Elixir structs, like `%Time{}`, to be used in property-based tests. This example shows generating valid times that are not noon. ```APIDOC ## Generating Custom Structs This example shows how to generate `%Time{}` structs for testing a `noon?/1` function. ### Generator for Non-Noon Times ```elixir defp non_noon_generator do gen all time <- valid_time_generator(), time != ~T[12:00:00] do time end end defp valid_time_generator do gen all hour <- StreamData.integer(0..23), minute <- StreamData.integer(0..59), second <- StreamData.integer(0..59) do Time.new!(hour, minute, second) end end ``` ### Property Test Example ```elixir describe "noon?/1" do test "returns true for noon" do assert noon?(~T[12:00:00]) == true end property "returns false for other times" do check all time <- non_noon_generator() do assert noon?(time) == false end end end ``` ``` -------------------------------- ### Generate UTF-8 codepoints Source: https://hexdocs.pm/stream_data/index.html Defines the specification for generating various types of UTF-8 codepoints and provides usage examples. ```elixir @spec codepoint(:ascii | :alphanumeric | :printable | :utf8) :: t(char()) ``` ```elixir Enum.take(StreamData.codepoint(), 3) #=> [889941, 349615, 1060099] Enum.take(StreamData.codepoint(:ascii), 3) #=> ~c"Kk:" ``` -------------------------------- ### Take Sample Binaries Source: https://hexdocs.pm/stream_data/index.html Demonstrates taking a sample of three binaries generated by StreamData.binary/0. ```elixir Enum.take(StreamData.binary(), 3) #=> [<<1>>, "", "@Q"] ``` -------------------------------- ### Verify properties with check_all/3 Source: https://hexdocs.pm/stream_data/index.html Demonstrates using check_all/3 to verify a property, showing how it handles failures and shrinks values. ```elixir options = [initial_seed: :os.timestamp()] {:error, metadata} = StreamData.check_all(StreamData.integer(), options, fn int -> if int == 0 or rem(int, 11) != 0 do {:ok, nil} else {:error, Integer.to_string(int)} end end) metadata.nodes_visited #=> 7 metadata.original_failure #=> 22 metadata.shrunk_failure #=> 11 ``` -------------------------------- ### ExUnit Properties: `__using__/1` Macro Source: https://hexdocs.pm/stream_data/ExUnitProperties.html The `__using__/1` macro is used to set up an `ExUnit.Case` module for property-based testing with StreamData. ```APIDOC ## `__using__/1` Macro Sets up an `ExUnit.Case` module for property-based testing. ### Usage ```elixir use ExUnit.Case, async: true use StreamData ``` This macro is typically used at the top of a test file to enable StreamData's property testing features. ``` -------------------------------- ### binary/1 Source: https://hexdocs.pm/stream_data/StreamData.html Generates binaries with optional length constraints. ```APIDOC ## binary(options) ### Description Generates binaries. The length of the generated binaries is limited by the generation size. ### Parameters #### Request Body - **options** (keyword) - Optional - Configuration options including :length, :min_length, and :max_length. ``` -------------------------------- ### ExUnit Properties: `property/1` and `property/3` Macros Source: https://hexdocs.pm/stream_data/ExUnitProperties.html Macros for defining property tests, either as a placeholder or with specific context and contents. ```APIDOC ## `property/1` and `property/3` Macros Defines a property test. ### `property/1` (Message) Defines a not-implemented property test with a string message. ```elixir property "this property is not yet implemented" ``` ### `property/3` (Message, Context, Contents) Defines a property and imports property-testing facilities in the body. ```elixir property "ensures data integrity", quote do # Property testing code here check all data <- StreamData.list(StreamData.integer()) do assert is_list(data) end end ``` The `property/3` macro allows for more structured definition of properties, including a context and the actual test implementation. ``` -------------------------------- ### Filter generator output Source: https://hexdocs.pm/stream_data/StreamData.html Specifies the filter function signature and provides examples of efficient vs inefficient generator filtering. ```elixir @spec filter(t(a), (a -> as_boolean(term())), non_neg_integer()) :: t(a) when a: term() ``` ```elixir def even_integers() do StreamData.filter(StreamData.integer(), &Integer.is_even/1) end ``` ```elixir def even_integers() do StreamData.map(StreamData.integer(), &(&1 * 2)) end ``` -------------------------------- ### Generate lists with options Source: https://hexdocs.pm/stream_data/index.html Use list_of/2 to generate lists with control over length using :length, :min_length, or :max_length options. Shrinking respects length constraints. ```elixir @spec list_of( t(a), keyword() ) :: t([a]) when a: term() ``` ```elixir Enum.take(StreamData.list_of(StreamData.integer(), length: 3), 3) ``` ```elixir Enum.take(StreamData.list_of(StreamData.integer(), max_length: 1), 3) ``` -------------------------------- ### string(kind_or_codepoints, options) Source: https://hexdocs.pm/stream_data/StreamData.html Generates a string of the given kind or from the given characters. ```APIDOC ## string(kind_or_codepoints, options) ### Description Generates a string of the given kind or from the given characters. ### Parameters #### Arguments - **kind_or_codepoints** (atom | range | list) - Required - The type of string or character set to generate. - **options** (list) - Optional - Configuration options for the generator. ``` -------------------------------- ### string(kind_or_codepoints, options) Source: https://hexdocs.pm/stream_data/index.html Generates a string of the given kind or from the given characters. ```APIDOC ## string(kind_or_codepoints, options) ### Description Generates a string of the given kind or from the given characters. ### Parameters - **kind_or_codepoints** (atom | range | list) - Required - The type of string or character set to generate. - **options** (list) - Optional - Additional configuration options. ``` -------------------------------- ### Run property tests with check macro Source: https://hexdocs.pm/stream_data/ExUnitProperties.html Demonstrates the use of the check macro to define property-based test clauses and assertions. ```elixir check all int1 <- integer(), int2 <- integer(), int1 > 0 and int2 > 0, sum = int1 + int2 do assert sum > int1 assert sum > int2 end ``` -------------------------------- ### Generate Dates within a Range Source: https://hexdocs.pm/stream_data/StreamData.html Demonstrates generating dates using the `date/1` function with options like `:origin`, `:min`, and `:max` to control the date range and shrinking behavior. It also shows how to use a `Date.Range.t()` for generation. ```elixir StreamData.date({:min, ~D[2023-01-01]}) StreamData.date([origin: ~D[2023-01-01], max: ~D[2023-12-31]]) StreamData.date(Date.Range.new(~D[2023-01-01], ~D[2023-12-31])) ``` -------------------------------- ### Generate integers with StreamData Source: https://hexdocs.pm/stream_data/index.html Demonstrates how to take a finite number of values from an infinite integer generator. ```elixir Enum.take(StreamData.integer(), 10) #=> [-1, 0, -3, 4, -4, 5, -1, -3, 5, 8] ``` -------------------------------- ### Generate Binaries Source: https://hexdocs.pm/stream_data/index.html Generates binaries. The length of the generated binaries is limited by the generation size. Options like :length, :min_length, and :max_length can be used to control the size. ```elixir @spec binary(keyword()) :: t(binary()) ``` -------------------------------- ### StreamData Configuration: `inspect_opts` Source: https://hexdocs.pm/stream_data/ExUnitProperties.html Customizes the `inspect/2` options used by StreamData when shrinking values upon error. ```APIDOC ## Options: `inspect_opts` When an error occurs, StreamData shrinks the generated values to find the smallest set that reproduces the error. It then prints these values using `inspect/2`. You can customize the `inspect/2` options by setting the `:inspect_opts` option in your test configuration. ### Configuration Example (`config/test.exs`) ```elixir import Config config :stream_data, inspect_opts: [limit: :infinity] ``` This configuration sets the inspect limit to infinity, ensuring all parts of the generated data are shown when an error occurs. ``` -------------------------------- ### ExUnitProperties property/3 Source: https://hexdocs.pm/stream_data/ExUnitProperties.html Defines a property test and imports property-testing facilities. ```APIDOC ## property/3 (macro) ### Description Defines a property test and imports `StreamData` functions and `check/2` into the test body. This macro is similar to `ExUnit.Case.test/3` but specifically for property tests. It is recommended for tests consisting solely of `check/2` calls to improve clarity and reporting. ### Example ```elixir use ExUnitProperties property "reversing a list doesn't change its length" do check all list <- StreamData.list_of(StreamData.integer()) do assert length(list) == length(:lists.reverse(list)) end end ``` ``` -------------------------------- ### Generate keyword lists with specific values Source: https://hexdocs.pm/stream_data/index.html Use keyword_of/1 with a generator for value_data to create keyword lists where keys are atoms and values are generated by value_data. Shrinks equivalently to list_of/1. ```elixir @spec keyword_of(t(a)) :: t(keyword(a)) when a: term() ``` ```elixir Enum.take(StreamData.keyword_of(StreamData.integer()), 3) ``` -------------------------------- ### Generate Based on Generation Size Source: https://hexdocs.pm/stream_data/index.html Use `sized/1` to create a generator that adapts its output based on the current generation size. The provided function receives the size and must return a generator. ```elixir @spec sized((size() -> t(a))) :: t(a) when a: term() ``` ```elixir data = StreamData.sized(fn size -> StreamData.resize(StreamData.integer(), size * 2) end) Enum.take(data, 3) #=> [0, -1, 5] ``` -------------------------------- ### StreamData.check_all/3 Options Source: https://hexdocs.pm/stream_data/StreamData.html Configuration options for the check_all/3 function used in property-based testing. ```APIDOC ## Options for check_all/3 ### Parameters - **initial_seed** (tuple) - Required - Three-element tuple with three integers used as the initial random seed. - **initial_size** (non-negative integer) - Optional - The initial generation size. Defaults to 1. - **max_runs** (non-negative integer) - Optional - Total number of elements to generate and check. Defaults to 100. - **max_run_time** (non-negative integer) - Optional - Total time in milliseconds to run the check. - **max_shrinking_steps** (non-negative integer) - Optional - Maximum number of shrinking steps to perform. Defaults to 100. ``` -------------------------------- ### Configure inspect options Source: https://hexdocs.pm/stream_data/ExUnitProperties.html Set global inspect options for error reporting in test configuration. ```elixir # config/test.exs import Config config :stream_data, inspect_opts: [limit: :infinity] ``` -------------------------------- ### Transform generators with Stream modules Source: https://hexdocs.pm/stream_data/index.html Shows how to pipe generators through Stream and Enum functions to filter and map generated values. ```elixir StreamData.integer() |> Stream.filter(& &1 > 0) |> Stream.map(& &1 * 2) |> Enum.take(10) #=> [4, 6, 4, 10, 14, 16, 4, 16, 36, 16] ``` -------------------------------- ### Define a property test with StreamData facilities Source: https://hexdocs.pm/stream_data/ExUnitProperties.html Defines a property test and imports StreamData functions and `check/2` into the body. Recommended when the body consists only of `check/2` calls for clarity and improved reporting. ```elixir use ExUnitProperties property "reversing a list doesn't change its length" do check all list <- list_of(integer()) do assert length(list) == length(:lists.reverse(list)) end end ``` -------------------------------- ### ExUnit Properties: `check/1` Macro Source: https://hexdocs.pm/stream_data/ExUnitProperties.html The `check/1` macro is used to run tests for a property, defining clauses for generating data and assertions for testing the property's validity. ```APIDOC ## `check/1` Macro Runs tests for a property. ### Description The `check/1` macro provides a concise syntax for defining properties and their associated tests. It allows you to specify data generation clauses and then assert conditions within the `do` block. ### Example ```elixir check all int1 <- integer(), int2 <- integer(), int1 > 0 and int2 > 0, sum = int1 + int2 do assert sum > int1 assert sum > int2 end ``` **Clauses**: Everything between `check all` and `do` specifies how to generate data (e.g., `int1 <- integer()`). **Body**: The `do` block contains the assertions that must hold true for the generated data. ``` -------------------------------- ### float/1 Source: https://hexdocs.pm/stream_data/StreamData.html Generates floats based on optional min and max constraints. ```APIDOC ## float(options) ### Description Generates floats according to the given options. Complexity grows proportionally to the generation size. ### Parameters - **options** (keyword) - Optional - **:min** (float) - The minimum inclusive value. - **:max** (float) - The maximum inclusive value. ### Response - **generator** (t(float())) - A generator for float values. ``` -------------------------------- ### Verify properties with check_all Source: https://hexdocs.pm/stream_data/index.html Defines the specification for checking properties on generated data using check_all/3. ```elixir @spec check_all(t(a), Keyword.t(), (a -> {:ok, term()} | {:error, b})) :: {:ok, map()} | {:error, map()} when a: term(), b: term() ``` -------------------------------- ### Generate iolists Source: https://hexdocs.pm/stream_data/index.html Use iolist/0 to generate values of the iolist() type. Shrinks towards smaller, less nested lists and bytes instead of binaries. ```elixir @spec iolist() :: t(iolist()) ``` ```elixir Enum.take(StreamData.iolist(), 3) ``` -------------------------------- ### Verify integer generation Source: https://hexdocs.pm/stream_data/ExUnitProperties.html Basic usage of check all to validate that generated values meet specific criteria. ```elixir check all int <- integer() do assert is_integer(int) end ``` -------------------------------- ### Generate iodata Source: https://hexdocs.pm/stream_data/index.html Use iodata/0 to generate values of the iodata() type. Shrinks towards less nested iodata and smaller binaries. ```elixir @spec iodata() :: t(iodata()) ``` ```elixir Enum.take(StreamData.iodata(), 3) ``` -------------------------------- ### Generate Based on Size Source: https://hexdocs.pm/stream_data/StreamData.html Use `sized/1` to create a generator whose behavior is determined by a provided function that receives the generation size. This allows for dynamic generation ranges, such as doubling the range of `integer/0`. ```elixir data = StreamData.sized(fn size -> StreamData.resize(StreamData.integer(), size * 2) end) Enum.take(data, 3) #=> [0, -1, 5] ``` -------------------------------- ### Generate Dates with StreamData Source: https://hexdocs.pm/stream_data/index.html Demonstrates generating sequences of dates using StreamData.date/1. Supports specifying origin, min/max dates, and date ranges. ```elixir Enum.take(StreamData.date(), 3) #=> [~D[2023-11-24], ~D[2023-11-25], ~D[2023-11-23]] ``` ```elixir Enum.take(StreamData.date(origin: ~D[2025-09-01]), 3) #=> [~D[2025-08-31], ~D[2025-08-31], ~D[2025-09-04]] ``` ```elixir Enum.take(StreamData.date(min: ~D[2025-01-01], max: ~D[2025-01-31]), 3) #=> [~D[2025-01-27], ~D[2025-01-21], ~D[2025-01-16]] ``` ```elixir Enum.take(StreamData.date(Date.range(~D[2025-01-01], ~D[2025-01-31])), 3) #=> [~D[2025-01-29], ~D[2025-01-03], ~D[2025-01-15]] ``` -------------------------------- ### StreamData.check_all/3 Options Source: https://hexdocs.pm/stream_data/index.html Options available for the StreamData.check_all/3 function to control random generation and checking behavior. ```APIDOC ## StreamData.check_all/3 Options This function takes the following options: * `:initial_seed` - three-element tuple with three integers that is used as the initial random seed that drives the random generation. This option is required. * `:initial_size` - (non-negative integer) the initial generation size used to start generating values. The generation size is then incremented by `1` on each iteration. See the "Generation size" section of the module documentation for more information on generation size. Defaults to `1`. * `:max_runs` - (non-negative integer) the total number of elements to generate out of `data` and check through `fun`. Defaults to `100`. * `:max_run_time` - (non-negative integer) the total number of time (in milliseconds) to run a given check for. This is not used by default, so unless a value is given, then the length of the check will be determined by `:max_runs`. If both `:max_runs` and `:max_run_time` are given, then the check will finish at whichever comes first, `:max_runs` or `:max_run_time`. * `:max_shrinking_steps` - (non-negative integer) the maximum numbers of shrinking steps to perform in case `check_all/3` finds an element that doesn't satisfy `fun`. Defaults to `100`. ``` -------------------------------- ### integer/0 and integer/1 Source: https://hexdocs.pm/stream_data/StreamData.html Generates integers, either bound by generation size or within a specific range. ```APIDOC ## integer() ### Description Generates integers bound by the generation size. ## integer(range) ### Description Generates an integer in the given `range`. ### Parameters #### Path Parameters - **range** (Range.t()) - Required - The range within which the integer should be generated. ``` -------------------------------- ### integer/0 and integer/1 Source: https://hexdocs.pm/stream_data/index.html Generates integers, either bound by generation size or within a specific range. ```APIDOC ## integer() ### Description Generates integers bound by the generation size. ## integer(range) ### Description Generates an integer in the given `range`. The generation size is ignored. ### Parameters #### Request Body - **range** (Range.t()) - Required - The range of integers to generate. ``` -------------------------------- ### ExUnit Properties: `pick/1` Function Source: https://hexdocs.pm/stream_data/ExUnitProperties.html The `pick/1` function is used to select a single random element from a StreamData generator. ```APIDOC ## `pick/1` Function Picks a random element generated by the `StreamData` generator `data`. ### Description Use `pick/1` when you need to obtain a single, randomly generated value from a defined StreamData generator. This is useful for specific test cases where you want to ensure a particular type of data is used. ### Example ```elixir my_random_string = pick(StreamData.string()) IO.inspect(my_random_string) ``` ``` -------------------------------- ### Configure StreamData in test environment Source: https://hexdocs.pm/stream_data/ExUnitProperties.html Set global StreamData options in your project's config files to adjust test behavior based on the environment. ```elixir # config/test.exs import Config config :stream_data, max_runs: if System.get_env("CI"), do: 1_000, else: 50 ``` -------------------------------- ### Verify list membership with custom run count Source: https://hexdocs.pm/stream_data/ExUnitProperties.html Override default configuration options like max_runs directly within a check all block. ```elixir check all list <- list_of(integer()), member <- member_of(list), max_runs: 50 do assert member in list end ``` -------------------------------- ### Take Sample Alphanumeric Atoms Source: https://hexdocs.pm/stream_data/index.html Demonstrates taking a sample of three alphanumeric atoms generated by StreamData.atom/1. ```elixir Enum.take(StreamData.atom(:alphanumeric), 3) #=> [:xF, :y, :B_] ``` -------------------------------- ### Generate Arbitrary Printable Atoms Source: https://hexdocs.pm/stream_data/index.html Generates arbitrary printable atoms up to 255 characters by mapping printable strings to atoms. Be mindful of the system limit for atom length. ```elixir printable_atom = StreamData.map( StreamData.string(:printable, max_length: 255), &String.to_atom/1 ) ``` -------------------------------- ### Generate unbounded integers Source: https://hexdocs.pm/stream_data/index.html Use integer/0 to generate integers. The generated values are bound by the generation size and shrink towards 0. ```elixir @spec integer() :: t(integer()) ``` ```elixir Enum.take(StreamData.integer(), 3) ``` -------------------------------- ### Generate Strings Source: https://hexdocs.pm/stream_data/index.html The `string/2` function generates strings based on a specified kind (e.g., `:ascii`, `:alphanumeric`, `:printable`, `:utf8`) or a custom set of characters. Options can be passed to modify generation behavior. ```elixir Enum.take(StreamData.string(:ascii), 3) #=> ["c", "9A", ""] Enum.take(StreamData.string(Enum.concat([?a..?c, ?l..?o])), 3) #=> ["c", "oa", "lb"] ``` -------------------------------- ### Generate Floats with StreamData Source: https://hexdocs.pm/stream_data/index.html Generates floating-point numbers. Options include :min and :max to define the range. Shrinking is towards simpler floats but respects the min/max bounds. ```elixir @spec float(keyword()) :: t(float()) ``` -------------------------------- ### tuple/1 Source: https://hexdocs.pm/stream_data/index.html Generates tuples where each element is taken from a corresponding generator. ```APIDOC ## tuple(tuple_datas) ### Description Generates tuples where each element is taken out of the corresponding generator in the `tuple_datas` tuple. ### Parameters - **tuple_datas** (tuple()) - Required - A tuple containing generators for each element. ``` -------------------------------- ### ExUnit Properties: `gen/1` Macro Source: https://hexdocs.pm/stream_data/ExUnitProperties.html The `gen/1` macro is syntactic sugar for creating custom data generators within StreamData. ```APIDOC ## `gen/1` Macro Syntactic sugar to create generators. ### Description This macro simplifies the creation of custom generators. It allows you to define the structure of the generated data using a familiar syntax, often involving other generators or basic types. ### Example ```elixir defp my_generator do gen all name <- string(), age <- integer(1..100) do %{name: name, age: age} end end ``` This defines a generator `my_generator` that produces maps with `:name` and `:age` keys. ``` -------------------------------- ### Define custom generators with gen Source: https://hexdocs.pm/stream_data/ExUnitProperties.html Create complex generators by mapping over existing ones or using the gen macro to combine multiple clauses. ```elixir defmodule User do defstruct [:name, :email] end ``` ```elixir email_generator = map({binary(), binary()}, fn {left, right} -> left <> "@" <> right end) user_generator = gen all name <- binary(), email <- email_generator do %User{name: name, email: email} end ``` -------------------------------- ### ExUnitProperties property/1 Source: https://hexdocs.pm/stream_data/ExUnitProperties.html Defines a not-implemented property test. ```APIDOC ## property/1 (macro) ### Description Defines a property test that is not yet implemented. This macro creates a test that will always fail with a "Not implemented" error message and is tagged with `:not_implemented`. It is similar to `ExUnit.Case.test/1`. ### Example ```elixir property "this will be a property test in the future" ``` ``` -------------------------------- ### bind/2 Source: https://hexdocs.pm/stream_data/StreamData.html Binds each element generated by data to a new generator returned by applying a function. ```APIDOC ## bind(data, fun) ### Description Binds each element generated by data to a new generator returned by applying fun. This is the basic mechanism for composing generators. ### Parameters #### Request Body - **data** (t(a)) - Required - The source generator. - **fun** (a -> t(b)) - Required - A function that takes an element and returns a new generator. ``` -------------------------------- ### StreamData Modules Overview Source: https://hexdocs.pm/stream_data/api-reference.html Overview of the primary modules available in the StreamData library. ```APIDOC ## Modules ### ExUnitProperties Provides macros for property-based testing. ### StreamData Functions to create and combine generators. ### StreamData.FilterTooNarrowError Error raised when a filter is too narrow. ### StreamData.TooManyDuplicatesError Error raised when too many duplicates are encountered during generation. ``` -------------------------------- ### Seed a Generator for Predictable Output Source: https://hexdocs.pm/stream_data/StreamData.html Use `seeded/2` to make a generator produce a predictable sequence of values using a specific seed. This is useful for debugging or when reproducible generation is required. The seed must be an integer. ```elixir int = StreamData.seeded(StreamData.integer(), 10) Enum.take(int, 3) #=> [-1, -2, 1] Enum.take(int, 4) #=> [-1, -2, 1, 2] ``` -------------------------------- ### Generate lists of specific data Source: https://hexdocs.pm/stream_data/index.html Use list_of/1 to generate lists where each element is produced by the given data generator. Equivalent to list_of/2 with no options. ```elixir @spec list_of(t(a)) :: t([a]) when a: term() ``` ```elixir Enum.take(StreamData.list_of(StreamData.binary()), 3) ``` -------------------------------- ### Generate values with specified probability Source: https://hexdocs.pm/stream_data/index.html Use frequency/1 to create a generator that selects values from different generators based on their specified probabilities. Ensure the sum of frequencies is positive. ```elixir @spec frequency([{pos_integer(), t(a)}]) :: t(a) when a: term() ``` ```elixir ints_and_some_bins = StreamData.frequency([ {3, StreamData.integer()}, {1, StreamData.binary()}, ]) Enum.take(ints_and_some_bins, 3) ``` -------------------------------- ### Verify string concatenation properties Source: https://hexdocs.pm/stream_data/ExUnitProperties.html Use multiple generators within check all to verify properties across combined data inputs. ```elixir check all start <- binary(), finish <- binary(), concat = start <> finish do assert String.starts_with?(concat, start) assert String.ends_with?(concat, finish) end ``` -------------------------------- ### Seed a Generator for Predictable Output Source: https://hexdocs.pm/stream_data/index.html Use `seeded/2` to make a generator produce a predictable sequence of values using a specific seed. This is useful for reproducible tests. ```elixir @spec seeded(t(a), integer()) :: t(a) when a: term() ``` ```elixir int = StreamData.seeded(StreamData.integer(), 10) Enum.take(int, 3) #=> [-1, -2, 1] Enum.take(int, 4) #=> [-1, -2, 1, 2] ``` -------------------------------- ### Generate a Constant Term Source: https://hexdocs.pm/stream_data/StreamData.html Illustrates the use of the `constant/1` generator, which always produces the specified term. This is useful for generating a fixed value repeatedly. ```elixir iex> Enum.take(StreamData.constant(:some_term), 3) [:some_term, :some_term, :some_term] ``` -------------------------------- ### check/3 Macro Source: https://hexdocs.pm/stream_data/ExUnitProperties.html The check/3 macro is the core of property-based testing in ExUnitProperties, used to execute assertions over a large number of randomly generated data points. ```APIDOC ## check/3 ### Description Executes a block of code multiple times with randomly generated data. If the assertion fails, the library attempts to shrink the input to the smallest failing case. ### Parameters - **generators** (list) - Required - A list of generator expressions (e.g., a <- StreamData.binary()). - **block** (do-block) - Required - The test logic containing assertions to be verified against the generated data. ### Request Example ```elixir check all a <- StreamData.binary(), b <- StreamData.binary() do assert starts_with?(a <> b, a) end ``` ``` -------------------------------- ### Generate values using a function with StreamData.repeatedly Source: https://hexdocs.pm/stream_data/index.html Uses a zero-argument function to generate values. This generator is not shrinkable. ```elixir uuid = StreamData.repeatedly(&Ecto.UUID.generate/0) Enum.take(uuid, 3) #=> ["2712ec5b-bc50-4b4a-8a8a-ca85d37a457b", "2092570d-8fb0-4e67-acbe-92db4c8a2bae", "1bef1fb1-8f86-46ac-a49e-3bffaa51e40b"] integer = StreamData.repeatedly(&System.unique_integer([:positive, :monotonic])) Enum.take(integer, 3) #=> [1, 2, 3] ``` -------------------------------- ### sized(fun) Source: https://hexdocs.pm/stream_data/StreamData.html Returns the generator returned by calling fun with the generation size. ```APIDOC ## sized(fun) ### Description Returns the generator returned by calling `fun` with the generation size. `fun` takes the generation size and has to return a generator. ### Parameters #### Arguments - **fun** ((size() -> t(a))) - Required - A function that takes a size and returns a generator. ### Response - **generator** (t(a)) - The generator returned by the function. ``` -------------------------------- ### sized(fun) Source: https://hexdocs.pm/stream_data/index.html Returns the generator returned by calling fun with the generation size. ```APIDOC ## sized(fun) ### Description Returns the generator returned by calling `fun` with the generation size. ### Parameters - **fun** ((size() -> t(a))) - Required - A function that takes the generation size and returns a generator. ``` -------------------------------- ### shuffle(enum) Source: https://hexdocs.pm/stream_data/StreamData.html Generates lists with the same elements as the provided enum but in a random order. ```APIDOC ## shuffle(enum) ### Description Generates lists with the same elements as the provided `enum` but in a random order. ### Parameters #### Arguments - **enum** (Enumerable.t()) - Required - The collection to shuffle. ### Response - **generator** (t(Enumerable.t())) - A generator that produces shuffled lists. ``` -------------------------------- ### shuffle(enum) Source: https://hexdocs.pm/stream_data/index.html Generates lists with the same elements as the provided enum but in a random order. ```APIDOC ## shuffle(enum) ### Description Generates lists with the same elements as the provided `enum` but in a random order. ### Parameters - **enum** (Enumerable.t()) - Required - The collection to shuffle. ``` -------------------------------- ### nullable/2 Source: https://hexdocs.pm/stream_data/index.html Generates either `nil` or a value from the given generator, with a configurable ratio. ```APIDOC ## nullable/2 ### Description Generates either `nil` or the value generated by the given `data`. The frequency distribution can be specified using the `:ratio` option. ### Method StreamData.nullable(generator, options) ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Options * `:ratio` - (float in between `0.0` and `1.0`, not included) specifies the frequency with which `nil` should be selected. Higher means that `nil` is more likely to be selected. Defaults to `0.5`. ### Request Example ```elixir # Example with default ratio StreamData.nullable(StreamData.integer()) # Example with higher chance of nil StreamData.nullable(StreamData.integer(), ratio: 0.8) ``` ### Response #### Success Response (200) - `value` (nil | term) - Either `nil` or a value generated by the input generator. #### Response Example ```elixir #=> nil #=> 123 #=> nil #=> -45 ``` ### Shrinking Shrinks towards `nil` if `nil` is generated, otherwise shrinks towards the input generator's shrinking behavior. ``` -------------------------------- ### Generate values from a list with StreamData.one_of Source: https://hexdocs.pm/stream_data/index.html Picks a generator at random from the provided list of generators for each value. ```elixir data = StreamData.one_of([StreamData.integer(), StreamData.binary()]) Enum.take(data, 3) #=> [-1, <<28>>, ""] ``` -------------------------------- ### Generate Binary Trees with StreamData.tree Source: https://hexdocs.pm/stream_data/StreamData.html Use `StreamData.tree/2` to generate nested data structures. The `subtree_fun` defines how inner nodes are created, allowing for recursive data generation like binary trees. ```elixir defmodule Branch do defstruct [:left, :right] end ``` ```elixir tree_data = StreamData.tree(StreamData.integer(), fn child_data -> StreamData.map({child_data, child_data}, fn {left, right} -> %Branch{left: left, right: right} end) end) Enum.at(StreamData.resize(tree_data, 10), 0) ``` -------------------------------- ### list_of/1 and list_of/2 Source: https://hexdocs.pm/stream_data/StreamData.html Generates lists where each value is generated by the provided data generator. ```APIDOC ## list_of(data, options) ### Description Generates lists where each value is generated by the given `data`. The length of the generated list is bound by the generation size or provided options. ### Parameters #### Request Body - **data** (t(a)) - Required - The generator for list elements. - **options** (keyword) - Optional - Configuration options including `:length`, `:min_length`, and `:max_length`. ``` -------------------------------- ### list_of/1 and list_of/2 Source: https://hexdocs.pm/stream_data/index.html Generates lists where each value is generated by the provided data generator. ```APIDOC ## list_of(data, options) ### Description Generates lists where each value is generated by the given `data`. The length is bound by generation size unless options are provided. ### Parameters #### Request Body - **data** (t(a)) - Required - The generator for list elements. - **options** (keyword) - Optional - Options include `:length`, `:min_length`, and `:max_length` to control list size. ``` -------------------------------- ### Generate Fixed Lists with StreamData Source: https://hexdocs.pm/stream_data/index.html Creates a generator for lists of a fixed length, where each element is generated from a corresponding generator. Shrinks by shrinking individual list elements. ```elixir data = StreamData.fixed_list([StreamData.integer(), StreamData.binary()]) Enum.take(data, 3) #=> [[1, <<164>>], [2, ".T"], [1, ""]] ``` -------------------------------- ### Generate ASCII Strings Source: https://hexdocs.pm/stream_data/StreamData.html Use `string/1` with the `:ascii` kind to generate strings containing only ASCII characters. These strings shrink towards lower codepoints. ```elixir Enum.take(StreamData.string(:ascii), 3) #=> ["c", "9A", ""] ``` -------------------------------- ### Shuffle List Elements Source: https://hexdocs.pm/stream_data/StreamData.html The `shuffle/1` function generates lists with the same elements as the input enumerable but in a random order. This is available since version 1.2.0. ```elixir StreamData.shuffle([1, 2, 3, 4, 5]) |> Enum.take(3) #=> [[4, 2, 5, 3, 1], [1, 3, 4, 5, 2], [3, 2, 5, 4, 1]] ``` -------------------------------- ### Generate Nullable Values Source: https://hexdocs.pm/stream_data/index.html Generates either nil or a value from the given generator. The ratio of nil to non-nil values can be controlled with the :ratio option. ```elixir @spec nullable( t(a), keyword() ) :: t(nil | a) when a: term() ``` -------------------------------- ### Generate Fixed Maps with StreamData Source: https://hexdocs.pm/stream_data/index.html Generates maps with predefined keys and generated values. Shrinks by shrinking the values associated with each key. Useful for creating structured data. ```elixir data = StreamData.fixed_map(%{ integer: StreamData.integer(), binary: StreamData.binary(), }) Enum.take(data, 3) #=> ["R1^", integer: -3}, %{binary: "", integer: 1}, %{binary: "", integer: -2} ``` -------------------------------- ### Resize a generator with StreamData.resize Source: https://hexdocs.pm/stream_data/index.html Forces a generator to use a fixed generation size, ignoring the default size. ```elixir data = StreamData.resize(StreamData.integer(), 10) Enum.take(data, 3) #=> [4, -5, -9] ```