xUnit 将特征添加到集合定义



在xUnit和Visual Studio中,我想在测试资源管理器中对标有[Collection("DB")]属性的测试进行分组。我只能按[Trait("Collection", "DB")]属性对测试进行分组。有没有办法将特定Trait分配给具有[Collection("DB")]属性的所有测试?

更新:我添加了 xUnit 问题 #799。

从 http://mac-blog.org.ua/xunit-category-trait/复制。

using System;
using System.Collections.Generic;
using System.Linq;
using Xunit;
using Xunit.Abstractions;
using Xunit.Sdk;
using XunitCategoriesSample.Traits;
namespace XunitCategoriesSample.Traits
{
    public class CategoryDiscoverer : ITraitDiscoverer
    {
        public const string KEY = "Category";
        public IEnumerable<KeyValuePair<string, string>> GetTraits(IAttributeInfo traitAttribute)
        {
            var ctorArgs = traitAttribute.GetConstructorArguments().ToList();
            yield return new KeyValuePair<string, string>(KEY, ctorArgs[0].ToString());
        }
    }
    //NOTICE: Take a note that you must provide appropriate namespace here
    [TraitDiscoverer("XunitCategoriesSample.Traits.CategoryDiscoverer", "XunitCategoriesSample")]
    [AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
    public class CategoryAttribute : Attribute, ITraitAttribute
    {
        public CategoryAttribute(string category) { }
    }
}
namespace XunitCategoriesSample
{
    public class Class1
    {
        [Fact]
        [Category("Jobsearcher")]
        public void PassingTest()
        {
            Assert.Equal(4, Add(2, 2));
        }
        [Fact]
        [Category("Employer")]
        public void FailingTest()
        {
            Assert.Equal(5, Add(2, 2));
        }
        int Add(int x, int y)
        {
            return x + y;
        }
    }
}

注意 您必须在 TraitDiscoverer 属性中提供正确的命名空间。

但这里还有更多,让我们制作更专业的属性:

public class JobsearcherTraitDiscoverer : ITraitDiscoverer
{
    public const string VALUE = "Jobsearcher";
    public IEnumerable<KeyValuePair<string, string>> GetTraits(IAttributeInfo traitAttribute)
    {
        yield return new KeyValuePair<string, string>(CategoryDiscoverer.KEY, VALUE);
    }
}
[TraitDiscoverer("XunitCategoriesSample.Traits.JobsearcherTraitDiscoverer", "XunitCategoriesSample")]
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
public class JobsearcherTraitAttribute : Attribute, ITraitAttribute
{
    public JobsearcherTraitAttribute()
    {
    }
}

因此,从现在开始,您只需键入[JobsearcherTrait]

链接:

https://github.com/xunit/xunit/issues/394 - 关于为什么 TraitAttribute 被标记为密封的讨论

https://github.com/xunit/samples.xunit/tree/master/TraitExtensibility - 按 xunit 示例如何创建自定义属性

https://github.com/wespday/CategoryTraits.Xunit2 - 再来一个样品

https://github.com/xunit/xunit/blob/47fdc2669ae6aa28f6d642e202840193dfc7dbd7/test/test.xunit.execution/Common/TraitHelperTests.cs - 实现自定义属性的 XUNIT 测试示例

在Xunit.Sdk.ITraitDiscoverer接口中,GetTraits方法的参数"traitAttribute"具有实际的属性值,但不幸的是,没有直接的方法可以获取它,因为Xunit.Abstractions.IAttributeInfo没有getter,这很奇怪。这只是另一个解决方案,无需调用 GetConstructorArguments()

我们需要的确切类别的枚举

public enum Category
{
    UiSmoke,
    ApiSmoke,
    Regression
}

自定义属性定义

[TraitDiscoverer("Automation.Base.xUnit.Categories.CategoryDiscoverer", "Automation.Base")]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true)]
public class TestCategoryAttribute : Attribute, ITraitAttribute
{
    public string Category { get; }
    public TestCategoryAttribute(Category category)
    {
        Category = category.ToString();
    }
}

这是类别解析器/发现者

public sealed class CategoryDiscoverer : ITraitDiscoverer
{
    public const string Key = "Category";
    public IEnumerable<KeyValuePair<string, string>> GetTraits(IAttributeInfo traitAttribute)
    {
        var category = traitAttribute.GetNamedArgument<string>(Key);
        yield return new KeyValuePair<string, string>(Key, category);
    }
}

这是我们需要知道 TestCategoryAttribute 类型中的确切属性名称的捕获,在发现器中,它使用 Key 常量定义。

无论如何,GetConstructorArguments()和GetNamedArgument()都是基于反射的,而发现器在每个测试运行后都会执行,这不是那么快。

你可以这样做:

enum Collection {
  DB,
  File,
  // Others
}

稍后在类或方法级别:

[Trait(nameof(Collection), nameof(Collection.DB))]

干净简单

最新更新