Pot fi îmbunătățite aceste teste de unitate de testare a rândurilor pentru a respecta practicile bune de proiectare TDD?

Pot fi îmbunătățite următorul test de unitate, să urmeze bune practici de proiectare TDD (denumirea, folosirea rândurilor de șir, proiectarea claselor) în oricare dintre cadrele .NET TDD/BDD?

De asemenea, există o modalitate mai bună în oricare dintre cadre de a avea șiruri în care pot avea o așteptare individuală pentru fiecare rând, la fel cum o fac și eu în acest exemplu (NUnit)?

Sistemul testat aici este clasa Constraint care poate avea mai multe intervale de numere întregi valide. Testul testează metoda NarrowDown care poate face ca intervalele valide să fie mai mici pe baza unei alte constrângeri.

[TestFixture]
internal class ConstraintTests
{
    [Test]
    public void NarrowDown_Works()
    {
        RowTest_NarrowDown(
            new Range[] { new Range(0, 10), new Range(20, 30), new Range(40, 50) },
            new Range[] { new Range(1, 9), new Range(21, 29), new Range(41, 49) },
            new Range[] { new Range(1, 9), new Range(21, 29), new Range(41, 49) });

        RowTest_NarrowDown(
            new Range[] { new Range(0, 10), new Range(20, 30), new Range(40, 50), new Range(60, 70) },
            new Range[] { new Range(1, 9), new Range(21, 29), new Range(41, 49) },
            new Range[] { new Range(1, 9), new Range(21, 29), new Range(41, 49) });

        RowTest_NarrowDown(
            new Range[] { new Range(0, 10), new Range(20, 30), new Range(40, 50) },
            new Range[] { new Range(1, 9), new Range(21, 29), new Range(41, 49), new Range(60, 70) });
    }

    private static void RowTest_NarrowDown(IEnumerable sut, IEnumerable context)
    {
        Constraint constraint = new Constraint(sut);
        Constraint result = constraint.NarrowDown(new Constraint(context));
        Assert.That(result, Is.Null);
    }

    private static void RowTest_NarrowDown(IEnumerable sut, IEnumerable context, IEnumerable expected)
    {
        Constraint constraint = new Constraint(sut);
        Constraint result = constraint.NarrowDown(new Constraint(context));
        Assert.That(result, Is.Not.Null);
        Assert.That(result.Bounds, Is.EquivalentTo(expected));
    }
}
1
Fiecare set de intrări ar trebui să fie un test independent. Dacă logica mai multor teste este identică cu intrarea-ieșire, utilizați "Teste parametrizate". NUnit utilizează atribute sau o metodă care oferă diferite seturi de intrări la un test parametrizat. Fiecare set este executat/raportat ca un test diferit de către alergătorul de test.
adăugat autor Gishu, sursa

2 răspunsuri

În primul rând, puteți îmbunătăți numele din unitatea de testare NarrowDown_Works este extrem de vagă și nu pot spune ce ar trebui să facă clasa testată.

Aveți multe afirmații și multe date, nu pot spune ce este important. Încercați să rupeți testul în teste mai mici și va fi mai ușor să le numiți, de asemenea. Dacă este posibil, folosiți o afirmație pe test .

Construcția datelor dvs. de testare este destul de complexă, luați în considerare utilizarea matchers , cum ar fi NHamcrest pentru a reduce cantitatea de date de afirmație de care aveți nevoie în loc să utilizați Is.EquivalentTo .

De asemenea, ați putea folosi mai ușor un constructor sau constructori din fabrică pentru a simplifica simplificarea inițializării pentru clasa Constraint mai degrabă decât pentru a trece într-o matrice de Ranges .

2
adăugat
+1 pentru sugestia lui NHamcrest
adăugat autor bitbonk, sursa

Ar trebui să utilizați o abordare bazată pe date cu fabrici de date (în NUnit-speak, ele sunt numite surse de caz test ). Acest lucru face ca testele dvs. să fie mult mai ușor de citit, înțeleg, modificat și menținut (sau, în general, mult mai curat):

[TestFixture]
internal class ConstraintTests
{
    static object[] TwoRanges = 
    {
        new object[]
            {
                new[] { new Range(0, 10), new Range(20, 30), new Range(40, 50) },
                new[] { new Range(1, 9), new Range(21, 29), new Range(41, 49), new Range(60, 70) }
            }
    };

    static object[] ThreeRanges = 
    {
        new object[]
            {
                new[] { new Range(0, 10), new Range(20, 30), new Range(40, 50) },
                new[] { new Range(1, 9), new Range(21, 29), new Range(41, 49) },
                new[] { new Range(1, 9), new Range(21, 29), new Range(41, 49) }
            },
        new object[]
            {
                new[] { new Range(0, 10), new Range(20, 30), new Range(40, 50), new Range(60, 70) },
                new[] { new Range(1, 9), new Range(21, 29), new Range(41, 49) },
                new[] { new Range(1, 9), new Range(21, 29), new Range(41, 49) }
            }
    };

    [Test, TestCaseSource("TwoRanges")]
    public void NarrowDown_WhenCalledWithTwoRanges_GivesTheExpectedResult(IEnumerable sut, IEnumerable context)
    {
        Constraint constraint = new Constraint(sut);
        Constraint result = constraint.NarrowDown(new Constraint(context));
        Assert.That(result, Is.Null);
    }

    [Test, TestCaseSource("ThreeRanges")]
    public void NarrowDown_WhenCalledWithThreeRanges_GivesTheExpectedResult(IEnumerable sut, IEnumerable context, IEnumerable expected)
    {
        Constraint constraint = new Constraint(sut);
        Constraint result = constraint.NarrowDown(new Constraint(context));
        Assert.That(result, Is.Not.Null);
        Assert.That(result.Bounds, Is.EquivalentTo(expected));
    }
}

Vedeți cât de simplificați metodele dvs. de testare acum? De asemenea, acest lucru va face ca fiecare set de date din sursa cazului de încercare inițial să fie rulat într-un test separat, astfel încât întregul lucru nu va eșua doar pentru că un set de date cauzează un eșec. Amintiți-vă: un test ar trebui să afirăm doar un lucru un .

HTH!

0
adăugat