3 Stimmen

Gibt es Verbesserungsvorschläge für diesen Stil für BDD/TDD?

Ich war Basteln mit tun die Setups mit unserer Einheit Test Spezifikationen, die wie gehen

Spezifikation für SUT, wenn Verhalten X in Szenario Y auftritt Gegeben, dass dieses Ding Und auch diese andere Sache Wenn ich X tue... Dann sollte es ... Und es soll auch ...

Ich wickelte jeden der Schritte des GivenThat in Aktionen... jede Rückmeldung, ob die Trennung mit Aktionen gut / schlecht / oder besser Weg, um die GivenThat klar zu machen ist?

        /// <summary>
        /// Given a product is setup for injection
        ///     And Product Image Factory Is Stubbed();
        ///     And Product Size Is Stubbed();
        ///     And Drawing Scale Is Stubbed();
        ///     And Product Type Is Stubbed();
        /// </summary>
        protected override void GivenThat()
        {
            base.GivenThat();

            Action givenThatAProductIsSetupforInjection = () =>
              {
                  var randomGenerator = new RandomGenerator();

                  this.Position = randomGenerator.Generate<Point>();

                  this.Product = new Diffuser
                                     {
                                         Size =
                                             new RectangularProductSize(
                                             2.Inches()),
                                         Position = this.Position,
                                         ProductType =
                                             Dep<IProductType>()
                                     };
              };

            Action andProductImageFactoryIsStubbed = () => Dep<IProductBitmapImageFactory>().Stub(f => f.GetInstance(Dep<IProductType>())).Return(ExpectedBitmapImage);

            Action andProductSizeIsStubbed = () =>
                 {
                     Stub<IDisplacementProduct, IProductSize>(p => p.Size);

                     var productBounds = new ProductBounds(Width.Feet(), Height.Feet());

                     Dep<IProductSize>().Stub(s => s.Bounds).Return(productBounds);
                 };

            Action andDrawingScaleIsStubbed = () => Dep<IDrawingScale>().Stub(s => s.PixelsPerFoot).Return(PixelsPerFoot);

            Action andProductTypeIsStubbed = () => Stub<IDisplacementProduct, IProductType>(p => p.ProductType);

            givenThatAProductIsSetupforInjection();
            andProductImageFactoryIsStubbed();
            andProductSizeIsStubbed();
            andDrawingScaleIsStubbed();
            andProductTypeIsStubbed();
        }

2voto

Michael Meadows Punkte 26846

Legen Sie sie in separaten Methoden ab, damit Sie sie in anderen Givens zusammenstellen können. Verwenden Sie außerdem Unterstriche als Ersatz für Leerzeichen (anstelle von Großbuchstaben). Erstellen Sie außerdem eine Methode Given_that die die Parameter von Action Delegierte.

protected void Given_that(params Action[] preconditions)
{
    foreach (var action in preconditions)
    {
        action();
    }
}

...

protected void a_product_is_set_up_for_injection()
{
    ...
}

protected void product_image_factory_is_stubbed()
{
    ...
}

etc...

...

Given_that(a_product_is_set_up_for_injection,
           product_image_factory_is_stubbed,
           product_size_is_stubbed,
           drawing_scale_is_stubbed,
           product_type_is_stubbed);

Davon abgesehen, denke ich, dass die Benennung Ihrer Vorbedingungen nicht BDD sind. Sie sind sehr technischer Natur und bezeichnen nicht die geschäftliche Notwendigkeit. Wenn Sie einem Nicht-Programmierer sagen würden, was Sie testen, würden Sie wahrscheinlich nicht sagen: "Das Produkt wird für die Injektion gestoppt." Sie würden wahrscheinlich eher sagen

Given a displacement product
    that is a two inch rectangular diffuser
    that has a random position
    that has a bitmap
    that has a size bounded by feet
    that has the expected pixels per foot

Jetzt können Sie Ihre "gegebenen" Methoden mit wenig Doppelarbeit zusammenstellen:

protected [the type of your test class] Given(params Action given)
{
    given();
    return this;
}

protected void That(params Action[] preconditions)
{
    foreach (var precondition in preconditions)
    {
        precondition();
    }
}

Given(a_displacement_product)
    .That(is_a_two_inch_rectangular_diffuser,
          has_a_random_position,
          has_a_bitmap,
          has_a_size_bounded_by_feet,
          has_the_expected_pixels_per_foot);

1voto

Kjetil Klaussen Punkte 6056

Zusammenstellung Ihrer Givens , Wann et Thens in getrennten Methoden ist eine gute Idee, und es ist der Weg, zum Beispiel SpecFlow ( http://www.specflow.org ) tut es. Wenn Sie also lieber etwas Automatisierung für die Erstellung dieses langweiligen, sich wiederholenden Stücks Klempnerarbeit wünschen, würde ich Ihnen wirklich ein Tool wie SpecFlow empfehlen. Und als Bonus erhalten Sie ein nettes Berichtswerkzeug :)

Eine weitere Möglichkeit, Ihren Code etwas flüssiger zu gestalten, ist die Erstellung einer kleinen BDD-Basisklasse. Werfen Sie einen Blick auf Jonas Follesoe's brillante kleine BDD DSL auf GitHub: http://gist.github.com/406014 ;

public abstract class BDD<T> where T : BDD<T>
{
    protected T Given { get { return (T)this; } }
    protected T And { get { return (T)this; } }
    protected T When { get { return (T)this; } }
    protected T Then { get { return (T)this; } }
}

Und wie Michael Meadows in seiner großartigen Antwort darauf hinweist: Wenn Sie den BDD-Weg des TDD gehen (was Sie wirklich tun sollten), konzentrieren Sie sich darauf, Ihre Spesifikationen für Geschäftsleute lesbar zu machen. Das bedeutet, dass Sie sich von technischen Begriffen wie mock, inject, factory, exception, etc. fernhalten sollten.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X