Skip to content

Instantly share code, notes, and snippets.

@Wind010
Created December 16, 2022 01:40
Show Gist options
  • Select an option

  • Save Wind010/439249944caed68619e6626f67b48fb8 to your computer and use it in GitHub Desktop.

Select an option

Save Wind010/439249944caed68619e6626f67b48fb8 to your computer and use it in GitHub Desktop.
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
namespace CommonTests.Attributes
{
/// <summary>
/// Abstract base class for use with TestMethodWithIgnoreIfSupportAttribute.cs.
/// Interfaces don't
/// </summary>
public abstract class BaseIgnoreIfAttribute: Attribute
{
/// <summary>
/// The criteria upon which test is ignored/skipped.
/// </summary>
public string IgnoreCriteria { get; protected set; }
/// <summary>
/// The details as to why the test was ignored/skipped.
/// </summary>
public string SkipDetails { get; protected set; }
internal virtual bool ShouldIgnore(ITestMethod testMethod)
{
throw new NotImplementedException();
}
}
}
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Linq;
namespace CommonTests.Attributes
{
/// <summary>
/// An extension to the [Ignore] attribute. Instead of using test lists / test categories to conditionally
/// skip tests, allow a [TestClass] or [TestMethod] to specify a method to run. If the method returns
/// `true` the test method will be skipped. The "ignore criteria" method must be `static`, return a single
/// `bool` value, and not accept any parameters. By default, it is named "IgnoreIf".
/// </summary>
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false,
Inherited = true)]
public class IgnoreIfEnvironmentIsAttribute : BaseIgnoreIfAttribute
{
/// <summary>
/// The environments in which this test should not run. Comma separated.
/// </summary>
public IgnoreIfEnvironmentIsAttribute(string allowedEnvironments = "Local,Development")
{
IgnoreCriteria = allowedEnvironments;
}
internal override bool ShouldIgnore(ITestMethod testMethod)
{
var environments = IgnoreCriteria.Split(',');
if (environments.Contains(Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT")
, StringComparer.OrdinalIgnoreCase))
{
return true;
}
SkipDetails = $"Test is expected to run with ASPNETCORE_ENVIRONMENT={IgnoreCriteria}.";
return false;
}
}
}
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Linq;
namespace CommonTests.Attributes
{
/// <summary>
/// An extension to the [Ignore] attribute. Instead of using test lists / test categories to conditionally
/// skip tests, allow a [TestClass] or [TestMethod] to specify a method to run. If the method returns
/// `true` the test method will be skipped. The "ignore criteria" method must be `static`, return a single
/// `bool` value, and not accept any parameters. By default, it is named "IgnoreIf".
/// </summary>
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false,
Inherited = true)]
public class RunIfEnvironmentIsAttribute : BaseIgnoreIfAttribute
{
/// <summary>
/// The environments in which this test should run. Comma separated.
/// </summary>
public RunIfEnvironmentIsAttribute(string notAllowedEnvironments = "Local,Development")
{
IgnoreCriteria = notAllowedEnvironments;
}
internal override bool ShouldIgnore(ITestMethod testMethod)
{
var environments = IgnoreCriteria.Split(',');
if (environments.Contains(Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT")
, StringComparer.OrdinalIgnoreCase))
{
SkipDetails = $"Test is expected to run with ASPNETCORE_ENVIRONMENT={IgnoreCriteria}.";
return false;
}
return true;
}
}
}
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Collections.Generic;
using System.Reflection;
namespace CommonTests.Attributes
{
// Based off https://matt.kotsenas.com/posts/ignoreif-mstest
/// <summary>
/// An extension to the [TestMethod] attribute. It walks the method and class hierarchy looking
/// for an [IgnoreIf] attribute. If one or more are found, they are each evaluated, if the attribute
/// returns `true`, evaluation is short-circuited, and the test method is skipped.
/// </summary>
public class TestMethodWithIgnoreIfSupportAttribute : TestMethodAttribute
{
public override TestResult[] Execute(ITestMethod testMethod)
{
var ignoreAttributes = FindAttributes(testMethod);
// Evaluate each attribute, and skip if one returns `true`
foreach (var ignoreAttribute in ignoreAttributes)
{
if (ignoreAttribute.ShouldIgnore(testMethod))
{
return new[]
{
new TestResult
{
Outcome = UnitTestOutcome.Inconclusive,
TestFailureException = new AssertInconclusiveException(ignoreAttribute.SkipDetails)
}
};
}
}
return base.Execute(testMethod);
}
private IEnumerable<BaseIgnoreIfAttribute> FindAttributes(ITestMethod testMethod)
{
// Look for an [IgnoreIf] on the method, including any virtuals this method overrides
var ignoreAttributes = new List<BaseIgnoreIfAttribute>();
ignoreAttributes.AddRange(testMethod.GetAttributes<BaseIgnoreIfAttribute>(inherit: true));
// Walk the class hierarchy looking for an [IgnoreIf] attribute
var type = testMethod.MethodInfo.DeclaringType;
while (type != null)
{
ignoreAttributes.AddRange(type.GetCustomAttributes<BaseIgnoreIfAttribute>(inherit: true));
type = type.DeclaringType;
}
return ignoreAttributes;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment