Try fast search NHibernate

Showing posts with label NUnitEx. Show all posts
Showing posts with label NUnitEx. Show all posts

12 August 2009

NUnitEx1.0.5 released

NUnitEx 1.0.5 was released tonight (download).

The new release is pointing NUnit2.5.2 fresh release.

There are only few improvements, in NUnitEx, regarding the constraint Ordered():

(new[] { 1, 2, 3 }).Should().Be.Ordered();
(new[] { 3, 2, 1 }).Should().Be.Ordered();
(new[] { 1, 2, 3 }).Should().Be.OrderedAscending();
(new[] { 3, 2, 1 }).Should().Be.OrderedDescending();

Have a good test experience!!

28 July 2009

NUnitEx 1.0.4 released

NUnitEx 1.0.4 was released today (download).

Charlie Poole, NUnit’s project leader, included NUnitEx as official NUnit AddOnsunder review for possible inclusion in NUnit 3.0” (thanks Charlie) and we are looking for some response from users (the thread is here).

News

Shorten Enumerable Constraints

Some constraints now accept a params T[] so you can write more concise assertion when the expected value is know.

var ints = new[] { 1, 2, 3 };
ints.Should().Have.SameSequenceAs(1, 2, 3);
ints.Should().Have.SameValuesAs(3, 2, 1);
ints.Should().Be.SubsetOf(1, 2, 3, 4);

These new overloads was implemented extending the extensions. ;-)

Count assertion

The Count assertion can be useful in two ways:

To have a “more readable” assertion: ints.Should().Have.Count.EqualTo(3)

As chainable assertion for IEnumerable<T>: ints.Should().Contain(3).And.Not.Have.Count.LessThan(2);

Notes

Thanks to José Romaniello NUnitEx was tested on Mono.

If you have some proposal please don’t hesitate to share it.

12 July 2009

NUnitEx 1.0.2

NUnitEx 1.0.2 was released today.

The new release is targeting NUnit2.5.1 released few days ago.

The new NUnitEx include some new fluent assertions and one extension method useful in tests.

FieldValue<T>

Allow access to a private field where a public property is not available.

[Test]
public void SelectAndUpdateStringContainCustomWhere()
{
const string customWhere = "table_name='second'";
var dialect = new MsSql2005Dialect();
var tg = new TableGenerator();
tg.Configure(NHibernateUtil.Int64,
new Dictionary<string, string> { { "where", customWhere } }, dialect);
    tg.FieldValue<string>("query").Should().Contain(customWhere);
tg.FieldValue<string>("updateSql").Should().Contain(customWhere);
}

Guess where was needed ;)

System.Type constraints
private class B {}

[Serializable]
private class D1 : B { }

private class D2 : D1 { }
var typeToTest = typeof(D1);

typeToTest.Should().Be.SubClassOf<B>();
typeToTest.Should().Be.AssignableFrom<D2>();
typeToTest.Should().Have.Attribute<SerializableAttribute>();
String Match for custom Regex
var re = new Regex("a.b", RegexOptions.Singleline | RegexOptions.IgnoreCase);
"a\nB".Should().Match(re);

Full Syntax Overview

The full syntax overview is available in the NUnitEx wiki.

Consideration

Have a look to this NUnit assertion:

Assert.That(stringToTest, Is.EqualTo("a String Value").IgnoreCase);

What kind of comparison is used ? What mean “IgnoreCase” ?

One Microsoft recommendation about string usage is:

DON'T: Use overloads for string operations that don't explicitly or implicitly specify the string comparison mechanism.

Under the cover the NUnit assertion is equivalent to :

stringToTest.ToLower().Equals("a String Value".ToLower());

As you know the ToLower method is not enough in some languages and the default assertion is obscuring it.

For this reason I prefer:

stringToTest.ToLowerInvariant().Should().Be.EqualTo("a string value");

21 June 2009

How much I like NUnitEx

It is so fluent….

// NUnit classic Assertion
Assert.AreEqual("1;2;3", (new[] {"1", "2"}).ConcatWithSeparator(';'));

// NUnit classic Constraints
Assert.That((new[] { "1", "2", "3" }).ConcatWithSeparator(';'), Is.EqualTo("1;2;3"));

// NUnitEx
(new[] { "1", "2", "3" }).ConcatWithSeparator(';').Should().Be.EqualTo("1;2;3");

No ?

