6
votes

Affirmer deux types d'énumérations différents sont équivalents

J'ai un test de l'unité Nunit que j'ai deux collections de types différents que je veux affirmer sont équivalents.

public static void IsPrettySimilar<T1, T2>(
    IEnumerable<T1> left, 
    IEnumerable<T2> right, 
    Func<T1, T2, bool> predicate)
{
    using (var leftEnumerator = left.GetEnumerator())
    using (var rightEnumerator = right.GetEnumerator())
    {       
        while (true)
        {
            var leftMoved = leftEnumerator.MoveNext();

            if (leftMoved != rightEnumerator.MoveNext()) 
            {
                Assert.Fail("Enumerators not of equal size");
            }

            if (!leftMoved)
            {
                break;
            }

            var isMatch = predicate(leftEnumerator.Current, 
                                rightEnumerator.Current);

            Assert.IsTrue(isMatch);
        }           
    }
}


0 commentaires

3 Réponses :


1
votes

Je sais que vous avez examiné CollectionAssert CODE>, cependant, j'ai trouvé une stratégie comme celle-ci très utile dans mes propres tests.

ToString et égal sur les objets fait ce passage de test. P>

[TestFixture]
public class Class1
{

    [Test]
    public void MyUnitTest()
    {
        var a = GetABunchOfAs(); // returns IEnumerable<A>
        var b = GetABunchOfBs(); // returns IEnumerable<B>

        CollectionAssert.AreEqual(a, b.OrderBy(x => x.y));

    }

    public List<A> GetABunchOfAs()
    {
        return new List<A>
        {
            new A() {x = 1},
            new A() {x = 2},
            new A() {x = 3},
            new A() {x = 4}
        };
    }

    public List<B> GetABunchOfBs()
    {
        return new List<B>
        {
            new B() {y = "4"},
            new B() {y = "1"},
            new B() {y = "2"},
            new B() {y = "3"},

        };
    }
}

public class A
{
    public int x;
    public override bool Equals(object obj)
    {
        return obj.ToString().Equals(x.ToString());
    }

    public override string ToString()
    {
        return x.ToString();
    }
}

public class B
{
    public string y;

    public override string ToString()
    {
        return y;
    }

    public override bool Equals(object obj)
    {
        return obj.ToString().Equals(y);
    }

}


0 commentaires

1
votes

Pensons à ce que vous essayez de tester. Vous n'essayez pas de tester que les objets de première séquence sont les mêmes que les objets de la deuxième séquence. Ils peuvent être très différents. Donc, le mot similaire em> est très vague ici. Ce que vous essayez vraiment de tester ici, c'est que certaines projection de la première séquence sont égales à une autre projection de la deuxième séquence. Et Nunit a déjà une telle fonctionnalité: xxx pré>

Ainsi, vous projetez les deux séquences pour obtenir des données particulières, vous pouvez également donner des noms agréables pour ces deux projections, ce qui rendra votre test lisible à d'autres. Vous avez une logique commerciale cachée ici, qui n'a pas d'explication dans le code - vous n'expliquez pas pourquoi em> vous faisant de telles projections. Donc, de beaux noms de résultats de projection expliqueront votre intention. E.g: p>

 Assert.IsPrettySimilar(employees, customers, (e, c) => u.Login == c.Name);


4 commentaires

Ceci est correct, je teste que les projections sont ce que j'attends. Cependant, dans mon scénario, mes deux types ont respectivement 7 et 4 propriétés. Les deux exemples que vous n'avez pas expliquent la commande ou le nombre, ce qui est quelque chose que je dois prendre en compte.


@Matthew, mais CollectionAssert.Areeequal vérifie à la fois le nombre et l'ordre des articles - il lancera une exception d'assertion lorsque l'une des séquences a manqué un élément (c'est-à-dire qu'il est plus court que d'autres) ou lorsque certains éléments ne sont pas égaux (son interne Mise en œuvre de énumérapesequal est à peu près identique à la méthode d'extension de la vôtre, à l'exception de l'utilisation du prédicat)


Ah d'accord, ça ressemble à cela pourrait faire ce que je veux alors, laissez-moi enquêter.


Cela ressemble à ce que je veux, cependant, je ne vais probablement pas l'utiliser comme dans mes exemples, je trouve que le prédicat est plus idiomatique aux tests que j'écris, mais c'est une bonne alternative.



0
votes

Cela ressemble à la réponse de Sergey est celui que je cherche (qui devait voir si Nunit a déjà une installation pour faire ce que je veux). Cependant, c'est la solution que j'ai terminée avec, qui est plus proche de la mise en œuvre que je veux.

public static class EnumerableAssert
{
    public static void AreEquivilent<TExpected, TActual>(IEnumerable<TExpected> expected, IEnumerable<TActual> actual, Func<TExpected, TActual, bool> predicate)
    {
        if (ReferenceEquals(expected, actual))
        {
            return;
        }

        using (var expectedEnumerator = expected.GetEnumerator())
        using (var actualEnumerator = actual.GetEnumerator())
        {
            while (true)
            {
                var expectedMoved = expectedEnumerator.MoveNext();

                if (expectedMoved != actualEnumerator.MoveNext())
                {
                    Assert.Fail("Expected and Actual collections are of different size");
                }

                if (!expectedMoved)
                {
                    return;
                }

                Assert.IsTrue(predicate(expectedEnumerator.Current, actualEnumerator.Current));
            }
        }
    }
}


0 commentaires