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

xunit.net 一个简单的忽略测试都做不好 #56

Open
ohroy opened this issue Sep 22, 2021 · 0 comments
Open

xunit.net 一个简单的忽略测试都做不好 #56

ohroy opened this issue Sep 22, 2021 · 0 comments

Comments

@ohroy
Copy link
Owner

ohroy commented Sep 22, 2021

需求

这是一个非常符合人类的逻辑的操作:忽略某些测试,除非我手动运行。
非常合理对吧?
对应当你测试一些有昂贵操作的行为时,这非常有用。比如你不能每次测试都请求某个收费的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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant