Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

implemented conditional OuterLoopAttribute #7370

Merged
merged 6 commits into from
May 13, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,19 @@ namespace Xunit
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, AllowMultiple = true)]
public class OuterLoopAttribute : Attribute, ITraitAttribute
{
public Type CalleeType { get; private set; }
public string[] ConditionMemberNames { get; private set; }

public OuterLoopAttribute() { }
public OuterLoopAttribute(string reason) { }
public OuterLoopAttribute(string reason, TestPlatforms platforms) { }
public OuterLoopAttribute(string reason, TargetFrameworkMonikers framework) { }
public OuterLoopAttribute(string reason, TestRuntimes runtimes) { }
public OuterLoopAttribute(string reason, TestPlatforms platforms = TestPlatforms.Any, TargetFrameworkMonikers framework = TargetFrameworkMonikers.Any, TestRuntimes runtimes = TestRuntimes.Any) { }
public OuterLoopAttribute(string reason, Type calleeType, params string[] conditionMemberNames)
{
CalleeType = calleeType;
ConditionMemberNames = conditionMemberNames;
}
}
}
50 changes: 49 additions & 1 deletion src/Microsoft.DotNet.XUnitExtensions/src/DiscovererHelpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using Xunit;

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

return true;
}

internal static IEnumerable<KeyValuePair<string, string>> EvaluateArguments(IEnumerable<object> ctorArgs,string category, int skipFirst=1)
{
Debug.Assert(ctorArgs.Count() >= 2);

TestPlatforms platforms = TestPlatforms.Any;
TargetFrameworkMonikers frameworks = TargetFrameworkMonikers.Any;
TestRuntimes runtimes = TestRuntimes.Any;
Type calleeType = null;
string[] conditionMemberNames = null;

foreach (object arg in ctorArgs.Skip(skipFirst)) // First argument is the issue number or reason.
{
if (arg is TestPlatforms)
{
platforms = (TestPlatforms)arg;
}
else if (arg is TargetFrameworkMonikers)
{
frameworks = (TargetFrameworkMonikers)arg;
}
else if (arg is TestRuntimes)
{
runtimes = (TestRuntimes)arg;
}
else if (arg is Type)
{
calleeType = (Type)arg;
}
else if (arg is string[])
{
conditionMemberNames = (string[])arg;
}
}

if (calleeType != null && conditionMemberNames != null)
{
if (DiscovererHelpers.Evaluate(calleeType, conditionMemberNames))
{
yield return new KeyValuePair<string, string>(XunitConstants.Category, category);
}
}
else if (DiscovererHelpers.TestPlatformApplies(platforms) &&
DiscovererHelpers.TestRuntimeApplies(runtimes) &&
DiscovererHelpers.TestFrameworkApplies(frameworks))
{
yield return new KeyValuePair<string, string>(XunitConstants.Category, category);
}
}
}
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using Xunit;
using Xunit.Abstractions;
using Xunit.Sdk;

Expand All @@ -25,52 +21,7 @@ public class ActiveIssueDiscoverer : ITraitDiscoverer
public IEnumerable<KeyValuePair<string, string>> GetTraits(IAttributeInfo traitAttribute)
{
IEnumerable<object> ctorArgs = traitAttribute.GetConstructorArguments();
Debug.Assert(ctorArgs.Count() >= 2);

string issue = ctorArgs.First().ToString();
TestPlatforms platforms = TestPlatforms.Any;
TargetFrameworkMonikers frameworks = TargetFrameworkMonikers.Any;
TestRuntimes runtimes = TestRuntimes.Any;
Type calleeType = null;
string[] conditionMemberNames = null;

foreach (object arg in ctorArgs.Skip(1)) // First argument is the issue number.
{
if (arg is TestPlatforms)
{
platforms = (TestPlatforms)arg;
}
else if (arg is TargetFrameworkMonikers)
{
frameworks = (TargetFrameworkMonikers)arg;
}
else if (arg is TestRuntimes)
{
runtimes = (TestRuntimes)arg;
}
else if (arg is Type)
{
calleeType = (Type)arg;
}
else if (arg is string[])
{
conditionMemberNames = (string[])arg;
}
}

if (calleeType != null && conditionMemberNames != null)
{
if (DiscovererHelpers.Evaluate(calleeType, conditionMemberNames))
{
yield return new KeyValuePair<string, string>(XunitConstants.Category, XunitConstants.Failing);
}
}
else if (DiscovererHelpers.TestPlatformApplies(platforms) &&
DiscovererHelpers.TestRuntimeApplies(runtimes) &&
DiscovererHelpers.TestFrameworkApplies(frameworks))
{
yield return new KeyValuePair<string, string>(XunitConstants.Category, XunitConstants.Failing);
}
return DiscovererHelpers.EvaluateArguments(ctorArgs, XunitConstants.Failing);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.

using System.Collections.Generic;
using System.Linq;
using Xunit.Abstractions;
using Xunit.Sdk;

Expand All @@ -20,7 +21,12 @@ public class OuterLoopTestsDiscoverer : ITraitDiscoverer
/// <returns>The trait values.</returns>
public IEnumerable<KeyValuePair<string, string>> GetTraits(IAttributeInfo traitAttribute)
{
yield return new KeyValuePair<string, string>(XunitConstants.Category, XunitConstants.OuterLoop);
IEnumerable<object> ctorArgs = traitAttribute.GetConstructorArguments();
if (ctorArgs.Count() < 2)
{
return new[] { new KeyValuePair<string, string>(XunitConstants.Category, XunitConstants.OuterLoop) };
}
return DiscovererHelpers.EvaluateArguments(ctorArgs, XunitConstants.OuterLoop);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.

using Xunit;
using Xunit.Sdk;

namespace Microsoft.DotNet.XUnitExtensions.Tests
{
Expand All @@ -24,6 +25,38 @@ public void ConditionalAttributeA()
s_conditionalFactExecuted = true;
}

[Fact]
[OuterLoop("never outer loop", TestPlatforms.Any & ~TestPlatforms.Any)]
public void NeverConditionalOuterLoopAttribute()
{
var method = System.Reflection.MethodBase.GetCurrentMethod();
var res = TraitHelper.GetTraits(method);

Assert.Empty(res);
}

[Fact]
[OuterLoop("always outer loop", TestPlatforms.Any)]
public void AlwaysConditionalOuterLoopAttribute()
{
var method = System.Reflection.MethodBase.GetCurrentMethod();
var res = TraitHelper.GetTraits(method);

Assert.Single(res);
Assert.Equal("outerloop", res[0].Value);
}

[Fact]
[OuterLoop("always outer loop")]
public void AlwaysOuterLoopAttribute()
{
var method = System.Reflection.MethodBase.GetCurrentMethod();
var res = TraitHelper.GetTraits(method);

Assert.Single(res);
Assert.Equal("outerloop", res[0].Value);
}

[ConditionalTheory(nameof(AlwaysTrue))]
[InlineData(1)]
[InlineData(2)]
Expand Down