Skip to content

Multiple ITraitAttributes are not honored via inheritance when a child class has one attribute and base class another #2186

@safern

Description

@safern

If you have a test setup like this:

[Trait("category", "failing")]
public abstract class BaseClassWithFailingCategory
{
    [Fact]
    public virtual void Test1()
    {
        Assert.False(true);
    }
}

[Trait("category", "foo")]
public class DerivedClassWithFooCategory : BaseClassWithFailingCategory
{
    [Fact]
    public void Test2()
    {
        Assert.False(true);
    }
}

and then run these tests with -notrait category=failing the tests under DerivedClassWithFooCategory will be executed. The only way to skip them, it would be to run them with -notrait category=foo or by adding a duplicate TraitAttribute into DerivedClassWithFooCategory that adds the failing category to it's traits.

Discovering: MyRunner.dll (method display = ClassAndMethod, method display options = None)
Discovered:  MyRunner.dll (found 2 of 2 test cases)
Starting:    MyRunner.dll
[FAIL] ConsoleApp1.DerivedClassWithFooCategory.Test1
Assert.False() Failure
Expected: False
Actual:   True
   at ConsoleApp1.BaseClassWithFailingCategory.Test1() in C:\Users\safern\source\repos\XUnitTestProject1\ConsoleApp1\Program.cs:line 74
[FAIL] ConsoleApp1.DerivedClassWithFooCategory.Test2
Assert.False() Failure
Expected: False
Actual:   True
   at ConsoleApp1.DerivedClassWithFooCategory.Test2() in C:\Users\safern\source\repos\XUnitTestProject1\ConsoleApp1\Program.cs:line 84
Finished:    MyRunner.dll

It seems like the intent to support this is there:

if (attributeUsage.Inherited && (attributeUsage.AllowMultiple || list == null))

And AttributeUsage data for ITraitAttribute allow's multiple and allows inheritance, so that condition should be true:

static readonly ConcurrentDictionary<Type, AttributeUsageAttribute> attributeUsageCache = new ConcurrentDictionary<Type, AttributeUsageAttribute>
{
[typeof(ITraitAttribute)] = new AttributeUsageAttribute(AttributeTargets.All) { AllowMultiple = true }
};

However I don't know why both traits are not added to tests under DerivedClassWithFooCategory

cc: @stephentoub @akoeplinger @ViktorHofer @bradwilson

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions