Skip to content

Conversation

@Serg046
Copy link
Contributor

@Serg046 Serg046 commented Nov 21, 2020

IMPORTANT

  • The code complies with the Coding Guidelines for C#.
  • The changes are covered by a new or existing set of unit tests which follow the Arrange-Act-Assert syntax such as is used in this example.
  • If the contribution adds a feature or fixes a bug, please update the release notes, which are published on the website.
  • If the contribution changes the public API the changes needs to be included by running AcceptApiChanges.ps1/AcceptApiChanges.sh.
  • If the contribution affects the documentation, please include your changes in this pull request so the documentation will appear on the website.

Fixes #1353

@Serg046 Serg046 changed the title Issue 1353 Some assertions are not including variable names in assertion message Nov 21, 2020
Copy link
Member

@dennisdoomen dennisdoomen left a comment

Choose a reason for hiding this comment

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

That's quite an impressive PR. To be fair, I would not have invested the time to support all the misuse of the language in your examples. But that's the awesomeness of the community ❤

}

[Fact]
public void When_variable_is_not_captured_it_should_use_the_variable_name()
Copy link
Member

Choose a reason for hiding this comment

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

🤔 I don't get this scenario.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It was added when I started with Mono.Cecil. That time such test was important, now it is not. I will just remove this test and maybe similar ones

Choose a reason for hiding this comment

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

I've removed this one - but I'm not sure what the similar ones that can be removed are

}

[Fact]
public void When_field_is_the_caller_it_should_use_the_field_name()
Copy link
Member

Choose a reason for hiding this comment

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

🙃 I think it's better to change the term caller into subject or something like that.

Choose a reason for hiding this comment

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

Done

}

[Fact]
public void When_method_name_contains_get_it_should_not_remove_the_prefix()
Copy link
Member

Choose a reason for hiding this comment

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

🤔 Why is this an expected scenario?
🙃 The name is rather difficult to read since you refer to some literal term. I would rephrase contains_get to contains_getter_prefix to keep it readable.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The whole test could be removed because the current code base just rely on symbols, no need to distinguish properties and methods

Choose a reason for hiding this comment

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

Done


// Assert
act.Should().Throw<XunitException>()
.WithMessage("*Expected foo.GetFoo(test1).GetFooStatic(\"test\"+2).GetFoo(foo.Field) to be <null>*");
Copy link
Member

Choose a reason for hiding this comment

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

🤔 I think it would be better to only capture the GetFoo(fool.Field), but I guess it's going to be too hard to figure that out.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think it is not that hard. We could look for the last dot which is not part of arguments list. The reason why I didn't do it like you suggest is that I saw the current behaviour better. Just let me know if you think it is worth doing. I can do it right here (guess it is better) or implement it as a separate PR.

Choose a reason for hiding this comment

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

@dennisdoomen I would be OK with leaving this as is as long as you are - I kind of like the extra context (although if it were too long via chained method calls, it could we unwieldy - then again with EF this could end up showing .ToList() which wouldn't be helpful).

}

[Fact]
public void When_method_contains_parameters_it_should_add_them_to_caller()
Copy link
Member

Choose a reason for hiding this comment

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

🔧 The proper term is arguments, not parameters.

Choose a reason for hiding this comment

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

Done

Result Handle(char symbol);
}

private class QuotesHandler : IHandler
Copy link
Member

Choose a reason for hiding this comment

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

🔧 I think it might be a good idea to move the CallerIdentifier and all this new code into a folder CallerIdentification. Especially because we also prefer to have separate files per class over private classes.

Choose a reason for hiding this comment

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

Done

}

var sb = new CallerStatementBuilder();
CallerStatementBuilder.Result state;
Copy link
Member

Choose a reason for hiding this comment

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

🔧 If your enum needs to be prefixed by another class, treating it as a nested type is not a good idea.

Choose a reason for hiding this comment

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

Done


public override string ToString() => statement.ToString();

public enum Result
Copy link
Member

Choose a reason for hiding this comment

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

🤔 I don't understand the different values. E.g. what's the difference between Done and Handled? Maybe adding some XML comments will help.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, I remember that I was not happy by this thing. The answer is in this method:

        public Result Append(string symbols)
        {
            Result result = Result.InProgress;
            using var symbolEnumerator = symbols.GetEnumerator();
            while (symbolEnumerator.MoveNext() && result != Result.Done)
            {
                result = Result.InProgress;
                using var handlerEnumerator = handlers.GetEnumerator();
                while (handlerEnumerator.MoveNext() && result == Result.InProgress)
                {
                    result = handlerEnumerator.Current.Handle(symbolEnumerator.Current);
                }
            }

            return result;
        }

I have 2 cycles and 2 flags for exit. I will try to refactor it somehow, anyway I need to move some things as suggested above.

Choose a reason for hiding this comment

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

@Serg046 Did you have any thoughts/suggestions you could share on this? I don't mind making the changes, there's just a lot going on 😛

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@mdentremont, the only suggestion is to refactor it somehow. I just remember that processing was line by line where Handled means that the line is processed and we need to switch next.

Choose a reason for hiding this comment

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

Ah no worries. I don't think it's all that bad as it stands - it takes a second to wrap your head around, but then it's decently straightforward.

If you have any refactoring ideas you'd like to apply, maybe just make them in a future PR 👍

return isQuoteContext ? Result.Handled : Result.InProgress;
}

private bool IsAtEscaped()
Copy link
Member

