# fugue
Extendable testing utilities for Plug
## Installation
`Fugue` is [available in Hex](https://hex.pm/docs/publish) and can be installed as:
1. Add concerto your list of dependencies in `mix.exs`:
```elixir
def deps do
[{:fugue, "~> 0.1.0"}]
end
```
## Usage
`Fugue` extends `ExUnit.Case` by adding macros for calling `Plug` applications in an extendable way.
```elixir
defmodule Test.MyApp do
use Fugue, plug: MyApp
test "root response" do
request()
after conn ->
conn
|> assert_status(200)
end
test "users read response" do
user_id = "123" # this could come from a seed function
request do
path "/users/#{user_id}"
end
after conn ->
conn
|> assert_body_contains(user_id)
end
end
```
Notice the setup and assertions are separated by an `after` keyword. The idea is to decouple the test case setup/generation from the actual test case execution. This ends up being useful in many ways. We could:
* generate cases on a single machine and distribute the requests around a cluster
* create benchmarks that exclude the setup time and just test the request rate (maybe even skip assertions entirely)
* serialize the requests into a file and run at a later time, or in a different language or service
* chain multiple tests together to create flow tests
* _insert your crazy idea here_
`Fugue` exposes several overridable functions to support this behavior:
### `execute/3`
`execute` is the lowest level hook. It receives the request struct and a function handle for assertions. The default behavior is to call the `call/2` function followed by the assertions:
```elixir
defmodule Test.MyApp do
use Fugue
defp execute(request, assertions, context) do
request
|> call(context)
|> assertions.()
end
end
```
### `call/2`
`call` receives the request struct and executes the request. In the case standard `Plug` apps this would look something like:
```elixir
defmodule Test.MyApp do
use Fugue
def call(request, _context) do
MyApp.call(request, [])
end
end
```
When using `Fugue`, you may pass `:plug` and `:plug_opts` to the default `call` implementation:
```elixir
defmodule Test.MyApp do
use Fugue, plug: MyApp,
plug_opts: []
end
```
### `init_request/1`
`init_request` is passed the test context and can create the request struct. This is helpful for when something other than `Plug.Conn` is used or the default values for `Plug.Conn` need to be changed.
### `prepare_request/2`
`prepare_request` is called just before calling `execute/3` which allows for any final modifications to the request to be made.