3053 - Conversion from TestCase string parameter to DateTimeOffset#3098
3053 - Conversion from TestCase string parameter to DateTimeOffset#3098rprouse merged 12 commits intonunit:masterfrom
Conversation
| /// <returns> | ||
| /// <c>true</c> if <paramref name="value"/> was converted and <paramref name="convertedValue"/> should be used; | ||
| /// <c>false</c> is no conversion was applied and <paramref name="convertedValue"/> should be ignored | ||
| /// </returns> |
There was a problem hiding this comment.
This xmldoc comment was copied over from TestCaseAttribute's "PerformSpecialConversion"
https://github.com/nunit/nunit/pull/3098/files#diff-012b7fc50160d70b26586addebf7ce1fL395
ChrisMaddock
left a comment
There was a problem hiding this comment.
Thanks for putting this together @stevenaw - sorry it's taken a while to review, it's not a nice part of the codebase to look at! 😅 Left a few comments - this will also need a second review from another member of @nunit/framework-team. 🙂
| { | ||
| argAsTargetType = null; | ||
| if (arg == null) | ||
| return false; |
There was a problem hiding this comment.
Note for other reviewers: the change in logic took me a bit of time to get my head around here - previously this would always return false for null - it will now return true if the arg is null AND the type is nullable. I can't see anywhere this would cause a problem.
| // Convert.ChangeType doesn't work for TimeSpan from string | ||
| if ((targetType == typeof(TimeSpan) || targetType == typeof(TimeSpan?)) && arg is string) | ||
| { | ||
| argAsTargetType = TimeSpan.Parse((string)arg); |
There was a problem hiding this comment.
Re: Your comment about CultureInvariant - good call. I'd consider this a 'bug' - hopefully not too many people will have come to rely on the behaviour! We discussed this in more detail a while back here: #2008
| } | ||
|
|
||
| [Test] | ||
| public void CanConvertIntToDecimal([Values(12)]decimal x) |
There was a problem hiding this comment.
Note to future reviewers: These three 'removed' tests had just been combined into a single test on line 94. Seems fine to me. 👍
|
Thanks for the review @ChrisMaddock ! |
|
Don’t worry - it’s taken me over a month to get round to looking at this! 😅 enjoy New Years! |
|
Thanks for the feedback @jnm2 ! |
Add tests Add TypeConverter for netstandard 1.4
…e from int support to RangeAttribute
4d4ff77 to
f4f22f3
Compare
|
|
||
| // See XML docs for the ParamAttributeTypeConversions class. | ||
| private static readonly Type[] Int32RangeConvertibleToParameterTypes = { typeof(int), typeof(sbyte), typeof(byte), typeof(short), typeof(decimal) }; | ||
| private static readonly Type[] Int32RangeConvertibleToParameterTypes = { typeof(int), typeof(sbyte), typeof(byte), typeof(short), typeof(decimal), typeof(long), typeof(double) }; |
There was a problem hiding this comment.
NOTE: this change is required based on this line: https://github.com/nunit/nunit/pull/3098/files#diff-64bcafa7925c912b792f366a7971facfR121
This was a hidden inconsistency between our attributes. TestCaseAttribute allowed int -> long and int -> double but RangeAttribute did not explicitly support the conversion. Now they are allowed on both (in nullable and non-nullable forms)
There was a problem hiding this comment.
This is good, we want this. The idea behind this list of special-cased conversions is to emulate C#'s implicit casts.
|
Thanks for taking the time to review this earlier @jnm2 |
|
|
||
| // See XML docs for the ParamAttributeTypeConversions class. | ||
| private static readonly Type[] Int32RangeConvertibleToParameterTypes = { typeof(int), typeof(sbyte), typeof(byte), typeof(short), typeof(decimal) }; | ||
| private static readonly Type[] Int32RangeConvertibleToParameterTypes = { typeof(int), typeof(sbyte), typeof(byte), typeof(short), typeof(decimal), typeof(long), typeof(double) }; |
There was a problem hiding this comment.
This is good, we want this. The idea behind this list of special-cased conversions is to emulate C#'s implicit casts.
|
@rprouse Okay to merge for 3.12? |
|
I'll probably have time to look at this during the weekend. |
rprouse
left a comment
There was a problem hiding this comment.
Thanks for doing all this. I apologize that it took so long to review and merge, everyone on the team has been pretty busy with work lately so we haven't been doing as good a job reviewing as we should. Thanks for being patient.
|
Thanks! |
Fixes #3053
Updates
TestCaseAttributeto convertStringparameter toDateTimeOffsetI noticed the existing type conversion logic wasn't applied to params arrays, so I expanded it to work there too (I added a test for the existing TimeSpan logic for that too).
Added Dependencies
NET Standard 1.4
System.ComponentModel.TypeConverterScope Creep
I also noticed that the
ValuesAttributehandles most type conversions theTestCaseAttributedoes, so I added thisstring -> DateTimeOffsetconversion for it too. I also consolidated some of the type conversion logic between them (TestCaseAttributenow usesParamAttributeTypeConversionstoo). In the process, I had to updateParamAttributeTypeConversionsto map values to nullable primitives, it looks like previously we only mapped null to nullable primitives.One potential change to existing behaviour is that
TestCaseAttributepreviously calledTimeSpan.Parse()without providing a culture, whereas it looked like most other conversions usedCultureInfo.InvariantCulture(including whenValuesAttributeconverts a string to aTimeSpan. So in the process of centralizing the type conversion logic,TestCaseAttributenow also usesCultureInfo.InvariantCulturewhen converting a string to aTimeSpan.In keeping with comment #3053 (comment),
TimeSpannow also gets converted usingTypeConverterinstead ofConvert, as it does not implemementIConvertible.Since this is a bit more than just "Conversion from TestCase string parameter to DateTimeOffset" covered in this PR, let me know if a second GH issue and/or PR should be required for the broader changes.