Choose a reason for hiding this comment

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

🔧 As mentioned before, I would rename this to IsVerbatim

Choose a reason for hiding this comment

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

Done

if (statement.Length > 1)
{
var idx = statement.Length - 1;
return statement[idx--] == '$'
Copy link
Member

Choose a reason for hiding this comment

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

❌ Please don't mix increments like these. People always forget in what order things happen.

Choose a reason for hiding this comment

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

Done

@dennisdoomen
Copy link
Member

@Serg046 did you give up on this?

@Serg046
Copy link
Contributor Author

Serg046 commented Dec 23, 2020

I am just waiting for the holidays. If you still think we could merge something like this, I will complete it soon.

@dennisdoomen
Copy link
Member

@jnyrup what do you think?

@jnyrup
Copy link
Member

jnyrup commented Dec 23, 2020

I think it looks quite interesting. I just haven't taken the time to digest this fully.

I was mostly concerned about other PRs keeping caller identification lazy.

@rygwdn
Copy link

rygwdn commented May 13, 2021

Is there still interest in this PR? I would love to see #1353 fixed!

@dennisdoomen
Copy link
Member

Is there still interest in this PR? I would love to see #1353 fixed!

If somebody is willing to finalize the PR, then yes.

Merge develop & address most PR feedback for issue fluentassertions#1353
Copy link
Member

@dennisdoomen dennisdoomen left a comment

Choose a reason for hiding this comment

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

👍🏻 Impressive piece of work
❌ Please make everything related to caller identification internal.

return isQuoteContext ? HandlerResult.Handled : HandlerResult.InProgress;
}

private bool IsVerbatim()
Copy link
Member

Choose a reason for hiding this comment

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

@$"" is also a valid interpolated verbatim string.

Choose a reason for hiding this comment

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

I think that's what it is doing?

Copy link
Member

Choose a reason for hiding this comment

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

Ahh sorry, I meant that $@"" is also a valid interpolated verbatim string.

Choose a reason for hiding this comment

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

ahh OK - I'll try to get this resolved today hopefully.

Choose a reason for hiding this comment

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

Done

* Better parameter checking of `MethodInfoSelectorAssertions` - [#1569](https://github.com/fluentassertions/fluentassertions/pull/1569)
* Better parameter checking of `XDocumentAssertions`, `XElementAssertions` and `XAttributeAssertions` - [#1564](https://github.com/fluentassertions/fluentassertions/pull/1564)
* In a chained assertion API call, a second call to `ForCondition` should not even evaluate its lambda when the previous assertion failed - [#1587](https://github.com/fluentassertions/fluentassertions/pull/1587)
* Improved caller name determination by supporting multiple lines, comments and semicolons - [#1435](https://github.com/fluentassertions/fluentassertions/pull/1435).
Copy link
Member

Choose a reason for hiding this comment

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

Beta 1 has shipped, this will be part of 6.0.0 xxx

Choose a reason for hiding this comment

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

Done

@mdentremont
Copy link

👍🏻 Impressive piece of work
❌ Please make everything related to caller identification internal.

Done

Matt d'Entremont added 3 commits June 17, 2021 20:10
- Add docs
- IHandler => IParsingStrategy
- Pass StringBuilder/statement in Parse method rather than handing it to
  strategy constructors (easier to follow)
- Handled => GoToNextSymbol
- strategies => priorityOrderedParsingStrategies to make it more clear
  that the order is important
- Having "WithMessage("*..*")" was causing failing tests to pass (this
  seems odd, maybe WithMessage isn't working correctly?)
Matt d'Entremont added 4 commits June 17, 2021 23:02
- note: a trailing whitespace character was auto-trimmed by my IDE, I
  left the change because it felt dirty :P
@mdentremont
Copy link

@dennisdoomen @jnyrup Thanks so much for the feedback you two!

While addressing the feedback, I noticed that the tests that did WithMessage("*...*") were being passed even though the parts inside the wildcards were not in the message (this sounds like a possible WithMessage bug?).

I also noticed some edge cases while reading through the code, so I added new tests to confirm my suspicions (the tests failed).

I've made a decent amount of refactoring, and have also fixed all of the broken tests (and of course addressed as much of the review feedback as I could, and replied where I couldn't).

Cheers!

Copy link
Member

@dennisdoomen dennisdoomen left a comment

Choose a reason for hiding this comment

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

Some unit tests are failing...

@dennisdoomen dennisdoomen requested a review from jnyrup June 29, 2021 06:48
Matt d'Entremont and others added 4 commits June 29, 2021 10:50
- I'm somewhat grasping for straws on this one, my IDE wants to suppress
  using ReSharper commments, and won't offer to suppress in this manner
Issue 1353 (hopefully the last set of changes)
internal class ShouldCallParsingStrategy : IParsingStrategy
{
private const string ShouldCall = ".Should()";
private const string ShouldCall = ".Should(";
Copy link
Member

Choose a reason for hiding this comment

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

Is there any disadvantage to using .Should( over .Should()?
I imagine Should is only called with an argument in our tests when we fake timing.

Copy link

@mdentremont mdentremont Jul 14, 2021

Choose a reason for hiding this comment

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

It think it seems reasonable. This way it also still works if somebody were to overload .Should via an extension method (not sure why they would though).

@jnyrup jnyrup merged commit 8d88ec7 into fluentassertions:develop Jul 19, 2021
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.

Some assertions are not including variable names in assertion message

5 participants