README.md

# Given ExUnit

Given-When-Then is a style of representing tests of specifying a system's
behaviour using specification by example - [Martin Fowler][gwt].

This is a micro library that is a lite extension to ExUnit and prefers 
pattern matching over regular expressions. There are other BDD libraries
but they do not seem to be maintained. The advantages of Given are:

1. no regular expressions
2. pattern match errors are clear and obvious
3. line numbers in errors are accurate as there are no separate text files

We use a parser to split clauses into words, strings, integers and dates then
call functions and rely on pattern matching to build up a test state. The input
is the standard context created with the `setup` and `setup_all` callbacks
and this context is passed from clause to clause with new data appended.

Here is a working example using the [peek at elixir-lang.org][ex]:

```elixir
defmodule Given.ReadmeTest do
  use ExUnit.Case
  use Given.Case

  describe "elixir-lang.org" do
    scenario "peek", ~s"""
    Given the string "Elixir"
    When graphemes
    And frequencies
    Then "i" occurs 2 times
    And "E" occurs 1 time
    """
  end

  # Pre-conditions
  def given_({:the_string, s}, _), do: [str: s]
  # Actions
  def when_({:graphemes}, %{str: s}), do: [gs: String.graphemes(s)]
  def when_({:frequencies}, %{gs: gs}), do: [freq: Enum.frequencies(gs)]
  # Post-conditions
  def then_({l, :occurs, n, _}, %{freq: freq}), do: assert n == freq[l]
end
```

See the [Case module][case] for the syntax of the scenarios and 
the [Parser module][parser] contains the terms that can be used.

[![CI](https://github.com/devstopfix/given-exunit/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/devstopfix/given-exunit/actions/workflows/ci.yml)

## Installation

```elixir
def deps do
  [
    {:given, "~> 1.22", only: [:test, :dev]}
  ]
end
```

### Testing

When changing the grammar or the parser, run tests with:

    PROPCHECK_NUMTESTS=20000 mix test

Run deliberately failing tests with:

    mix test --only failing_test


[case]: https://hexdocs.pm/given_exunit/Given.Case.html
[parser]: https://hexdocs.pm/given_exunit/Given.Parser.html
[docs]: https://hexdocs.pm/given_exunit
[ex]: https://elixir-lang.org
[gwt]: https://martinfowler.com/bliki/GivenWhenThen.html