这是为什么承袭建立执行多次? [英] Why is this inherited Establish executed multiple times?

查看:106
本文介绍了这是为什么承袭建立执行多次?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的理解是,每个制定应该只执行一次,而下面的代码显示它执行多次。我们正在嵌套类提供一些分组,同时保持单元测试在一个文件中的主题。这似乎是它是一个错误。

My understand is that each Establish should only be executed once, but the code below shows it executing multiple times. We're nesting the classes to provide some grouping while keeping the unit tests for a Subject in one file. This seems like it is a bug.

我们正在使用machine.specifications.runner.resharper整形延伸和MSpec 0.9.1。

We're using the machine.specifications.runner.resharper Reshaper extension and MSpec 0.9.1.

[Subject(typeof(string))]
internal class EstablishRunTwice {
    Establish sharedContext = () => Console.WriteLine("Shared context");

    internal class ScenarioA : EstablishRunTwice {
        Establish scenarioAContext = () => Console.WriteLine("ScenarioA context");

        internal class ScenarioAVariation1 : ScenarioA {
            Because of = () => Console.WriteLine("ScenarioAVariation1 Because");

            It it1 = () => Console.WriteLine("ScenarioAVariation1 It1");

            It it2 = () => Console.WriteLine("ScenarioAVariation1 It2");
        }

        internal class ScenarioAVariation2 : ScenarioA {
            Because of = () => Console.WriteLine("ScenarioAVariation2 Because");

            It it1 = () => Console.WriteLine("ScenarioAVariation2 It1");

            It it2 = () => Console.WriteLine("ScenarioAVariation2 It2");
        }
    }

    internal class ScenarioB : EstablishRunTwice {
        Establish context = () => Console.WriteLine("ScenarioB context");

        Because of = () => Console.WriteLine("ScenarioB Because");

        It it1 = () => Console.WriteLine("ScenarioB It1");

        It it2 = () => Console.WriteLine("ScenarioB It2");
    }
}



结果是这样的ScenarioAVariation1:

The result is this for ScenarioAVariation1:

Shared context
Shared context
ScenarioA context
Shared context
Shared context
ScenarioA context
ScenarioAVariation1 Because
ScenarioAVariation1 It1
ScenarioAVariation1 It2

当我们使用NUnit做我们自己的自定义上下文规范的框架,我们得到了周围的运行通过确保所有的子类是抽象的(在这种情况下,EstablishRunTwice和ScenarioA是抽象的)NUnit的问题,但MSpec抛出一个错误试图这样做。

When we were doing our own custom context specification framework using NUnit, we got around issues with the NUnit running by making sure all subclasses were abstract (in this case, EstablishRunTwice and ScenarioA would be abstract), but MSpec throws an error attempting to do so.

推荐答案

这是构建的东西真正令人困惑的方式 - 聪明,但也许有点的的聪明。我觉得很难阅读和理解的目的。事实上,我甚至不能开始想象,编译器会与继承结构做的,所以我的无法的理解意图。我想,也许你过这种思维

That's a really confusing way to structure things - clever, but perhaps a bit too clever. I find it hard to read and understand the intent. In fact, I can't even begin to imagine what the compiler would do with that inheritance structure and therefore I can't understand the intent. I think maybe you're over-thinking this.

因此,让我看看, ScenarioA 不仅是嵌套在 EstablishRunTwice ,也可以从它继承。这是否意味着它继承嵌套自身拷贝一路下跌到无穷大?然后, ScenarioB 所有的继承!我的头刚刚发生爆炸。我并不感到惊讶,你会比较混乱的结果。这是什么嵌套的真正的给你?它使代码更可读或更容易维护?我不相信它。

So let me see, ScenarioA is not only nested in EstablishRunTwice, but also inherits from it. Does that mean it inherits nested copies of itself all the way down to infinity? And then, ScenarioB inherits from all of that! My head has just exploded. I'm not surprised you get confusing results. What does that nesting really give you? Does it make the code more readable or easier to maintain? I'm not convinced it does.

使用KISS原则。做事情的方式,一般是把每个上下文在其自己的类,没有嵌套;只需使用文件组相关的测试,你也可以使用关注参数在 [主题] 属性作为另一个分组方式。您可以从其他上下文继承如果是有道理的,但MSpec工作了几年后,我慢慢来,太多的继承会损害可读性,使测试代码更粘稠的结论,所以明智地使用继承。

Use the KISS principle. The normal way of doing things is to put each context in its own class, no nesting; just use files to group related tests, and you can also use the Concern argument in the [Subject] attribute as another way of grouping. You can inherit from other contexts if that makes sense, but after working with MSpec for a couple of years, I'm slowly coming to the conclusion that too much inheritance can harm readability and make the test code more viscous, so use inheritance wisely.

更新的:已经反映在我的觉得的你正试图实现的时间长一点,我怀疑你正试图重新发明的行为的。这也许是MSpec的不良记录,并了解功能,该功能允许您定义一组可以在后面的多个测试环境中应用共同的行为。这听起来像不像你想达到什么样的?这里是行为的一个例子:

Update: Having reflected on what I think you are trying to achieve for a bit longer, I suspect you are trying to re-invent behaviours. This is perhaps a poorly documented and understood feature of MSpec, which lets you define a set of common behaviours that can later be applied in multiple test contexts. Does that sound like what you are trying to achieve? Here's an example of behaviours:

[Behaviors]
internal class DenebRightAscension
    {
    It should_have_20_hours_ = () => UUT.Degrees.ShouldEqual(20u);
    It should_have_41_minutes = () => UUT.Minutes.ShouldEqual(41u);
    It should_have_59_seconds = () => UUT.Seconds.ShouldEqual(59u);
    protected static Bearing UUT;
    }


[Subject(typeof(HourAngle), "sexagesimal")]
internal class when_converting_hour_angle_to_sexagesimal
{
    Because of = () =>
    {
        RaDeneb = 20.6999491773451;
        UUT = new Bearing(RaDeneb);
    };

    Behaves_like<DenebRightAscension> deneb;

    protected static Bearing UUT;
    static double RaDeneb;
}

[Subject(typeof(Bearing), "sexagesimal")]
internal class when_converting_to_sexagesimal
    {
    Because of = () =>
        {
        RaDeneb = 20.6999491773451;
        UUT = new Bearing(RaDeneb);
        };

    Behaves_like<DenebRightAscension> deneb;

    protected static Bearing UUT;
    static double RaDeneb;
    }

请注意,在行为字段由名称匹配,而不是由任何一种继承。因此,行为神奇知道我是什么意思UUT即使类没有丝毫关系。

Note that in behaviours fields are matched by name, not by any kind of inheritance. So the behaviour magically knows what I mean by 'UUT' even though the classes are in no way related.

这篇关于这是为什么承袭建立执行多次?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