Working sample of Custom Constraints.

303 views
Skip to first unread message

constructor

unread,
Sep 28, 2014, 10:26:16 AM9/28/14
to nunit-...@googlegroups.com
Hi,

I am looking for working sample of custom constraints. Unfortunately, page http://www.nunit.org/index.php?p=customConstraints&r=2.5.10 doesn't contain sample. 

I investigate "custom constraints" and prepare next test:

[Test]
        public void Strings_MyConstraint()
        {
            const string expected = "Joe";
            const string actual = "joe";
            var myConstraint = new MyConstraint(expected);
            Assert.That(actual, Has.Some.Matches(myConstraint));
        }

where debug version of MyConstraint:
public class MyConstraint : Constraint
    {
        private readonly object m_expected;        
        public MyConstraint(object expectedValue)
        {
            m_expected = expectedValue;
        }
        #region Implementation of abstract methods
        public override bool Matches(object actual)
        {
            return false;            
            //return ((string)m_expected).ToLower() == ((string)actual).ToLower();
        }
        public override void WriteDescriptionTo(MessageWriter writer)
        {
            throw new NotImplementedException();
        }
        #endregion
    }

and actual parameter contains first symbol of actual value:

Please, could you publish working sample of custom constraint?
I use nunit 2.6.3.
I check option to implement "deep" compare of 2 objects and want to check "custom constraint" for the implementation.

thank you,
Igor.

Simone Busoli

unread,
Sep 28, 2014, 11:08:50 AM9/28/14
to NUnit-Discuss
Hi Igor,

you can check out how NUnit's own constraints are implemented here.

For a simple, self-contained example I would suggest the XmlSerializableConstraint.

Simone

--
You received this message because you are subscribed to the Google Groups "NUnit-Discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to nunit-discus...@googlegroups.com.
To post to this group, send email to nunit-...@googlegroups.com.
Visit this group at http://groups.google.com/group/nunit-discuss.
For more options, visit https://groups.google.com/d/optout.

constructor

unread,
Sep 28, 2014, 11:23:54 AM9/28/14
to nunit-...@googlegroups.com
Hi Simone,
Unfortunately, I cannot understand the sample.

Could you implement simple constrain (compare 2 strings with ignoring lower/upper case)?
For any other type, let constrain raise error.

thank you,
Igor.

Simone Busoli

unread,
Sep 28, 2014, 11:31:17 AM9/28/14
to NUnit-Discuss

Such a constraint already exists:

Assert.That(actual, Is.EqualTo(expected).Ignor

​e​
Case)

constructor

unread,
Sep 28, 2014, 2:14:43 PM9/28/14
to nunit-...@googlegroups.com
I understand, but I want to see simple sample for customer constraint.

Simone Busoli

unread,
Sep 28, 2014, 2:46:25 PM9/28/14
to NUnit-Discuss
Igor, I already pointed you at the repository where you can find plenty of them, I'm afraid there nothing else I can help you with.

Simone

Charlie Poole

unread,
Sep 28, 2014, 4:50:56 PM9/28/14
to NUnit-Discuss
Hi Igor,

If the example Simone suggested is too difficult because of how it deals with serialization look at some of the others. There are over 100 and I'm sure at least a few of them will help you. We plan to develop some examples for the new docs, but none of us have time to do it right in this thread.

Charlie

constructor

unread,
Oct 5, 2014, 11:14:42 AM10/5/14
to nunit-...@googlegroups.com
Charlie,

Let's define next task: I want sometimes to compare only even symbols in my strings with help of nunit and Is.EqualTo.

So, I prepare customer's constraint EvenCharsConstraint and implement next tests (see below).
But the tests contain 2 "expected" variables transfer: to original EqualTo and my OnlyEvenChars. How can I re-design the code to receive IsEqual as basis, OnlyEvenChars as extension via fluent interface and single "expected" transfer?
Current implementation ignores first IsEqualTo, but I don't understand how to use it in my customer EvenCharsConstraint.

        [Test]
        public void SameEvenChars_MyConstraint_Pass()
        {
            const string expected = "Tom";
            const string actual = "Joe";
            Assert.That(actual, Is.EqualTo(expected)
                                  .OnlyEvenChars(expected));
        }
        [Test]
        [ExpectedException(typeof(AssertionException))]
        public void NotSameEvenChars_MyConstraint_Failed()
        {
            const string expected = "Tom";
            const string actual = "Sam";
            Assert.That(actual, Is.EqualTo(expected)
                                  .OnlyEvenChars(expected));
        }
 
where class EvenCharsConstraint implemented next:

    public class EvenCharsConstraint : EqualConstraint
    {
        private readonly object m_expected;        
        private object m_actual;
        public EvenCharsConstraint(object expectedValue)
            : base(expectedValue)

        {
            m_expected = expectedValue;
        }
        #region Implementation of abstract methods
        public override bool Matches(object actual)
        {
            m_actual = actual;
            bool matches = base.Matches(actual);
            if (!matches && m_expected is String && m_actual is String)
            {
                string expectedString = (string) m_expected;
                string actualString = (string) actual;
                if (expectedString.Length == actualString.Length)
                {
                    bool result = !expectedString.Where((expectedChar, index) => (index + 1) % 2 == 0 && expectedChar != actualString[index]).Any();
                    matches = result;
                }
            }
            return matches;
        }
        #endregion
    }

    public static class MyIs
    {
        public static EqualConstraint OnlyEvenChars(this EqualConstraint equalConstraint, object expected)
        {
            return new EvenCharsConstraint(expected);
        }            
    }


thank you,
Igor.

constructor

unread,
Oct 6, 2014, 1:54:12 AM10/6/14
to nunit-...@googlegroups.com
Also implemented other version:

 [Test]
        public void SameEvenChars_MyConstraint_Pass()
        {
            const string expected = "Tom";
            const string actual = "Joe";
            Assert.That(actual, Is.EqualTo(expected)
                                  .OnlyEvenChars());
        }

with help of 
public class EvenCharsEqualityComparer : IEqualityComparer
    {
        public new bool Equals(object x, object y)
        {
            if (x is String && y is String)
            {
                string xString = x as String;
                string yString = y as String;
                bool result = (xString.Length == yString.Length);
                result = result && !yString.Where((expectedChar, index) => (index + 1) % 2 == 0 && expectedChar != xString[index]).Any();
                return result;
            }
            var equalConstraint = new EqualConstraint(y);
            return equalConstraint.Matches(x);
        }
        public int GetHashCode(object obj)
        {
            return base.GetHashCode();
        }
    }


Could you help me to understand correct patterns of "custom constraint" usage?

thank you,
Igor.
Reply all
Reply to author
Forward
0 new messages