antonmi / espec

Elixir Behaviour Driven Development
Other
808 stars 62 forks source link

Feature: scoped_before #278

Closed indiejames closed 5 years ago

indiejames commented 6 years ago

It would be useful to be able to define a before that is scoped to the current level not to all child levels. As an example consider the following test code:

describe "State tests" do
    before do
      IO.puts("Calling `before`")
      {:shared, a: 1}
    end

    describe "Test 1" do
      it do: shared.a |> should(eq 1)
      it do: shared.a |> should(eq 1)
    end

    describe "Test 2" do
      it do: shared.a |> should(eq 1)
      it do: shared.a |> should(eq 1)
    end
  end

When run this will produce the following output:

$ mix espec
Calling `before`
.Calling `before`
.Calling `before`
.Calling `before`
.

4 examples, 0 failures

Finished in 0.1 seconds (0.08s on load, 0.01s on specs)

The before gets called for every test. It would be useful to be able to declare a before that only gets called once for each describe, like so

describe "State tests" do
    scoped_before do
      IO.puts("Calling `scoped_before`")
      {:shared, a: 1}
    end

    describe "Test 1" do
      it do: shared.a |> should(eq 1)
      it do: shared.a |> should(eq 1)
    end

    describe "Test 2" do
      it do: shared.a |> should(eq 1)
      it do: shared.a |> should(eq 1)
    end
  end

When run this would produce the following output:

$ mix espec
  .Calling `scoped_before`
  .
  .Calling `scoped_before`
  .
  4 examples, 0 failures

    Finished in 0.1 seconds (0.08s on load, 0.01s on specs)

The scoped_before would only be called once for each nested describe.

antonmi commented 6 years ago

Hi @indiejames ! Sorry for the late response. I'm not sure that sharing data between tests is a good idea and there is no such functionality in ESpec. But there is the "before_all" callback. It doesn't allow you to set shared value, but you can implement an Agent and store values there.