s.CreateQuery("from EntityWithPropNames e where e.PropertiesNames like '%p2%'")
.UniqueResult<EntityWithPropNames>()
.PropertiesNames
.Should().Have.SameSequenceAs(new[] {"p1", "p2", "p3"});

14 April 2009

NUnitEx: assertion.Should().Satisfy(lambda);

In the first post about NUnitEx, Liviu has left a comment with this assertion:

CustomAssert(()=> DateTimeToday < DateTime.Now);

It sound very interesting from someone of us and Simone Busoli began an experiment named “Language Integrated NUnit” (LinUnit). The main concepts behind LinUnit are :

  • pure .NET based assertion
  • assertions easy to extend

LinUnit is now part of NUnitEx.

Examples

const string somethig = "something";

somethig.Should()
.Satisfy(x => x.Contains("some"));

somethig.Should()
.Satisfy(x => !x.Contains("also"));

somethig.ToUpperInvariant().Should()
.Satisfy(x => x.ToUpperInvariant().Contains("SOME"));

somethig.Should()
.Satisfy(x => x.StartsWith("so") && x.EndsWith("ing") && x.Contains("meth"));

somethig.Should()
.Satisfy(x => !x.StartsWith("ing") && !x.EndsWith("so") && !x.Contains("body"));

As you can see the parameter of Satisfy method is a pure C# lambda.

Note that the matter here is the assertion message; for example given this

const string somethig = "something";
somethig.Should()
.Satisfy(x => x.Contains("also"));

the failing message say:

Expected: "x.Contains("also")"
But was:  "something"

One more example using Linq extensions

var ints = new[] { 1, 5, 5, 3 };

ints.Should()
.Satisfy(x => x.SequenceEqual(new[] { 1, 5, 5, 3 }));

The implementation of  “Language Integrated NUnit”, available in NUnitEx, need some more improvement in order to use conventional NUnit constraints, where available, and more complex expressions (basically an improvement of the expression visitor).

Which syntax I should use ?

Well… this is exactly the news. You can use the syntax you have more feeling in the place you think is the best place.

For example for action-exception I prefer this syntax

Assert.Throws<ArgumentNullException>(() => new AClass(null))
.ParamName.Should().Be.Equal("obj");

I’m using NUnitEx in some projects and what I have noticed is that I’m not using Assert.That(…) anymore. For sure, at the begin, you may have some problem to identify the assertion because you can’t easy find “Assert”, with its different color, in the source code but believe me is only a matter of time. The advantage of “Should” with the intellisense helping you will be clear from the first usage.

Entschuldigen, diese sache kann ich nicht lesen

What mean “readability” ? What is readable ?

Probably the most readable is your natural language.

In Italian
{1, 2, 3} dovrebbe avere la stessa sequenza di {1, 2, 3} ed essere un sub-insieme di {5,1,2,3}

In Spanish
{1, 2, 3} tendría que tener la misma secuencia de {1, 2, 3} y ser un subconjunto de {5,1,2,3}

In English
{1, 2, 3) should have same sequence as {1, 2, 3} and be a subset of {5,1,2,3}

In C#
(new[] {1,2,3}).Should().Have.SameSequenceAs(new[] {1,2,3}).And.Be.SubsetOf(new[] {5,1,2,3})

In the natural language we are using spaces to separate words, but in C# we can’t so, in general, we are using the ‘_’ (underscore) or ‘.’ (dot).

In my opinion something like ShouldNotBeNullOrEmpty is less readable than

Should().Not.Be.Null().And.Not.Be.Empty()

A dot-separated-syntax help to separate each word and give you the chance to be helped by intellisense (and obviously is better extensible). A one-PascalCase-syntax mean that you should remember many words of the assertion name before the intellisense can help you.

When my wife (she are using the PC for others matters) read 5.Should().Be.LessThan(10) said : “seriously your work is ask, to the PC, such kind of things” (well… exactly she said “¿me estas cargando?”); what was interesting is that, even a no C# expert, can read it.

When the implementation of LinUnit-syntax will be more complete, probably, many .NET developer will feel better with it because it is pure .NET and you don’t need to remember which is the assertion.


kick it on DotNetKicks.com

25 March 2009

NUnitEx : assertion.Should().Be.Fluent();

Continuing the implementation from the previous post, NUnitEx look nice and useful.

