Skip to content

Commit c973cd2

Browse files
authored
implemented conditional OuterLoopAttribute (#7370)
implemented conditional OuterLoopAttribute, which conditionally sets `outerloop` category
1 parent 6b97586 commit c973cd2

File tree

5 files changed

+102
-52
lines changed

5 files changed

+102
-52
lines changed

src/Microsoft.DotNet.XUnitExtensions/src/Attributes/OuterLoopAttribute.cs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,19 @@ namespace Xunit
1313
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, AllowMultiple = true)]
1414
public class OuterLoopAttribute : Attribute, ITraitAttribute
1515
{
16+
public Type CalleeType { get; private set; }
17+
public string[] ConditionMemberNames { get; private set; }
18+
1619
public OuterLoopAttribute() { }
1720
public OuterLoopAttribute(string reason) { }
21+
public OuterLoopAttribute(string reason, TestPlatforms platforms) { }
22+
public OuterLoopAttribute(string reason, TargetFrameworkMonikers framework) { }
23+
public OuterLoopAttribute(string reason, TestRuntimes runtimes) { }
24+
public OuterLoopAttribute(string reason, TestPlatforms platforms = TestPlatforms.Any, TargetFrameworkMonikers framework = TargetFrameworkMonikers.Any, TestRuntimes runtimes = TestRuntimes.Any) { }
25+
public OuterLoopAttribute(string reason, Type calleeType, params string[] conditionMemberNames)
26+
{
27+
CalleeType = calleeType;
28+
ConditionMemberNames = conditionMemberNames;
29+
}
1830
}
1931
}

src/Microsoft.DotNet.XUnitExtensions/src/DiscovererHelpers.cs

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
using System.Collections.Generic;
66
using System.Diagnostics;
77
using System.Linq;
8-
using System.Reflection;
98
using System.Runtime.InteropServices;
109
using Xunit;
1110

@@ -59,5 +58,54 @@ internal static bool Evaluate(Type calleeType, string[] conditionMemberNames)
5958

6059
return true;
6160
}
61+
62+
internal static IEnumerable<KeyValuePair<string, string>> EvaluateArguments(IEnumerable<object> ctorArgs,string category, int skipFirst=1)
63+
{
64+
Debug.Assert(ctorArgs.Count() >= 2);
65+
66+
TestPlatforms platforms = TestPlatforms.Any;
67+
TargetFrameworkMonikers frameworks = TargetFrameworkMonikers.Any;
68+
TestRuntimes runtimes = TestRuntimes.Any;
69+
Type calleeType = null;
70+
string[] conditionMemberNames = null;
71+
72+
foreach (object arg in ctorArgs.Skip(skipFirst)) // First argument is the issue number or reason.
73+
{
74+
if (arg is TestPlatforms)
75+
{
76+
platforms = (TestPlatforms)arg;
77+
}
78+
else if (arg is TargetFrameworkMonikers)
79+
{
80+
frameworks = (TargetFrameworkMonikers)arg;
81+
}
82+
else if (arg is TestRuntimes)
83+
{
84+
runtimes = (TestRuntimes)arg;
85+
}
86+
else if (arg is Type)
87+
{
88+
calleeType = (Type)arg;
89+
}
90+
else if (arg is string[])
91+
{
92+
conditionMemberNames = (string[])arg;
93+
}
94+
}
95+
96+
if (calleeType != null && conditionMemberNames != null)
97+
{
98+
if (DiscovererHelpers.Evaluate(calleeType, conditionMemberNames))
99+
{
100+
yield return new KeyValuePair<string, string>(XunitConstants.Category, category);
101+
}
102+
}
103+
else if (DiscovererHelpers.TestPlatformApplies(platforms) &&
104+
DiscovererHelpers.TestRuntimeApplies(runtimes) &&
105+
DiscovererHelpers.TestFrameworkApplies(frameworks))
106+
{
107+
yield return new KeyValuePair<string, string>(XunitConstants.Category, category);
108+
}
109+
}
62110
}
63111
}
Lines changed: 1 addition & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,7 @@
11
// Licensed to the .NET Foundation under one or more agreements.
22
// The .NET Foundation licenses this file to you under the MIT license.
33

4-
using System;
54
using System.Collections.Generic;
6-
using System.Diagnostics;
7-
using System.Linq;
8-
using Xunit;
95
using Xunit.Abstractions;
106
using Xunit.Sdk;
117

