TUnit icon indicating copy to clipboard operation
TUnit copied to clipboard

Unclear precedence of AND and OR

Open vbreuss opened this issue 1 year ago • 6 comments

I couldn't find anything in the documentation with regards to the precedence between AND and OR.

Consider the following test:

[Test]
public async Task And_Or_Precedence_Test()
{
    char[] sut = "CD".ToCharArray();

    await Assert.That(sut)
        .Contains('A').And
        .Contains('B').Or
        .Contains('C').And
        .Contains('D');
}

I would have expected the test to fail, as I would expect the condition to be interpreted as (A && B) || (C && D), to be in line with the operator precedence in C#.

However, this test succeeds, because A && B || C && D seems to be interpreted as (((A && B) || C) && D).

vbreuss avatar Oct 13 '24 03:10 vbreuss

Did the analyzer kick in?

thomhurst avatar Oct 13 '24 06:10 thomhurst

No, I didn't see any analyzer...

vbreuss avatar Oct 13 '24 06:10 vbreuss

Hmm I'll need to check then.

There should be an analyzer flagging mixing of and+or..for the reason you mentioned, it can be confusing how the logic will evaluate.

So the analyzer allows chained ANDs or chained ORs, but should flag if a mix is used.

thomhurst avatar Oct 13 '24 06:10 thomhurst

Analyzer showing for me fine: image

thomhurst avatar Oct 14 '24 17:10 thomhurst

Hmm, after restarting Visual Studio, I could see the analyzer: image It was probably an issue with the preview version.

However, as this is only an indication (that could be turned off), wouldn't it make sense to make an explicit choice of precedence in these cases? Or state, that this is not supported and throw an exception when both are mixed, so as not to lead to false positives in tests?

vbreuss avatar Oct 14 '24 19:10 vbreuss

Probably throwing would be better, as:

await Assert.That(sut)
        .Contains('A')
        .And.Contains('B')
        .Or
        .Contains('C');
await Assert.That(sut)
        .Contains('A')
        .And
        .Contains('B')
        .Or.Contains('C');

Both are the exact same code, but due to the formatting/placement of it you might think it means something different to what it does.

thomhurst avatar Oct 14 '24 19:10 thomhurst