I tried to check available features “simulating” the use of NUnitEx assertions inside some frameworks where I am involved.

Before show some new examples, I would thank to Davy, Steve and Gustavo for their help in the API definition (by the way if you find something wrong is only my fault).

New constrain chain

string something = "something";

something.Should()
.StartWith("so")
.And
.EndWith("ing")
.And
.Contain("meth");

something.Should()
.StartWith("so")
.And
.EndWith("ing")
.And
.Not.Contain("body");
var ints = new[] { 1, 2, 3 };
ints.Should()
.Have.SameSequenceAs(new[] { 1, 2, 3 })
.And
.Not.Have.SameSequenceAs(new[] { 3, 2, 1 })
.And
.Not.Be.Null()
.And
.Not.Be.Empty();

New ValueOf

ValueOf is a new property available in certain cases when we know the type during “constraints-chain”.

var instanceOfClass = new D2();

instanceOfClass.Should()
.Be.AssignableTo<D1>()
.And.Be.OfType<D2>()
.And.ValueOf.StringProperty
.Should().Be.Null();

New Actions constrains

(new Action(() => new AClass(null)))
.Should().Throw<ArgumentNullException>()
.And.
ValueOf.ParamName
.Should().Be.Equal("obj");

Obviously you can mix the classic assertion with NUnitEx API:

Assert.Throws<ArgumentNullException>(() => new AClass(null))
.ParamName.Should().Be.Equal("obj");

Exceptions assertions

These are some examples using NUnitEx syntax + LINQ

Giving:

public class SillyClass
{
public SillyClass(object obj)
{
if (obj == null)
{
throw new ArgumentException("mess",
new ArgumentNullException("mess null",
new ArgumentOutOfRangeException("obj")));
}
}
}

possible assertions are:

new Action(() => new SillyClass(null))
.Should().Throw<ArgumentException>()
.And.ValueOf.InnerExceptions()
.OfType<ArgumentOutOfRangeException>().First()
.ParamName.Should().Be.Equal("obj");

new Action(() => new SillyClass(null))
.Should().Throw<ArgumentException>()
.And.ValueOf.InnerExceptions().Select(e => e.GetType())
.Should().Contain(typeof(ArgumentOutOfRangeException));

new Action(() => new SillyClass(null))
.Should().Throw<ArgumentException>()
.And.ValueOf.InnerException
.Should().Be.OfType<ArgumentNullException>()
.And.ValueOf.Message.Should().Be.Equal("mess null");

What next

I didn’t see so many interest to have API available for NUnit2.4.8 so I would jump this step.

In term of NUnitEx internals what will be interesting is its implementation for xUnit and MbUnit, if somebody have interest I’m happy to share the project (somebody named Lars for example ;-) ).


kick it on DotNetKicks.com

22 March 2009

NUnitEx : News

After the very good feed back of the previous post, the new look of NUnitEx is:

Bollean Constraints:

actual.Should().Be.True();
actual.Should().Be.False();

Object Constraints:

actual.Should().Be.Equal(something);
actual.Should().Be.Null();
actual.Should().Be.SameInstanceAs(something);
actual.Should().Be.InstanceOf<SomeClass>();
actual.Should().Be.OfType<SomeClass>();
actual.Should().Be.AssignableFrom<SomeClass>();
actual.Should().Be.AssignableTo<SomeClass>(); 
actual.Should().Be.BinarySerializable();
actual.Should().Be.XmlSerializable();

Each constraint allow negation as : actual.Should().Not.Be.Equal(something);

Struct/Struct? Constraints

actual.Should().Be.LessThan(maxvalue);
actual.Should().Be.GreaterThan(minvalue);
actual.Should().Be.LessThanOrEqual(maxvalue);
actual.Should().Be.GreaterThanOrEqual(minvalue);
actual.Should().Be.Equal(actual);

Each constraint allow negation as : actual.Should().Not.Be.Equal(minvalue);

String Constraints

actual.Should().Be.Equal("a");
actual.Should().Be.Empty();
actual.Should().Be.Null();
actual.Should().Contain("some");
actual.Should().StartWith("some");
actual.Should().EndWith("ing");
actual.Should().Match("ome[tT]h");

Each constraint allow negation as : actual.Should().Not.Be.Equal("a string");

Enumerable Constraints

