Add test coverage for platform attribute behaviours#5204
Conversation
4916196 to
00400de
Compare
There was a problem hiding this comment.
@stevenaw What you test is the behaviour of your ObservableAttribute, not the PlatformAttribute. The latter doesn't use properties to checking on the properties at the fixture and test level tests how NUnit deals with properties there, not how the PlatformAttribute works.
Your ChildTestWithoutAttribute_DoesntExplicitlyInheritPlatforms is wrong.
PlatformAttribute on a (base) Fixture mark the test as non-runnable.
The actual unit test needs to check if the test is runnable based upon the platform passed in.
You can either change the expected result based upon the real platform the test is running on, e.g. if running on Linux, the Windows test should be NotRunnable and vice versa.
Alternatively, to bypass the actual Platform in the PlatformHelper, we need to allow a unit test to change the IsPlatformSupported method behaviour to a controlled one supplied by the test.
One way with your new dictionary is to add a method that adds dummy entries to the PlatformChecks dictionary which you then use in your tests.
|
Thanks @manfred-brands My original comment in #5166 and intent here was not to test the run/skip check itself, but rather the relationship between a fixture and tests with regards to this attribute. In particular, that the configuration applied to a fixture is completely independent of that applied to a test method. The run/skip check is then, of course, derived from that however we already have quite good coverage of those checks here: https://github.com/nunit/nunit/blob/main/src/NUnitFramework/tests/Internal/PlatformDetectionTests.cs That's also why I felt it important to write I can try your suggestion to update the tests to probe more directly for the run/skip check by substituting dummy values into the static |
|
@manfred-brands I've pushed a commit which I think makes the changes you were asking for. It required disabling parallelization of these tests as well making changes to NUnit itself to remove the |
|
|
||
| private static readonly Dictionary<string, Func<OSPlatform, bool>> PlatformChecks = | ||
| #pragma warning disable IDE0044 // Add readonly modifier | ||
| #pragma warning disable IDE1006 // Naming Styles |
There was a problem hiding this comment.
I've left these suppressions in like this temporarily until we confirm if we want to go in this direction. If we went ahead then I'd fix the underlying formatting issue
There was a problem hiding this comment.
No I wasn't thinking of completely replacing the dictionary.
More of adding non-standard entries.
That way it won't affect the standard operation
manfred-brands
left a comment
There was a problem hiding this comment.
I have added 3 commits.
- Using test specific platforms.
- Add test on real platforms.
- Add tests using Excludes
Only thing left is the test naming.
Even though the attribute is separately applied to the fixture and the test, if the fixture is not runnable, the test will not be run, regardless of the test attributes.
So the attribute on the fixture is implicitly inherited.
|
|
||
| private static readonly Dictionary<string, Func<OSPlatform, bool>> PlatformChecks = | ||
| #pragma warning disable IDE0044 // Add readonly modifier | ||
| #pragma warning disable IDE1006 // Naming Styles |
There was a problem hiding this comment.
No I wasn't thinking of completely replacing the dictionary.
More of adding non-standard entries.
| namespace NUnit.TestData | ||
| { | ||
| [ObservablePlatform(Includes = [PlatformNames.DotNET])] | ||
| [Platform(Includes = [PlatformNames.Win])] |
There was a problem hiding this comment.
I was thinking of using non-standard platforms not affecting any other test.
| [OneTimeSetUp] | ||
| public void OneTimeSetUp() | ||
| { | ||
| _platformField = typeof(PlatformHelper).GetField("PlatformChecks", BindingFlags.Static | BindingFlags.NonPublic)!; |
There was a problem hiding this comment.
If we make the field internal we don't have to resort to reflection.
There was a problem hiding this comment.
Thanks for your change. I admit I usually try to avoid modifying the system under test just to expose things for testing, but I'm alright with this approach.
| Assert.That(testMethod.RunState, Is.EqualTo(RunState.Runnable)); | ||
| Assert.That(fixture.RunState == RunState.Runnable, Is.EqualTo(allowOS)); |
There was a problem hiding this comment.
General question: Why would a testMethod be Runnable when the fixture is not?
There was a problem hiding this comment.
I've always understood this to be an implementation detail. TestSuite and TestMethod both implement ITest, and the IApplyToTest interface in turn applies only to the ITest which it has been decorated with. I understand the framework should then account for these varying RunStates when attempting to run a test method where the suite is "Skipped" though I admit I haven't explicitly checked that condition.
There is a bit more discussion on the nuance in #2936 as it relates to properties of tests. The best single comment I could find there to explain is Charlie's comment here: #2936 (comment)
|
Thanks for your changes and approval here @manfred-brands . No concerns from me with what you've pushed either. |
Fixes #5168
A doc update PR will also be required before both can be reviewed