antonmi / espec

Elixir Behaviour Driven Development
Other
808 stars 62 forks source link

Bugfix - Incorrect shared values in before #290

Closed sascha-wolf closed 5 years ago

sascha-wolf commented 5 years ago

This PR fixes an issue with the tags passed into before blocks. The issue occurred when a tag was overwritten in a lower context and then the same tag accessed in the before clause.

See the below added and currently failing regression test:

defmodule Regression.IncorrectSharedValuesInBeforeSpec do
  use ESpec, option: true

  before do: send self(), {:option, shared[:option]}

  it "option should be true" do
    assert_receive {:option, true}
  end

  it "option should be false", option: false do
    assert_receive {:option, false}
  end
end

Cause

The cause for this issue was that Example.extract_options/1 returned a Keyword list with all entries, sorted by most specific to least specific.

https://github.com/antonmi/espec/blob/541ca38e9b548cbcc5c23882ee4af97c21f17b3c/lib/espec/example.ex#L72-L75

This Keyword list was then transformed to a map in ExampleRunner:

https://github.com/antonmi/espec/blob/541ca38e9b548cbcc5c23882ee4af97c21f17b3c/lib/espec/example_runner.ex#L73-L76

This in turn iterated over the received Keyword list, putting the elements into a map. The ordering then lead to less specific values overriding more specific ones.

Long story short. A Keyword list looking like this:

[
  a: 1, # Most specific a
  b: 2,
  a: 3  # Least specific a
]

Became this map:

%{
  a: 3,
  b: 2
}

Solution

This PR updates the Example.extract_options/1 implementation to instead return a map with the currently valid options. It also updates Example.extract_option/2 to make use of this map instead of iterating over the keyword list.

The previous implementation can now be accessed under Example.extract_all_options/1.

antonmi commented 5 years ago

Looks awesome! Thanks @Zeeker !