@@ -25,52 +21,7 @@ public class ActiveIssueDiscoverer : ITraitDiscoverer
2521
public IEnumerable<KeyValuePair<string, string>> GetTraits(IAttributeInfo traitAttribute)
2622
{
2723
IEnumerable<object> ctorArgs = traitAttribute.GetConstructorArguments();
28-
Debug.Assert(ctorArgs.Count() >= 2);
29-
30-
string issue = ctorArgs.First().ToString();
31-
TestPlatforms platforms = TestPlatforms.Any;
32-
TargetFrameworkMonikers frameworks = TargetFrameworkMonikers.Any;
33-
TestRuntimes runtimes = TestRuntimes.Any;
34-
Type calleeType = null;
35-
string[] conditionMemberNames = null;
36-
37-
foreach (object arg in ctorArgs.Skip(1)) // First argument is the issue number.
38-
{
39-
if (arg is TestPlatforms)
40-
{
41-
platforms = (TestPlatforms)arg;
42-
}
43-
else if (arg is TargetFrameworkMonikers)
44-
{
45-
frameworks = (TargetFrameworkMonikers)arg;
46-
}
47-
else if (arg is TestRuntimes)
48-
{
49-
runtimes = (TestRuntimes)arg;
50-
}
51-
else if (arg is Type)
52-
{
53-
calleeType = (Type)arg;
54-
}
55-
else if (arg is string[])
56-
{
57-
conditionMemberNames = (string[])arg;
58-
}
59-
}
60-
61-
if (calleeType != null && conditionMemberNames != null)
62-
{
63-
if (DiscovererHelpers.Evaluate(calleeType, conditionMemberNames))
64-
{
65-
yield return new KeyValuePair<string, string>(XunitConstants.Category, XunitConstants.Failing);
66-
}
67-
}
68-
else if (DiscovererHelpers.TestPlatformApplies(platforms) &&
69-
DiscovererHelpers.TestRuntimeApplies(runtimes) &&
70-
DiscovererHelpers.TestFrameworkApplies(frameworks))
71-
{
72-
yield return new KeyValuePair<string, string>(XunitConstants.Category, XunitConstants.Failing);
73-
}
24+
return DiscovererHelpers.EvaluateArguments(ctorArgs, XunitConstants.Failing);
7425
}
7526
}
7627
}

src/Microsoft.DotNet.XUnitExtensions/src/Discoverers/OuterLoopTestsDiscoverer.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// The .NET Foundation licenses this file to you under the MIT license.
33

44
using System.Collections.Generic;
5+
using System.Linq;
56
using Xunit.Abstractions;
67
using Xunit.Sdk;
78

@@ -20,7 +21,12 @@ public class OuterLoopTestsDiscoverer : ITraitDiscoverer
2021
/// <returns>The trait values.</returns>
2122
public IEnumerable<KeyValuePair<string, string>> GetTraits(IAttributeInfo traitAttribute)
2223
{
23-
yield return new KeyValuePair<string, string>(XunitConstants.Category, XunitConstants.OuterLoop);
24+
IEnumerable<object> ctorArgs = traitAttribute.GetConstructorArguments();
25+
if (ctorArgs.Count() < 2)
26+
{
27+
return new[] { new KeyValuePair<string, string>(XunitConstants.Category, XunitConstants.OuterLoop) };
28+
}
29+
return DiscovererHelpers.EvaluateArguments(ctorArgs, XunitConstants.OuterLoop);
2430
}
2531
}
2632
}

src/Microsoft.DotNet.XUnitExtensions/tests/ConditionalAttributeTests.cs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// The .NET Foundation licenses this file to you under the MIT license.
33

44
using Xunit;
5+
using Xunit.Sdk;
56

67
namespace Microsoft.DotNet.XUnitExtensions.Tests
78
{
@@ -24,6 +25,38 @@ public void ConditionalAttributeA()
2425
s_conditionalFactExecuted = true;
2526
}
2627

28+
[Fact]
29+
[OuterLoop("never outer loop", TestPlatforms.Any & ~TestPlatforms.Any)]
30+
public void NeverConditionalOuterLoopAttribute()
31+
{
32+
var method = System.Reflection.MethodBase.GetCurrentMethod();
33+
var res = TraitHelper.GetTraits(method);
34+
35+
Assert.Empty(res);
36+
}
37+
38+
[Fact]
39+
[OuterLoop("always outer loop", TestPlatforms.Any)]
40+
public void AlwaysConditionalOuterLoopAttribute()
41+
{
42+
var method = System.Reflection.MethodBase.GetCurrentMethod();
43+
var res = TraitHelper.GetTraits(method);
44+
45+
Assert.Single(res);
46+
Assert.Equal("outerloop", res[0].Value);
47+
}
48+
49+
[Fact]
50+
[OuterLoop("always outer loop")]
51+
public void AlwaysOuterLoopAttribute()
52+
{
53+
var method = System.Reflection.MethodBase.GetCurrentMethod();
54+
var res = TraitHelper.GetTraits(method);
55+
56+
Assert.Single(res);
57+
Assert.Equal("outerloop", res[0].Value);
58+
}
59+
2760
[ConditionalTheory(nameof(AlwaysTrue))]
2861
[InlineData(1)]
2962
[InlineData(2)]

0 commit comments

Comments
 (0)