Code Monkey home page Code Monkey logo

deepequal's People

Contributors

allrameest avatar arung2207 avatar bdrupieski avatar dependabot[bot] avatar herebebeasties avatar jamesfoster avatar kzu avatar rokklobster avatar smoogipoo avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

deepequal's Issues

Sticking the differences into the Context object feels wrong

I notice that in the latest version, you are sticking Difference objects into the ComparisonContext. Tracking differences and having custom formatters could certainly make sense. But I think this is the wrong way to go about it. Logically, the Difference objects should be part of a Result object, not part of the ComparisonContext object. In other words, you would have a ResultModel object, or something like that. One of its fields could be a ComparisonResult -- pass, fail, or inconclusive. Another field might contain your differences.

In addition to making logical sense, this would eliminate the need to return two objects from your Compare methods.

Refactor extensions on object

The library has several extension methods on object (WithDeepEqual etc.) This makes them pollute Intellisense for all class objects, which is quite annoying.

I suggest refactoring to instead use non-extension methods, e.q. DeepEqual.IsEqual(ob1, ob2) etc.

how to define tolerance for "double" (or "float") comparison?

found very flexible way to define comparison,

Implemented "flexible" way to compare 2 double with tolerance.
Probably, could you add 2 options (tolerance for double and float") by short way.

        [Test]
        public void DoubleTypeTesting()
        {
            const double expected = 5.0;
            const double actual1 = 5.1;
            const double actual2 = 5.2;

            IComparison comparison = new MyComparison(0.15);

            actual1.WithDeepEqual(expected)
                .WithCustomComparison(comparison)
                .Assert();

            actual2.WithDeepEqual(expected)
                .WithCustomComparison(comparison)
                .Assert();

        }

DateTime comparisons failing

Good evening,

Apologies if this is addressed somewhere and I have missed it. DateTime value comparison doesn't appear to be happy, see below. Before finding DeepEqual I had to compare them after calling ToString() and comparing the string contents. Hopefully I'm just missing something

DeepEqual.Syntax.DeepEqualException : Comparison Failed: The following 2 differences were found.
    Actual.DateCreated != Expected.DateCreated (9/7/2015 9:57:38 PM != 9/7/2015 9:57:38 PM)
    Actual.LastModified != Expected.LastModified (9/7/2015 9:57:38 PM != 9/7/2015 9:57:38 PM)

Comparison fails if implementation has "new" keyword on property

Although it's not very common practice, sometimes, object models may provide a more concrete (down-casted) type of the same property as the base class, for the sake of convenience. The way to do this is to redefine the property, with the "new" keyword.

This fails with DeepEquals as it considers the property to be duplicated. Here's the repro:

[Fact]
public void when_comparing_object_with_new_property_then_fails()
{
    var obj1 = new Derived { Schema = new DerivedSchema() };
    var obj2 = new Derived { Schema = new DerivedSchema() };

    obj1.IsDeepEqual(obj2);
}

public interface IBaseSchema { }
public interface IDerivedSchema : IBaseSchema { }

public class DerivedSchema : IDerivedSchema { }

public class Base
{
    public IBaseSchema Schema { get; set; }
}

public class Derived : Base
{
    // NOTE: the point here is to just make access to 
    // derived schema specific properties more convenient
    // by avoiding down-casting everywhere, especially 
    // since this can be guaranteed to be of the given 
    // type.
    public new IDerivedSchema Schema
    {
        get { return (IDerivedSchema)base.Schema; }
        set { base.Schema = value; }
    }
}

Add support for .NET 4.0

Since there's nothing 4.5-specific, it would be great if it was compatible with .NET 4.0 too :)

Comparing object to primitive values is unexpected always deep equal.

Given the example below, I would never expect the object Foo carrying the value 12 to equal 42.
It seems like a bug to me, and I'm afraid it'll result in many unexpected false positives.

        [Fact]
        public void ShouldFail()
        {
            new Foo(12).ShouldDeepEqual(42);
        }

        public class Foo
        {
            public int Value { get; }

            public Foo(int value)
            {
                this.Value = value;
            }
        }

NuGet package is not strongly renamed

The NuGet package for DeepEqual is not strongly named, which means it cannot be loaded in a project that is signed. Could you sign the assembly and publish a strongly named package so that it can be referenced in signed assemblies?

Provide extensiblity for custom formatting

There is no current way of extending the formatting of the exception message. You can easily add your own custom comparisons but if you need richer information in the output then you should be able to add a custom Difference subclass and register a DifferenceFormatter

NaN support

Trying to run a property test using FsCheck. It generates also NaN for double values. Normally is always NaN != NaN, but for equality it doesn't matter. Is there any option for it or is it possible to convince DeepEqual to take NaNs as equal?

Possible to ignore a property across all elements of an array?

If I've missed some documentation which answers this, please let me know.

When doing a comparison, is it possible to ignore a property of an array element? E.g...

Instead of this:

actual.WithDeepEqual(expected)
    .IgnoreSourceProperty(o => o.People[0].Id)
    .IgnoreSourceProperty(o => o.People[1].Id)
    ...
    .IgnoreSourceProperty(o => o.People[n].Id)
    .Assert();

Do this:

actual.WithDeepEqual(expected)
    .IgnoreSourceArrayProperty(o => o.People, o => o.Id)
    .Assert();

That way, the comparison would ignore the Id property for each element in the People array on the source object.

Default comparison of enums

It seems that by default instances of different enum types are never evaluated as deep-equal, even if their names match.

I have to apply SkipDefault<EnumType1>().SkipDefault<EnumType2>() or WithCustomComparison(new EnumComparison()) to get a working comparison.

Is this the intended behavior?

public enum Foo { X = 1, Y = 2 } 
public enum Bar { X = 1, Y = 2 }

[Test]
public void Enums_WithSameName_ShouldDeepEqual()
{
    // throws with Actual != Expected (X != X)
    (Foo.X).ShouldDeepEqual(Bar.X);
}

[Test]
public void Enums_WithSameName_WithDeepEqualAndSkipTypes_ShouldAssert()
{
    // works (and successfully throws when comparing Foo.X with Bar.Y)
    (Foo.X).WithDeepEqual(Bar.X).SkipDefault<Foo>().SkipDefault<Bar>().Assert();
}

[Test]
public void Enums_WithSameName_WithCustomComparison_ShouldAssert()
{
    // works (and successfully throws when comparing Foo.X with Bar.Y)
    (Foo.X).WithDeepEqual(Bar.X).WithCustomComparison(new EnumComparison()).Assert();
}

exception message (string comparison): nunit vs. DeepEqual

NUnit:

Expected string length 3 but was 8. Strings differ at index 0.
  Expected: "Joe"
  But was:  "Chandler"
  -----------^

DeepEqual:

System.Exception : Comparison Failed: The following 1 differences were found.
    Actual.Name != Expected.Name (Actual: "Chandler", Expected: "Joe")

seems attached test should fail by DeepEqual, but didn't fail

        [Test]
        public void TestIgnoreByType()
        {
            var expected = new Data { Id = 5, Name = "Joe" };
            expected.Items.Add(new DataItem { Name="1", Tag = new Tag()});
            var actual = new Data { Id = 5, Name = "Joe" };
            actual.Items.Add(new DataItem { Name = "1", Tag = new Tag()});

            actual.WithDeepEqual(expected)
                .Assert();

            Assert.AreEqual(expected.Items[0].Tag.R, actual.Items[0].Tag.R);
        }

    public class Data
    {
        public int Id;
        public string Name { get; set; }
        public List<DataItem> Items = new List<DataItem>();
    }

    public class DataItem
    {
        public string Name { get; set; }
        public Tag Tag { get; set; }
    }

    public class Tag
    {
        static readonly Random random = new Random();
        public int R { get; set; }

        public Tag()
        {
            R = random.Next();
            Console.WriteLine("R={0}", R);
        }
    }

Only get difference without assert

Can I get difference between two objects without throw new DeepEqualException?
Method ‘ShouldDeepEqual’ returns good message with difference, but it creates exception.

StackOverflow exception on object graphs with cycles

In version 0.12.0.0 installed from NuGet, I get a StackOverflowException when an object graph contains cycles.

Sample below:

public class A
{
    public List<B> Bees { get; set; }
}

public class B
{
    public A A { get; set; }
}

public class C
{
    public D D { get; set; }
}

public class D
{
    public C C { get; set; }
}

class Program
{
    static void Main(string[] args)
    {
        var a = new A();
        var b = new B { A = a };
        a.Bees = new List<B> { b };

        var a1 = new A();
        var b1 = new B { A = a1 };
        a1.Bees = new List<B> { b1 };

        a1.ShouldDeepEqual(a); //stack overflow exception

        b1.ShouldDeepEqual(b); //stack overflow exception


        var c = new C();
        var d = new D { C = c };
        c.D = d;

        var c1 = new C();
        var d1 = new D { C = c1 };
        c1.D = d1;

        c1.ShouldDeepEqual(c); //stack overflow exception

        d1.ShouldDeepEqual(d); //stack overflow exception
    }
}

An expression tree may not contain a call or invocation that uses optional arguments

After updating to DeepEqual 1.5.0, I have numerous errors stating: An expression tree may not contain a call or invocation that uses optional arguments with lines like the following

_repository.Received().Update(Arg.Is<MyClass>(obj => obj.IsDeepEqual(expected)));

It's a NSubstitute test. I'm forced to add an extra NULL parameter to all my mock asserts:

_repository.Received().Update(Arg.Is<MyClass>(obj => obj.IsDeepEqual(expected, null)));

Could IsDeepEqual use an overload instead of an optional parameter?

Thanks.

compare enums via string match

is it possible some option to compare enums via string match?

when there are two different classes with the same structure and content, comparison is ok, except enums

upd: seems possible with custom comparison, but nice to have option

Is it possible to setup a map for properties?

Hi,
Great library, thanks for putting this together.

Do you know if it's possible to setup an exception to the user comparison of matching properties so that if a property has been renamed we can check the objects were copied properly ?

for example. imagine type 1 has a 'lastName' property, and type 2 has a 'surname' property.
Could we do something like 'mapProperty(x=> x.lastName, y=> y.surname)' ?

Thanks.

Doesn't work with internal properties

If my TestClass has public properties it works but when they are sat as internal DeepEquels no longer find any differences.

public class TestClass
{        
     internal int TestInt { get; set; }
     internal string TestString { get; set; }
}

[TestFixture]
public class TestClassTest
{

    [Test]
    public void SerTest()
    {
        var testA = new TestClass() {TestInt = 1, TestString = "A"};
        var testB = new TestClass() { TestInt = 2, TestString = "B" };

        testA.ShouldDeepEqual(testB);
        Assert.DoesNotThrow(() => testA.ShouldDeepEqual(testB));
        Assert.IsTrue(testA.IsDeepEqual(testB));
    }
}

option for case-insensitive member name match

is there some option for case-insensitive member name match?
i.e. Class1.ID match with Class2.id

also custom property matcher and/or regex pairs to match property names will be nice

with regex pairs: [/id/i, /(primary_?)?id/i] will match Class1.{id|ID|Id|...} to Class2.{id|ID|Id|PrimaryId|primary_id|...}

Comparing `IEnumerable`s without regards to order (without throwing)

I have a use case where I want to compare two collections of entities (specific class type here is a custom in-house class, Answer; it could be anything) and see if they are equal without concern for the order. The collections are IEnumerable, so I can't count on a specific ordering, which also means I don't want my equality check to care about order. Right now, I've getting failures in DeepEqual where essentially it's telling me value1[0] != value2[0], but value1[1] == value2[0] and vice versa for 2 two-element collections.

I need to fix that.

I'd hoped to create collections that are ordered (by Id in this case) in my custom Compare and then compare, but obviously the only really important idea is that they are matchable in some way that allows equality checks.

Right now I'm using code like the following in a custom IComparison:

public (ComparisonResult result, IComparisonContext context) Compare(IComparisonContext context, object value1, object value2)
{
	var custom1 = (IEnumerable<Answer>)value1;
	var custom2 = (IEnumerable<Answer>)value2;

        // Ob could add to the lines above
	var ordered1 = custom1.ToList();
	var ordered2 = custom2.ToList();

	ordered1.Sort((a, b) => a.Id.CompareTo(b.Id));
	ordered2.Sort((a, b) => a.Id.CompareTo(b.Id));

	// I haven't found a good way to return the description.
	// I can pull from the exception thrown by ShouldDeepEqual,
	// but that apparently leaves the app in an residual
	// exception-has-been-thrown state that gets ugly?
	if (!ordered1.IsDeepEqual(ordered2))
	{
	    context.AddDifference(value1, value2);
	    return (ComparisonResult.Fail, context);
	}

	return (ComparisonResult.Pass, context);
}

The comments kind of tell the tale. If I capture a throw (by using ShouldDeepEqual instead of IsDeepEqual), I get some text I might be able to output somewhere, but I didn't seem to be able to attach it to AddDifference. So for the time being I'm checking the IsDeepEqual boolean and returning the right ComparisonResult value without a good message.

There is an AddDifference overload that has a string as the third parameter, but that's for the field that's failing, and it didn't display text especially cleanly when it failed.

What's the right way to compare IEnumerable<T>?

Nested properties are not ignored.

When attempting to ignore a nested property, it is still being considered during the comparison:

actual.WithDeepEqual(expected)
    .IgnoreSourceProperty(o => o.SomeProperty.ChildProperty)
    .Assert();

This still throws an exception when SomeProperty.ChildProperty is different. Perhaps this is simply not supported?

How to?

Not an issue but more a question/suggestion. How hard would it be to add matching strategy, IgnorePropertiesMissingInDestination and IgnorePropertiesMissingInSource?

Comparison of KeyValuePair types

Found an issue - IsDeepEqueal() method returns false as the comparison result of exact KeyValuePair objects. That's working well when I'm using KeyValuePair with primitive types, but not working with my other defined types.

public class Model
{
    public int Id { get; set; }
    public string Name { get; set; }
}

class Program
{
    static void Main(string[] args)
    {
        var model_1 = new KeyValuePair<string, Model>("1", new Model() { Id = 10, Name = "1" });
        var model_2 = new KeyValuePair<string, Model>("1", new Model() { Id = 10, Name = "1" });

        var model_3 = new KeyValuePair<int, string>(1, "1");
        var model_4 = new KeyValuePair<int, string>(1, "1");

        Console.WriteLine(model_1.IsDeepEqual(model_2));
        Console.WriteLine(model_3.IsDeepEqual(model_4));
    }                                         
}

Ignore property with in list type of sub object with Deep Equal

Hello

I am using the DeepEqual to test if the results of a test match my expected output.

I do the comparison simply as

results.ShouldDeepEqual(expected);

However, I don't know how to ignore a property within my list type

The type I am deep comparing contains a list. The data type held within this list contains a Guid property Id which I want to ignore, as well as a date.

Ignoring top level properties works fine. However, I don't see how to ignore properties on a list type.

To get around this for now, I have had to write some code to clear these properties myself, but this is obviously not ideal.

for (var i = 0; i < results.MyList.Count; i++)
{
    results.MyList[i].Id = Guid.Empty;
    expectedResults.MyList[i].Id = Guid.Empty;
}

How can I accomplish this?

Comparing dictionaries containing classes is problematic

When running the provided code the IsDeepEqual call consumes more than 1 GB of memory and had to be stopped after 1 minute.

using System;
using System.Collections.Generic;
using DeepEqual.Syntax;

namespace test1
{
    class Test
    {
        public string A { get; set; }
    }
    class Program
    {
        static void Main(string[] args)
        {
            var object1 = new Dictionary<int, Test>();
            var object2 = new Dictionary<int, Test>();
            for (int c = 0; c < 100; c++)
            {
                object1.Add(c, new Test { A = c.ToString() });
                object2.Add(c, new Test { A = c.ToString() });
            }

            object2[10].A = "different";
            Console.WriteLine($"Equals: {object1.IsDeepEqual(object2)}");
        }
    }
}

This happens under .NET Core 3.1 and .NET 5 using version 2.0.0

Bypass Equals implementations on classes

I'm using DeepEqual for unit testing, and I would like to make a comparison of two class instances, that has a custom implementation of Equals, that compares only on a subset of the objects properties.

Is it possible to configure DeepEqual to not use the Equals method for comparison on class types (not strings), and thus always fall back to complex object comparisons for these?

And if not, would it be a welcome addition to the library?

Examples

Hi,
I want to use your library but I'm not able to ignore some properties in the following way (i guessed).

content.WithDeepEqual(expected).IgnoreSourceProperty(x => x.InfoContrat.PerfP).Assert();
This is the only property i don't want to compare.

Is this the good way to go ?

Where can i have some more documentation / examples ?

(my actual and expected objects are way too big to paste here)

Possibly unintended breaking change between 2.0.0 and 4.2.1

The following test passed in 2.0.0 but fails in 4.2.1 as it returns a Pass now. Is this intended?

    [Fact]
    public void ComparingObjectsWithNoProperties_DifferentType()
    {
        var comparer = (IComparison)new ComparisonBuilder().Create();
        var context = new ComparisonContext();

        Assert.Equal(
            ComparisonResult.Inconclusive, 
            comparer.Compare(context, new object(), new Blah()).result);
    }
    
    public class Blah { }

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.