actual.Should().Have.SameSequenceAs(new[] { 1, 2, 3 });
actual.Should().Be.Null();
actual.Should().Be.Empty();
actual.Should().Be.SameInstanceAs(expected);
actual.Should().Contain(expected);
actual.Should().Have.SameValuesAs(new[] { 3, 2, 1 });
actual.Should().Have.UniqueValues();
actual.Should().Be.SubsetOf(new[] { 1, 2, 3, 4 });
actual.Should().Be.Ordered();

Each constraint allow negation as : actual.Should().Not.Have.SameSequenceAs(new[] { 3, 1 });

What next

Allow concatenation:

actual.Should().Not.Be.Null()
.And.Contain(expected)
.And.Have.UniqueValues();

Perhaps some new custom assertions for IEnumerable<T>.

Some constraints for Action as, for example:

new Action(() => new Something(null)).Should().Throw<ArgumentNullException>()
.Where.Message.Should().StartsWith("The parameter");

At last I’m studying the possibility to have the same API for others Unit-Test frameworks as xUnit, MbUnit and so on.

Remember that your feedback is very important.



kick it on DotNetKicks.com

10 March 2009

NUnitEx : actual.Should().EqualTo(expected)

After this thread, I have begun a new project on GoogleCode: NUnitEx.

The intention of the project is to be a “base-line” of a possible API implementation for NUnit3.0. As me, Charlie Poole, think that  “to have the code available is different than few-words and with this project we can "test" the acceptance of a possible API based on .Net3.5” (the phrase is mine and Charlie simply said “great!”).

NUnitEx is working on-top of NUnit, so you can mix NUnit classic assertions (Assert.That(…)) with NUnitEx assertions.

The short story

The first problem was define which should be the entry point… exactly… Should(), Should().Be, ShouldBe(), Should().Not.Be, ShouldBe().Not, Should().Contains, Should().EqualTo(exepected).WithMessage(message), Should().EqualTo(exepected).Because(message) and so on. The decision I have taken, so far, is: make it less verbose as possible maintaining Should() as the entry point.

The second problem was how much complicated should be the implementation. I have studied some NUnit2.4 internals and then I have compared it with NUnit2.5… well… to be short, the decision I have taken is: make it less complicated as possible and use NUnit from a point more external as possible.

Highlight

NUnit assertions/constraints are generics and polymorphic; generics because you can apply the same to everything (or near to it), polymorphic because the same constraint may change its behavior depending on the System.Type of actual/expected. Using NUnitEx this is not ever possible.

Take a look to the follows classic assertions :

Assert.That(true, Is.Null);
Assert.That(new object(), Is.True);

You can’t write the same using NUnitEx simply because an System.Boolean can’t be null or an System.Object can’t be a System.Boolean (the intellisense is your friend).

State of the art

Commons, and more used, constraints are implemented and the framework is usable.

So far the code-coverage is 100%.

Before begin the full implementation, of all constraints, a refactoring is needed in order to manage a more deeper methods-chaining leaving all methods with, at most, one parameter.

The discussion over the API is open; feel free to express your opinion.

To run NUnitEx tests you need to download the last available release of NUnit-Gui (2.5.0) available here.

When the heavy work will be done I’m planning to open a branch to support NUnit2.4.8.

Examples

DateTime.Today.Should().LessThan(DateTime.Now);
(5.0).Should().EqualTo(5);
((uint)10).Should().GreaterThan((short)4);
5.Should().LessThan(10);
(23.0m).Should().LessThan(double.MaxValue);

int? negableInt = 10;
negableInt.Should().EqualTo(10);
5.Should().LessThan(negableInt);
11.Should().GreaterThan(negableInt);
negableInt.HasValue.Should().True();
"a".Should().EqualTo("a");
"a".Should().Not.Empty();
"a".Should().Not.Null();
"".Should().Empty();
"".Should().Not.EqualTo("a");
((string) null).Should().Null();
var ints = new[] {1, 2, 3};
ints.Should().SequenceEqualTo(ints);
ints.Should().Not.SequenceEqualTo(new[] { 3, 2, 1 });
ints.Should().Not.Null();
ints.Should().Not.Empty();
(new int[0]).Should().Empty();
((IEnumerable<int>) null).Should().Null();
var ints = new[] { 1, 2, 3 };
ints.Should().Contains(2);
ints.Should().Not.Contains(4);

Where find NUnitEx

The project is really fresh, bins and sources are available here.


kick it on DotNetKicks.com