Skip to content

3053 - Conversion from TestCase string parameter to DateTimeOffset#3098

Merged
rprouse merged 12 commits intonunit:masterfrom
stevenaw:3053/datetimeoffset
Apr 28, 2019
Merged

3053 - Conversion from TestCase string parameter to DateTimeOffset#3098
rprouse merged 12 commits intonunit:masterfrom
stevenaw:3053/datetimeoffset

Conversation

@stevenaw
Copy link
Copy Markdown
Member

@stevenaw stevenaw commented Nov 26, 2018

Fixes #3053

Updates TestCaseAttribute to convert String parameter to DateTimeOffset
I 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.TypeConverter

Scope Creep

I also noticed that the ValuesAttribute handles most type conversions the TestCaseAttribute does, so I added this string -> DateTimeOffset conversion for it too. I also consolidated some of the type conversion logic between them (TestCaseAttribute now uses ParamAttributeTypeConversions too). In the process, I had to update ParamAttributeTypeConversions to map values to nullable primitives, it looks like previously we only mapped null to nullable primitives.

One potential change to existing behaviour is that TestCaseAttribute previously called TimeSpan.Parse() without providing a culture, whereas it looked like most other conversions used CultureInfo.InvariantCulture (including when ValuesAttribute converts a string to a TimeSpan. So in the process of centralizing the type conversion logic, TestCaseAttribute now also uses CultureInfo.InvariantCulture when converting a string to a TimeSpan.

In keeping with comment #3053 (comment), TimeSpan now also gets converted using TypeConverter instead of Convert, as it does not implemement IConvertible.

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.

/// <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>
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Copy link
Copy Markdown
Member

@ChrisMaddock ChrisMaddock left a comment

Choose a reason for hiding this comment

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

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. 🙂

Comment thread src/NUnitFramework/framework/nunit.framework.csproj
{
argAsTargetType = null;
if (arg == null)
return false;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

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.

Comment thread src/NUnitFramework/framework/nunit.framework.csproj
// Convert.ChangeType doesn't work for TimeSpan from string
if ((targetType == typeof(TimeSpan) || targetType == typeof(TimeSpan?)) && arg is string)
{
argAsTargetType = TimeSpan.Parse((string)arg);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

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

Comment thread src/NUnitFramework/tests/Attributes/ValuesAttributeTests.cs
}

[Test]
public void CanConvertIntToDecimal([Values(12)]decimal x)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Note to future reviewers: These three 'removed' tests had just been combined into a single test on line 94. Seems fine to me. 👍

Comment thread src/NUnitFramework/framework/Attributes/TestCaseAttribute.cs Outdated
@stevenaw
Copy link
Copy Markdown
Member Author

Thanks for the review @ChrisMaddock !
I gave a quick reply to a question, but it might be a few days until I can parse and respond to the rest of the review. Thanks for pointing out the nuspec thing though!

@ChrisMaddock
Copy link
Copy Markdown
Member

Don’t worry - it’s taken me over a month to get round to looking at this! 😅 enjoy New Years!

Comment thread src/NUnitFramework/framework/Internal/ParamAttributeTypeConversions.cs Outdated
Comment thread src/NUnitFramework/framework/Internal/ParamAttributeTypeConversions.cs Outdated
@stevenaw
Copy link
Copy Markdown
Member Author

Thanks for the feedback @jnm2 !
I'm on vacation right now, but should be able to get to this within a week or two

@stevenaw stevenaw force-pushed the 3053/datetimeoffset branch from 4d4ff77 to f4f22f3 Compare February 18, 2019 21:59

// 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) };
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

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)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This is good, we want this. The idea behind this list of special-cased conversions is to emulate C#'s implicit casts.

@stevenaw
Copy link
Copy Markdown
Member Author

Thanks for taking the time to review this earlier @jnm2
I'm unable to update the labels on this PR, but if you have time to re-review, I think I've incorporated all your suggestions.

jnm2
jnm2 previously approved these changes Mar 21, 2019
Comment thread src/NUnitFramework/framework/Attributes/TestCaseAttribute.cs Outdated

// 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) };
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This is good, we want this. The idea behind this list of special-cased conversions is to emulate C#'s implicit casts.

@jnm2 jnm2 requested a review from a team March 21, 2019 00:54
@jnm2 jnm2 requested a review from a team March 22, 2019 00:03
@jnm2
Copy link
Copy Markdown
Contributor

jnm2 commented Apr 24, 2019

@rprouse Okay to merge for 3.12?

@mikkelbu
Copy link
Copy Markdown
Member

I'll probably have time to look at this during the weekend.

Copy link
Copy Markdown
Member

@rprouse rprouse left a comment

Choose a reason for hiding this comment

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

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.

@rprouse rprouse merged commit 580a1ab into nunit:master Apr 28, 2019
@stevenaw
Copy link
Copy Markdown
Member Author

Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Conversion from TestCase string parameter to DateTimeOffset

5 participants