Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add more specific effect matchers #178

Merged
merged 3 commits into from
Aug 26, 2021
Merged

Conversation

kmcbride
Copy link
Collaborator

@kmcbride kmcbride commented Aug 22, 2021

Introduces a few additional effect matchers to MobiusTest and MobiusNimble:

  • hasOnlyEffects / haveOnlyEffects: Enforces that only the expected effects are present, regardless of order
  • hasExactlyEffects / haveExactlyEffects: Enforces that only the expected effects are present, in the specified order

@codecov
Copy link

codecov bot commented Aug 22, 2021

Codecov Report

Merging #178 (63cbf1e) into master (231e8ab) will increase coverage by 0.37%.
The diff coverage is 100.00%.

❗ Current head 63cbf1e differs from pull request most recent head 321ec9b. Consider uploading reports for the commit 321ec9b to get more accurate results
Impacted file tree graph

@@            Coverage Diff             @@
##           master     #178      +/-   ##
==========================================
+ Coverage   94.37%   94.74%   +0.37%     
==========================================
  Files          43       43              
  Lines        1279     1370      +91     
==========================================
+ Hits         1207     1298      +91     
  Misses         72       72              
Flag Coverage Δ
ios 94.74% <100.00%> (+0.37%) ⬆️
macspm 94.69% <100.00%> (+0.38%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Impacted Files Coverage Δ
MobiusNimble/Source/NimbleFirstMatchers.swift 100.00% <100.00%> (ø)
MobiusNimble/Source/NimbleNextMatchers.swift 100.00% <100.00%> (ø)
MobiusTest/Source/FirstMatchers.swift 100.00% <100.00%> (ø)
MobiusTest/Source/NextMatchers.swift 100.00% <100.00%> (ø)

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 231e8ab...321ec9b. Read the comment docs.

rastersize
rastersize previously approved these changes Aug 23, 2021
Copy link
Contributor

@rastersize rastersize left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it just me or is it a bit weird that the Nimble matchers are named have while the MobiusTest matchers are named has? Not a big deal but seems like it would make sense to use the same prefix.

For a future change I wonder if we should rename (as-in add a new method named that, migrate existing code to it and then remove the old method) (has|have)Effects to containsEffect? In order to make it more clear which matcher does what.

@kmcbride
Copy link
Collaborator Author

Is it just me or is it a bit weird that the Nimble matchers are named have while the MobiusTest matchers are named has? Not a big deal but seems like it would make sense to use the same prefix.

I initially thought that as well, but it helps tests read more naturally. I assume that's the original reasoning for it.

  • Standard: assertThatNext(hasOnlyEffects([.foo, .bar]))
  • Nimble: expect(next).to(haveOnlyEffects([.foo, .bar]))

For a future change I wonder if we should rename (as-in add a new method named that, migrate existing code to it and then remove the old method) (has|have)Effects to containsEffect? In order to make it more clear which matcher does what.

Yeah, I struggled with how to best name them. The problem is that contains doesn't seem to have a consistent meaning across frameworks — in Hamcrest it means "exactly these items in this order" but in Nimble it's "at least these items in any order".

@rastersize
Copy link
Contributor

Is it just me or is it a bit weird that the Nimble matchers are named have while the MobiusTest matchers are named has? Not a big deal but seems like it would make sense to use the same prefix.

I initially thought that as well, but it helps tests read more naturally. I assume that's the original reasoning for it.

  • Standard: assertThatNext(hasOnlyEffects([.foo, .bar]))
  • Nimble: expect(next).to(haveOnlyEffects([.foo, .bar]))

Ah yeah that makes sense 👍

For a future change I wonder if we should rename (as-in add a new method named that, migrate existing code to it and then remove the old method) (has|have)Effects to containsEffect? In order to make it more clear which matcher does what.

Yeah, I struggled with how to best name them. The problem is that contains doesn't seem to have a consistent meaning across frameworks — in Hamcrest it means "exactly these items in this order" but in Nimble it's "at least these items in any order".

I think Hamcrest is the odd one out here. As both Nimble and the Swift standard library uses contains as “has at least these items”. However I feel like such a change might warrant more input from the wider (internal at least) iOS community.

@pettermahlen
Copy link
Member

I think both 'has' and 'contains' mean the same thing - that is, no difference regarding whether it means 'has at least' or 'has exactly' or 'contains at least' and 'contains exactly'. So for precision, a longer name is warranted, in my opinion.

@kmcbride kmcbride merged commit 681ff65 into spotify:master Aug 26, 2021
@kmcbride kmcbride deleted the effect-matchers branch August 26, 2021 19:25
Comment on lines +152 to +157
var unmatchedActual = next.effects
var unmatchedExpected = expected
zip(next.effects, expected).forEach {
_ = unmatchedActual.firstIndex(of: $1).map { unmatchedActual.remove(at: $0) }
_ = unmatchedExpected.firstIndex(of: $0).map { unmatchedExpected.remove(at: $0) }
}
Copy link
Collaborator

@zvonicek zvonicek Aug 28, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kmcbride I'm trying to finalize #177 (finally!) and this code is causing me troubles. When for example next.effects == [.a, .b] and expected == [.b], then after running this code unmatchedExpected == [.b], which I think is incorrect, as .b could actually be matched.

Could this be implemented this way (which would in my opinion fix the problem):

let unmatchedActual = next.effects.filter { !expected.contains($0) }
let unmatchedExpected = expected.filter { !next.effects.contains($0) }

or is there any edge case I'm not seeing here?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The intention here was to do the minimum work necessary to determine if the expectation could be satisfied, so the arrays don't always contain the "true" diff between the two inputs even though the returned value is correct. Feel free to adjust as needed for computing the actual diff 😬

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants