View Source Given.Case (given_exunit v1.22.206)

Extend ExUnit.Case test cases with feature tests.

At the top of your test module:

defmodule MyApp.FeatureTests do
  use ExUnit.Case, async: true
  use Given.Case
end

A feature is often defined as a set of scenarios. The feature can be achieved by grouping scenarios inside a standard ExUnit describe block:

describe "feature 1" do
  scenario "one", ~s[Given x When y Then z]
end

describe "feature 2" do
  scenario "two", ~s""
  Given x
  When y
  Then z
  ""
end

^ note the doc does not use triple quotes - your test cases should!

A scenario is a list of clauses. Each clause must start with one of GIVEN, WHEN, or THEN in UPPER or Title case. Newlines are counted as whitespace when separating clauses and are recommended but not required.

Clauses must appear in the order GIVEN WHEN THEN. If multiple clauses of the same kind are required then AND (or And) can be interspersed:

GIVEN pre-condition AND another pre-condition
WHEN action
THEN post-condition AND another post-condition

The error messages on the parser are not yet very descriptive! If there is a problem then a Given.SyntaxError will be raised when the test is run however you may also fail the compile with this flag:

use Given.Case, fail_compile: true

If a scenario is required but has not yet been written you can write a failing test as you would in ExUnit.Case by writing a placeholder with a name but without the prose:

describe "Leap seconds" do
  scenario "handle 61 seconds in a minute"
end

Once the scenario is written you must implement the Given.Step callbacks that match the parsed terms:

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]

A pre-condition may return a keyword list of values that are appended to the context and passed from clause to clause. ExUnit.Assertions can be used as normal in the post-conditions.

You may setup a test context as normal:

setup [:setup_a]

scenario "addition", ~s""
Given :a
Then :a is 1
""

def given_(_, _), do: true
def then_({_, :is, x}, %{a: a}), do: assert a == x

def setup_a(_context) do
  [a: 1]
end

Summary

Functions

Defines a named yet not implemented test.

Defines an ExUnit test with given name and prose.

Functions

Link to this macro

scenario(test_name)

View Source (macro)

Defines a named yet not implemented test.

Provides a convenient macro that allows a test to be defined with a string, but not yet implemented. The resulting test will always fail and print a "Not implemented" error message. The resulting test case is also tagged with :not_implemented.

Examples

scenario "handle leap seconds"
Link to this macro

scenario(test_name, prose)

View Source (macro)

Defines an ExUnit test with given name and prose.

The test context cannot be matched but is passed into the first clause. For more information on contexts, see ExUnit.Callbacks.

Clauses must appear in the order GIVEN WHEN THEN. If multiple clauses of the same kind are required then AND (or And) can be interspersed:

Example

GIVEN pre-condition AND another pre-condition
WHEN action
THEN post-condition AND another post-condition