简体   繁体   English

我如何重写此foreach使其成为以前的Linq表达式的一部分?

[英]How can I rewrite this foreach to be a part of the previous Linq expression?

I am decorating my MSTest tests with custom attributes, SpecificationAttribute and VerificationAttribute which I later use to generate html test specification reports. 我正在用自定义属性, SpecificationAttributeVerificationAttribute装饰我的MSTest测试,以后将它们用于生成html测试规范报告。

The attributes look like this: 属性如下所示:

[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
public class SpecificationAttribute : Attribute
{
    public SpecificationAttribute(int step, string text)
    {
        Step = step;
        Text = text;
    }

    public int Step { get; set; }

    public string Text { get; set; }
}

I have written a test which asserts that a test method must have unique steps in the usage of the attributes. 我编写了一个测试,该测试断言测试方法在使用属性时必须具有唯一的步骤。 For example, the following usage fails my test, as it should: 例如,以下用法未能通过我的测试,因为它应该:

[Specification(1, "Click Button)]
[Verification(1, "Verify popup")]
[Specification(1, "Click close")]
[Verification(2, "Verify popup disappears")]

My test looks like this: 我的测试看起来像这样:

[TestMethod]
public void TestForNoDuplicateStepsOnMethod()
{
    var specificationMethods = Assembly.GetExecutingAssembly().GetTypes()
        .Where(type =>
            type.GetCustomAttribute<CompilerGeneratedAttribute>() == null &&
                type.GetCustomAttribute<TestClassAttribute>() != null)
        .SelectMany(type => type.GetMethods())
        .Where(methodInfo =>
            methodInfo.GetCustomAttribute<TestMethodAttribute>() != null &&
            methodInfo.GetCustomAttributes<SpecificationAttribute>().Any())
        .ToArray();

    foreach (var method in specificationMethods)
    {
        var specificationAttributes = method.GetCustomAttributes<SpecificationAttribute>();

        var duplicates = specificationAttributes.GroupBy(s => s.Step).Where(grp => grp.Count() > 1).SelectMany(x => x).ToList();

        if (duplicates.Any())
        {
            var initialMessage = $@"{Environment.NewLine}{method.DeclaringType}.{method.Name} contains several SpecificationAttribute with the same step number." + Environment.NewLine + Environment.NewLine;

            var message = duplicates.Aggregate(initialMessage, (s, attribute) => s + attribute.Step + " " + attribute.Text + Environment.NewLine);

            Assert.Fail(message);
        }
    }
}

I would like to rewrite the last part so that it becomes part of the Linq query. 我想重写最后一部分,使其成为Linq查询的一部分。 Is this possible? 这可能吗? Also, my current test only outputs one failed method. 另外,我当前的测试仅输出一种失败的方法。 It would be desireable if the Linq query could include all methods with failing conditions on unique step number. 如果Linq查询可以包括在唯一步骤号上具有失败条件的所有方法,那将是可取的。

if you dont need to do more operation on var specificationMethods you could try this: 如果您不需要对var SpecificationMethods进行更多操作,则可以尝试以下操作:

 [TestMethod]
    public void TestForNoDuplicateStepsOnMethod()
    {
        Assembly.GetExecutingAssembly().GetTypes()
            .Where(type =>
                type.GetCustomAttribute<CompilerGeneratedAttribute>() == null &&
                    type.GetCustomAttribute<TestClassAttribute>() != null)
            .SelectMany(type => type.GetMethods())
            .Where(methodInfo =>
                methodInfo.GetCustomAttribute<TestMethodAttribute>() != null &&
                methodInfo.GetCustomAttributes<SpecificationAttribute>().Any())
            .ToList().ForEach (method=> 
        {
            var specificationAttributes = method.GetCustomAttributes<SpecificationAttribute>();

            var duplicates = specificationAttributes.GroupBy(s => s.Step).Where(grp => grp.Count() > 1).SelectMany(x => x).ToList();

            if (duplicates.Any())
            {
                var initialMessage = $@"{Environment.NewLine}{method.DeclaringType}.{method.Name} contains several SpecificationAttribute with the same step number." + Environment.NewLine + Environment.NewLine;

                var message = duplicates.Aggregate(initialMessage, (s, attribute) => s + attribute.Step + " " + attribute.Text + Environment.NewLine);

                Assert.Fail(message);
            }
    }
  }
}

(Edited to fix the problem with positive tests) Try this but IMHO it is much harder to read. (经过编辑以通过积极的测试解决该问题)尝试此操作,但是恕我直言,它很难阅读。

[TestMethod]
public void TestForNoDuplicateStepsOnMethod()
{
    var errors = Assembly.GetExecutingAssembly().GetTypes()
        .Where(type =>
            type.GetCustomAttribute<CompilerGeneratedAttribute>() == null &&
                type.GetCustomAttribute<TestClassAttribute>() != null)
        .SelectMany(type => type.GetMethods())
        .Where(methodInfo =>
            methodInfo.GetCustomAttribute<TestMethodAttribute>() != null &&
            methodInfo.GetCustomAttributes<SpecificationAttribute>().Any())
        .Select(method =>
            method.GetCustomAttributes<SpecificationAttribute>()
        .GroupBy(s => s.Step)
            .Where(grp => grp.Count() > 1)
            .Select(x => x.Aggregate(
                $@"{Environment.NewLine}{method.DeclaringType}.{method.Name} contains several SpecificationAttribute with the same step number." 
                + Environment.NewLine,
                (s, attribute) => s + attribute.Step + " " + attribute.Text + Environment.NewLine))
                .Aggregate("", (s, message) => s + message))
            .Aggregate("", (s, message) => s + message);
        Assert.AreEqual("", errors);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM