需求
这是一个非常符合人类的逻辑的操作:忽略某些测试,除非我手动运行。
非常合理对吧?
对应当你测试一些有昂贵操作的行为时,这非常有用。比如你不能每次测试都请求某个收费的api吧,这样不光是效率问题,经费问题,还有可能因为网络的波动而导致测试失败。又比如当你在测试里写一些概念验证,比如往临时往数据库里插入某条数据,你总不可能每次测试都要运行吧。
这么一个简单的需求,xunit.net竟然选择了一个匪夷所思的实现方法,即彻底隐藏,无论如何也不能执行了。并且从2015年到现在(2021年)也坚持不改,大有一幅你打死我我也不改的架势。
这是一个多么愚蠢的设计,如果我真的需要永久的禁止这个测试,我直接删除掉不就行了,或者直接简单注释掉声明测试的注解,也要比这个方便的多。
[Fact]
public void TestS() {
1.Should().Be(1);
}
这样的一个测试,是改成
[Fact(Skip = "!2313")]
public void TestS() {
1.Should().Be(1);
}
容易,还是改成
//[Fact]
public void TestS() {
1.Should().Be(1);
}
容易? 我想答案显然易见。
而以前的Nunit则可以通过Explicit 注解完美实现。‘
怎么办
万万没想到,最后我还是用一个非常曲折的方式实现了这一需求
public class RunnableInDebugOnlyAttribute : FactAttribute {
public RunnableInDebugOnlyAttribute() {
if (!Debugger.IsAttached) {
Skip = "Only running in interactive mode.";
}
}
}
/// <summary>
/// Apply this attribute to your test method to specify a category.
/// </summary>
[TraitDiscoverer("Test.CategoryDiscoverer", "Test")]
[AttributeUsage(AttributeTargets.Method)]
class IgnoredAttribute : Attribute, ITraitAttribute {
public IgnoredAttribute() {
}
}
/// <summary>
/// Apply this attribute to your test method to specify a category.
/// </summary>
[TraitDiscoverer("Test.CategoryDiscoverer", "Test")]
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
class CategoryAttribute : Attribute, ITraitAttribute {
public CategoryAttribute(string category) {
}
}
/// <summary>
/// This class discovers all of the tests and test classes that have
/// applied the Category attribute
/// </summary>
public class CategoryDiscoverer : ITraitDiscoverer {
/// <summary>
/// Gets the trait values from the Category attribute.
/// </summary>
/// <param name="traitAttribute">The trait attribute containing the trait values.</param>
/// <returns>The trait values.</returns>
public IEnumerable<KeyValuePair<string, string>> GetTraits(IAttributeInfo traitAttribute) {
var ctorArgs = traitAttribute.GetConstructorArguments().ToList();
var category = "";
if (ctorArgs.Count == 0) {
var name = traitAttribute.ToString()?.Split(".").Last();
if (name.EndsWith("Attribute")) {
name = name.Remove(name.LastIndexOf("Attribute", StringComparison.Ordinal));
}
category = name;
}
else if (ctorArgs.Count == 1) {
category = ctorArgs[0].ToString();
}
else {
throw new Exception("unknown trait");
}
yield return new KeyValuePair<string, string>("Category", category);
}
}
尽管这种方式非常的麻烦
[RunnableInDebugOnly, Ignored]
public void TestS() {
1.Should().Be(1);
}
他需要配合Rider使用,在编辑器中设置Skip tests from categories 的值为 Ignored,即可在Rider中实现忽略掉指定的分类。
但是命令行怎么办?则使用 RunnableInDebugOnly注解来声明仅在Debug模式下执行。(当然也可以修改逻辑为某个环境变量存在时执行等)
结论
有些人吧,就是犟。臭毛病。
ref
xunit/xunit#701
https://youtrack.jetbrains.com/issue/RIDER-49097
需求
这是一个非常符合人类的逻辑的操作:忽略某些测试,除非我手动运行。
非常合理对吧?
对应当你测试一些有昂贵操作的行为时,这非常有用。比如你不能每次测试都请求某个收费的api吧,这样不光是效率问题,经费问题,还有可能因为网络的波动而导致测试失败。又比如当你在测试里写一些概念验证,比如往临时往数据库里插入某条数据,你总不可能每次测试都要运行吧。
这么一个简单的需求,
xunit.net竟然选择了一个匪夷所思的实现方法,即彻底隐藏,无论如何也不能执行了。并且从2015年到现在(2021年)也坚持不改,大有一幅你打死我我也不改的架势。这是一个多么愚蠢的设计,如果我真的需要永久的禁止这个测试,我直接删除掉不就行了,或者直接简单注释掉声明测试的注解,也要比这个方便的多。
这样的一个测试,是改成
容易,还是改成
容易? 我想答案显然易见。
而以前的
Nunit则可以通过Explicit注解完美实现。‘怎么办
万万没想到,最后我还是用一个非常曲折的方式实现了这一需求
尽管这种方式非常的麻烦
他需要配合
Rider使用,在编辑器中设置Skip tests from categories的值为Ignored,即可在Rider中实现忽略掉指定的分类。但是命令行怎么办?则使用
RunnableInDebugOnly注解来声明仅在Debug模式下执行。(当然也可以修改逻辑为某个环境变量存在时执行等)结论
有些人吧,就是犟。臭毛病。
ref
xunit/xunit#701
https://youtrack.jetbrains.com/issue/RIDER-49097