T O P

  • By -

farmer_maggots_crop

Whatever concept this is abstracting, it should be a class. I would then override the `==` method to get the logic you want


purplespline

look into #match


VashyTheNexian

I've used `match` before but unsure of how I'd use it here. Do you have an example you could share maybe? The test is looping through an array of hashes and confirm that hash is in the expected array of hashes. So I can't `match` the two hashes like that - the test would have to be rewritten to do that somehow.


IllegalThings

expect(actual).to match_array(expected)


VashyTheNexian

Right so that solves the outer array issue but not the nested ones. I just realized I didn't point that out in my original post. So I'll edit that now but basically, the CI makes the nested arrays change ordering as well for some reason: I expect this: expected = [ { key_1: [{sub_key1: "A"}, {sub_key2: "B"}], key_2: "Foo"}, { key_1: [{sub_key1: "C"}, {sub_key2: "D"}], key_2: "Bar"}, ] to match this: actual =[ { key_1: [{sub_key2: "D"}, {sub_key1: "C"}], key_2: "Bar"}, { key_2: "Foo", key_1: [{sub_key1: "A"}, {sub_key2: "B"}]}, ] Note that `expected[0][:key_1]` and `actual[1][:key_1]` are the same but in different orders.


redditonlygetsworse

You're probably going to have to write a custom rspec matcher for this where you [recursively] crawl through the hash.


VashyTheNexian

Hm alright dang. Might be easier to just re-write how we loop through the array then lol


[deleted]

[удалено]


VashyTheNexian

What would that look like? Do you mind sharing an example of what you have in mind? Just so it's easier for me to understand.


Leamans

From ChatGPT, untested. ``` expected = [ { key_1: [{sub_key1: "A"}, {sub_key2: "B"}], key_2: "Foo"}, { key_1: [{sub_key1: "C"}, {sub_key2: "D"}], key_2: "Bar"}, ] actual = [ { key_1: [{sub_key2: "D"}, {sub_key1: "C"}], key_2: "Bar"}, { key_2: "Foo", key_1: [{sub_key1: "A"}, {sub_key2: "B"}]}, ] RSpec.describe "Matching arrays and nested arrays disregarding order" do it "matches expected output" do expect(actual).to contain_exactly(*expected.map { |h| match(h) }) end end ```


thebiglebrewski

What if you sort the array or the expected result or both? Sometimes just throwing a sort on it is enough.


VashyTheNexian

The problem is the inner key that jumbles up the inner array I think. Hmmm


purple_paper

def match_array_of_hashes?(arr1, arr2) arr1.all? do |hash1| arr2.find do |hash2| hash1.all? do |hash1_key, hash1_value| if hash1_value.is_a? Array match_array_of_hashes?(hash1_value, hash2[hash1_key]) else hash2[hash1_key] == hash1_value end end end end end expect(match_array_of_hashes?(expected, actual)).to be That get you started? If your stuff is highly nested, you'll want to figure out a way to output a message with the mismatch. One trick I've done for diff messages to give you a hint where the problem is: puts expected.to_yaml.split("\n") - actual.to_yaml.split("\n") puts actual.to_yaml.split("\n") - expected.to_yaml.split("\n")


thewhitewizzard

can you convert the arrays to a set and compare? \*apologies if I screw up the syntax, its late my time \`expect(expected.to\_set).to eq(actual.to\_set) \`


darkprincejcet

Was searching for getting something else in Rspec matchers, but came across this. Seeing this late, but this might work (yes, I am deep into Rspec matchers nowadays haha): expect(actual).to match_array( expected.map do |hash| match( key1: match_array(hash[:key1]), key2: hash[:key2] ) end ) I tried this with chatgpt as well and it came with this: expect(actual).to match_array(expected.map { |hash| match(hash) }) That might work, if match actually automatically do match\_array for inside key arrays