-
-
Notifications
You must be signed in to change notification settings - Fork 212
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
fix: display mismatch reasons in "following elements were mismatched" #1362
Conversation
// TODO: assertionCreatorOrNull should be non-nullable, and this "to be null" should be a part of expectation | ||
assertionBuilder.createDescriptive(DescriptionBasic.TO_BE, Text.NULL) { | ||
e == null | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is strange to handle e == null
here. I wish assertionCreatorOrNull
was non-nullable.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree, this functionality could be refactored. Is due to some legacy behaviour introduced in Atrium 0.2.0 or the like and wouldn't be necessary any more. Going to create a discussion about it
The fix makes expect(listOf(User("joe", "qwerty"), User("j", "qwerty1"))) {
toHaveElementsAndAll {
feature("login", { login })
.feature("size", { length })
.because("login should be longer than one letter") {
toBeGreaterThan(1)
}
feature("password", { password })
.because("password should be secure") {
notToEqual("qwerty")
}
}
} to produce
The following should probably be hidden:
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The output already looks good 👍 but the implementation needs to be adopted
@@ -63,8 +63,7 @@ abstract class BaseExpectImpl<T>( | |||
representationInsteadOfFeature?.let { provider -> | |||
maybeSubject.fold({ null }) { provider(it) } | |||
} ?: maybeSubject.getOrElse { | |||
// a RootExpect without a defined subject is almost certain a bug | |||
Text(SHOULD_NOT_BE_SHOWN_TO_THE_USER_BUG) | |||
Text.EMPTY |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please don't change this in the end, if you saw this text in reporting, then it is most likely an implementation bug 😉
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, what is your recommendation then?
Currently, Atrium uses an explicit None
subject in order to render elements need all:
block.:
atrium/logic/atrium-logic/src/commonMain/kotlin/ch/tutteli/atrium/logic/impl/containsHelpers.kt
Line 45 in 65227ad
it.collectAssertions(container, None, assertionCreatorOrNull) |
@@ -61,6 +61,6 @@ class TextFeatureAssertionGroupFormatter( | |||
parameterObject: AssertionFormatterParameterObject | |||
) : AssertionGroup by assertionGroup { | |||
override val description: Translatable = newName | |||
override val representation: Any = if(parameterObject.isNotInExplanatoryFilterGroup()) assertionGroup.representation else Text.EMPTY | |||
override val representation: Any = assertionGroup.representation |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
please revert in the end
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What would be your suggestion then?
Apparently, the current implementation in Atrium is "whatever is displayed in explanatory goes WITHOUT representation".
At the same time, the only way to put "warning sign" is to wrap it in explanatory.
That creates a deadlock, and I think it is wrong that "explanatory" implies "remove all representations". I just do not understand why it removes the representations. I believe the ones who want to display message "without representation" should call the relevant APIs "without representation", and it should not be "explanatory" that hides representations.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it is wrong that "explanatory" implies "remove all representations"
The reason why we remove the representation is because usually we explain what expectation was defined without it being bound to a subject. For instance, the ◆ elements need all:
part. The expectations shown there are not bound to a specific element in the Iterable.
At the same time, the only way to put "warning sign" is to wrap it in explanatory.
I see now better where your request for a non-fluent assertionBuilder comes from :)
I see overlapping topics here. I think one way forward would be that we can define that a certain Assertion
should be shown as is within an explanatory group, i.e. kind of escape the explanatory mechanism. This way we would also only show failing expectations etc. as it was not within an explanatory group.
Another approach would be that we allow more freely what bullet points are used and then you would not use an explanatory group in your case but just a regular list group with another bullet point.
Have to go, wil, think about it later on.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We need to take the approach with escaping because otherwise we loose context. for this to work, we need:
- change from NonFiltering count to FilteringStack
- A new GroupAssertionType EscapeNonFiltering which behaves like an invisible group but additionally modifies the stack
I can give further pointers in case you want to tackle this. I am writing on top of my head, would need to take a closer look regarding the exact places and names.
val mismatches = list.mapIndexedNotNull { index, e -> | ||
val assertion = if (assertionCreatorOrNull != null) { | ||
container.collectBasedOnSubject(Some(e as E), assertionCreatorOrNull) | ||
} else { | ||
// TODO: assertionCreatorOrNull should be non-nullable, and this "to be null" should be a part of expectation | ||
assertionBuilder.createDescriptive(DescriptionBasic.TO_BE, Text.NULL) { | ||
e == null | ||
} | ||
} | ||
|
||
assertion.takeIf { mismatchIf(it.holds()) }?.let { | ||
assertionBuilder | ||
.feature | ||
.withDescriptionAndRepresentation(TranslatableWithArgs(INDEX, index), e) | ||
.withAssertion(it) | ||
.build() | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You should do the modification within createIndexAssertions and not here - I suggest you rename createIndexAssertions to createMismatch
as it is used only for this purpose
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Of course, it should replace the current createIndexAssertions
, however, I tried to implement something minimal to see what are other changes required.
One of the takeaways, for now, is the current implementation shows both successful and failing assertions, and it does not distinguish between successful and failing ones.
For instance login: "joe"
was successful, however, it was displayed the same as password: "qwerty"
which failed.
closing this as the issue as such will be resolved with the new reporter based on Proof. The reporting for the case in the issue will look as follows:
Stay tuned... |
Fixes #1359
I confirm that I have read the Contributor Agreements v1.0, agree to be bound on them and confirm that my contribution is compliant.