TUnit icon indicating copy to clipboard operation
TUnit copied to clipboard

Char Assertions

Open thomhurst opened this issue 8 months ago • 5 comments

Discussed in https://github.com/thomhurst/TUnit/discussions/2314

Originally posted by AnnaSasDev May 2, 2025 For a highly specific thing, whih might be better built differently but that is besides the point of this discussion, I wanted to do something like the folloing (tiny example):

char a = 'a'
await Assert.That(a).IsDigit()

But I didnt find any assertions for this already in TUnit, so I wanted to put out some feelers out if this is something that could be implemented? If so, I would love to work on it, and I would probably want to implement the ones that are direct takeovers from in the standard library on the char type, and their IsNot... variants:

  • IsAscii
  • IsAsciiDigit
  • IsAsciiLetterLower
  • IsAsciiLetterUpper
  • IsAsciiLetterOrDigit
  • IsAsciiHexDigit
  • IsAsciiHexDigitUpper
  • IsAsciiHexDigitLower
  • IsDigit
  • IsBetween
  • IsLetter
  • IsWhiteSpace
  • IsUpper
  • IsLower
  • IsPunctuation
  • IsLetterOrDigit
  • IsControl
  • IsNumber
  • IsSeparator
  • IsSurrogate
  • IsSymbol
  • IsHighSurrogate
  • IsLowSurrogate

thomhurst avatar May 02 '25 14:05 thomhurst

cc @AnnaSasDev

thomhurst avatar May 02 '25 14:05 thomhurst

I wonder if something like a generator couldnt do the bulk of the lifting for this, given I have just seen the other issue #2316 and #2318 where I could build a generator that would be used like the following (pseudo code):

[CreateAssertion(typeof(char), nameof(char.IsDigit), TypeOfAssertion.Is)]
public partial class CharIsExtensions{}

Which would generate something like (again pseudo)

public partial class CharIsExtensions{
   public static InvokableValueAssertionBuilder<char> IsDigit(this IValueSource<char> valueSource) {
        return valueSource.RegisterAssertion(new FuncValueAssertCondition<string, int>(0,
            (value, _, self) => {
                if (value is null) {
                    self.FailWithMessage("Actual char is null");
                    return false;
                }
                
                return value.IsDigit();
            },
            (s, _, _) => $"'{s}' was not a digit",
            $"to be digit")
            , []); }
}

and vice versa with a TypeOfAssertion.IsNot and maybe some extra params to make the return messages more verbose or not.

AnnaSasDev avatar May 02 '25 15:05 AnnaSasDev

That sounds interesting! I wouldn't be opposed to that!

Sounds like a lot more work up-front, but would be good going forwards for easily asserting on more in-built types.

thomhurst avatar May 02 '25 15:05 thomhurst

That sounds interesting! I wouldn't be opposed to that!

Sounds like a lot more work up-front, but would be good going forwards for easily asserting on more in-built types.

How "early" of an early pr draft do you want me to make, because just having tinkered with it for a second I already realize it will require quite a lot of input as to where to place the required attributes, what the project name will be, etc...

AnnaSasDev avatar May 02 '25 16:05 AnnaSasDev

Whenever ya like. Happy for a draft to be open whenever !

thomhurst avatar May 02 '25 16:05 thomhurst

This issue is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 5 days.

github-actions[bot] avatar Jun 02 '25 00:06 github-actions[bot]

This issue is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 5 days.

github-actions[bot] avatar Jul 06 '25 00:07 github-actions[bot]