mercredi 11 novembre 2020

Matching parts of data structure for equality regardless of their content in rspec

Rspec's match operator is a fantastic tool to validate the structure of data structures using pattern matching.

This works great:

expect([1,2,2]).to match([a_kind_of(Integer), 2, 2)])

However, often we don't want to validate the specific values contained in the data structure, and instead want to validate that the relation between different elements is what we expect. Reusing the example, we might just want to say that the values in the second and third position are the same (e.g. because they are randomly generated IDs).

Conceptually, I'm looking for the capacity that variables provide in Elixir's pattern matching:

iex(1)> [1, a, a] = [1, 2, 2]
[1, 2, 2]
iex(2)> [1, a, a] = [1, 3, 3]
[1, 3, 3]
iex(3)> [1, a, a] = [1, 2, 3]
** (MatchError) no match of right hand side value: [1, 2, 3]

Converting to rspec, it might look like this example:

expect([1,2,2]).to match([a_kind_of(Integer), variable('a'), variable('a'))])

So, my main question is: Does anything like this magical variable matcher exist in RSpec?

If not, is there a way I could build it? I'm pretty sure I could build something out of the satisfies matcher using something akin to:

@state = {} # challenging to clean up this on every test
def variable(var_name)
   satisfying {|x|
     if @state.include?(var_name)
       x == @state[var_name]
     else
       @state[var_name] = x
       true
     end
   }
end

But then it becomes challenging to clean up the state between tests.

Aucun commentaire:

Enregistrer un commentaire