Try fast search NHibernate

Showing posts with label Tests. Show all posts
Showing posts with label Tests. Show all posts

16 October 2010

Sharp Tests Ex 1.1.0 RTM

Sharp Tests Ex 1.1.0 RTM was released today.

Mayor changes are related to some internal matters and references to specific framework.

Now you can use SharpTestsEx even to test your Silverlight4 applications.

Download it and : Happy testing!!!

29 June 2010

Alt.Net Hispano Vale!!

Bueno, que Alt.Net Hispano, con todo su aporte, Vale mucho ya lo saben.

La novedad es que el sabado pasado, para llenar un sabado sin VAN, hicimos un Alt.Net café con un poco de ejercicio de TDD al estilo Maulo (que vendría a ser como me sale a mi).

El resultado es que nació un nuevo framework de validación que se espera nos sirva para involucrar más gente al mundo OpenSource y, tal vez, para generar otros ejemplos de varias herramientas y tecnicas que el mundo Alt.Net quiere mucho.

El video del encuentro, como siempre, lo pueden ver en el wiki de las reuniones .

El sitio del nuevo framework es http://vale.codeplex.com/ y su nacimiento fue grabado en un screencast:

30 May 2010

Sharp Tests Ex 1.0.0 release

I’m happy to announce the final release of Sharp Tests Ex 1.0.0

After use it so long time in various projects (Open Source and commercial) without any kind of problems, enjoying its fluent interface and its ‘Satisfier’, is time to put a final point to its first version.

In these months I have enjoined most of users comments as, for example, the anagram of the project name : Sharp Test sEx.

In one issue, a user has defined it as “sexy framework”… so true that Sharp Tests Ex has its Satisfier ;)

Few moths ago the NHibernate team has approved the usage of Sharp Tests Ex in our tests and now, that it is stable, I can use it even in NHibernate.

before Sharp Tests Ex was as you can hear here but now: I can get satisfaction!!
Enjoy it!!… with moderation… LOL

13 April 2010

Sharp Tests Ex 1.0.0RC2 was released

Sharp Tests Ex 1.0.0RC2 was released today.
There are two mayor news:
  • the Executing static class
  • the Executing extension

The Executing static class

It is the replacement of the previous ActionAssert static class that now is marked as obsolete and will be removed after final release of 1.0.0.
The difference with ActionAssert will be more clear seeing the implementation of the new class:
public static class Executing
{
  public static Action This(Action action)
  {
    return action;
  }
}


As you can see it is a simple and real short-cut for Actions Assertion.

This class is particularly useful to test constructors:

Executing.This(() => new AClass(null)).Should().Throw<ArgumentNullException>();

and obviously with chains:

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

The Executing extension

Working with Sharp Tests Ex I have noticed how much difficult is leave the fluent-assertion and go back to a static Assert. Previous to 1.0.0RC2 the only way to create an Assert for a method execution was through ActionAssert and each time I have used it I felt a strange sensation. To fix the problem here come the Executing extension.

Given a class like this:

public class MyClass
{
  public void DoSomething(string value)
  {
    if (value == null)
    {
      throw new ArgumentNullException("value","My message");
    }
  }
}

the tests of the method may look like:

var myClass = new MyClass();
myClass.Executing(a => a.DoSomething(null)).Throws<ArgumentNullException>();
myClass.Executing(a => a.DoSomething("somethig")).NotThrows();

and even in this case you can use chains as usual:

myClass.Executing(a => a.DoSomething(null)).Throws<ArgumentNullException>()
.Exception.Satisfy(ex => ex.ParamName == "value" && ex.Message.Contains("My message"));


Enjoy the new release downloading it !

08 March 2010

AAA with Moq and Sharp Tests Ex

Log time ago I have added an issue to Moq’s issue-tracker (the issue here) and today I will show you why it can be closed.

In your application you have some places where a class is “working as a bridge” between two others. this is a common situation in MVP (Model View Presenter) and in MVC (Model View Controller).

To test “the bridge” in many case you want mock the others two classes (note: the test is needed even when you are using a Object2Object auto-mapper).

In pure AAA style the test may look as this (I have simplified it):

[TestMethod]
public void WhenPresentCallServiceRegisterThenValuesAreMappedFromView()
{
var view = new Mock<IUsuarioParticularNuevoView>();
var service = new Mock<IUsuarioParticularNuevoService>();

view.SetupGet(v => v.Contraseña).Returns("pizza");
view.SetupGet(v => v.AceptaTermino).Returns(true);
view.SetupGet(v => v.Apellido).Returns("Fulano");
view.SetupGet(v => v.CiudadSelecionadaId).Returns(100);
view.SetupGet(v => v.CodigoPostal).Returns("AC123");
view.SetupGet(v => v.Email).Returns("pizzaCALDA");
view.SetupGet(v => v.EsHombre).Returns(false);
view.SetupGet(v => v.FechaNacimiento).Returns(DateTime.Today);
view.SetupGet(v => v.Nombre).Returns("Mengano");
view.SetupGet(v => v.OrigenReferencia).Returns("Amigo");
view.SetupGet(v => v.ProvinciaSelecionadaId).Returns(123);
view.SetupGet(v => v.RecibeNoticias).Returns(false);
view.SetupGet(v => v.TelefonoArea).Returns("011");
view.SetupGet(v => v.TelefonoNumero).Returns("123456");
view.SetupGet(v => v.OrigenRegistracion).Returns("yahoo");

var pre = new UsuarioParticularNuevoPresenter(view.Object, service.Object);
pre.Register();

service.Verify(
s =>
s.Register(
It.Is<UsuarioNuevoInfo>(
uni =>
uni.AceptaTermino && uni.Apellido == "Fulano" && uni.CiudadSelecionadaId == 100 && uni.CodigoPostal == "AC123"
&& uni.Contraseña == "pizza" && uni.Email == "pizzacalda" && uni.EsHombre == false
&& uni.FechaNacimiento == DateTime.Today && uni.Nombre == "Mengano" && uni.OrigenReferencia == "Amigo"
&& uni.ProvinciaSelecionadaId == 123 && uni.RecibeNoticias == false && uni.TelefonoArea == "011"
&& uni.TelefonoNumero == "123456" && uni.OrigenRegistracion == "yahoo")));
}

I know that I have two bugs in the implementation of the class UsuarioParticularNuevoPresenter but how can I know which are if the failure message is this:

Test method MoqSharpTestsEx.ShowTest.WhenPresentCallServiceRegisterThenValuesAreMappedFromView threw exception: Moq.MockException:
Expected invocation on the mock at least once, but was never performed: s => s.Register(It.Is<UsuarioNuevoInfo>(uni => ((((((((((((((uni.AceptaTermino && (uni.Apellido = "Fulano")) && (uni.CiudadSelecionadaId = 100)) && (uni.CodigoPostal = "AC123")) && (uni.Contraseña = "pizza")) && (uni.Email = "pizzacalda")) && (uni.EsHombre = False)) && (uni.FechaNacimiento = DateTime.Today)) && (uni.Nombre = "Mengano")) && (uni.OrigenReferencia = "Amigo")) && (uni.ProvinciaSelecionadaId = 123)) && (uni.RecibeNoticias = False)) && (uni.TelefonoArea = "011")) && (uni.TelefonoNumero = "123456")) && (uni.OrigenRegistracion = "yahoo")))).

If you are following my blog you know that there is something new in the .NET ecosystem : Sharp Tests Ex and its Satisfier.

What I need to do, to have a more readable failure message, is really simple:

service.Verify(
s =>
s.Register(
It.Is<UsuarioNuevoInfo>(
ui =>
ui.Satisfy(
uni =>
uni.AceptaTermino && uni.Apellido == "Fulano" && uni.CiudadSelecionadaId == 100 && uni.CodigoPostal == "AC123"
&& uni.Contraseña == "pizza" && uni.Email == "pizzacalda" && uni.EsHombre == false
&& uni.FechaNacimiento == DateTime.Today && uni.Nombre == "Mengano" && uni.OrigenReferencia == "Amigo"
&& uni.ProvinciaSelecionadaId == 123 && uni.RecibeNoticias == false && uni.TelefonoArea == "011"
&& uni.TelefonoNumero == "123456" && uni.OrigenRegistracion == "yahoo"))));

Can you see the difference ?
Well does no matter… you will see the difference in the failure message :

MoqSharpTestsEx.UsuarioNuevoInfo Should Satisfy (uni => uni.Email == "pizzacalda")
Strings differ at position 6.
pizzaCALDA
pizzacalda
_____^____

And

MoqSharpTestsEx.UsuarioNuevoInfo Should Satisfy (uni => uni.EsHombre == False)

I’m going to say that issue can be closed because I’m a Sharp Tests Ex user.

Are you satisfying your tests ?

06 February 2010

Sharp Tests Ex RC

Sharp Tests Ex 1.0.0 was released today. You can download it from here.

There are few issues fixed:

* Executing two times the Expression cause unexpected not failing Assertion
* Add EqualTo to boolean constraint
* intValue.Should().BE(5) as short-cut instead EqualTo

The SharpTestsEx’s API is now considered stable, how much ? we will use SharpTestsEx for NHibernate-Core tests as we are using it in NHibernate.Validator.

Happy testing!!

25 December 2009

SharpTestsEx 1.0.0Beta : Satisfy your test

SharpTestsEx 1.0.0 was released today. You can download it from here.

More than few improvements, regarding some assertions and its failure message, and some internal refactoring, the mayor change is about the “satisfier”.

To talk about the syntax of the satisfier is something hard basically because there is no syntax. From user side of view, using the satisfier, the assertion is a simple and pure Func<TA, bool>.

From our side of view, the satisfier is the challenge of show an understandable failure message and, perhaps, help you to understand own much readable and self-explained is the name of some method.

Let me show you some example to understand how the satisfier works.

Example 1

Given this empty class

public class Session
{
public bool IsOpen { get; private set; }
public void Open() {}
public void Close() {}
}

The test to pass is:

var session = new Session();
session.Satisfy(s => !s.IsOpen);
session.Open();
session.Satisfy(s => s.IsOpen);
session.Close();
session.Satisfy(s => !s.IsOpen);

The test fail with this message:

SharpTestsExExamples.Session Should Satisfy (s => s.IsOpen)

Implementing the Open method the failure message is:

SharpTestsExExamples.Session Should Satisfy (s => !(s.IsOpen))

Example 2 (using Enumerable and LINQ)

In this case the value under test is a IEnumerable<int>:

var ints = new[] { 1, 2, 3 };
With
ints.All(x => x.Satisfy(a => a < 3));

The failure message is : 3 Should Satisfy (a => a < 3)

As you can see the extension Satisfy can be used even as a predicate inside a LINQ expression and, in this way, only the value breaking the test will be showed.

With
ints.Satisfy(a => a.All(x => x < 3));

The failure message is : [1, 2, 3] Should Satisfy (a => a.All(x => x < 3))

The same result using Any
ints.Any(x => x.Satisfy(a => a > 5));

The failure message : 1 Should Satisfy (a => a > 5)

Example 3 (method call)

var actual = "sometXing";
actual.Satisfy(a => a.ToUpperInvariant().Contains("TH"));

Fail with : "sometXing" Should Satisfy (a => a.ToUpperInvariant().Contains("TH"))

Example 4 (LINQ method call)

var ints = new[] { 1, 2, 3 };
ints.Satisfy(a => a.SequenceEqual(new[] { 3, 2, 1 }));

As you know SequenceEqual is a LINQ extension method included in .NET 3.5 and the satisfier will recognize it and will show:

[1, 2, 3] Should Satisfy (a => a.SequenceEqual(new[] {3, 2, 1}))
Values differ at position 0.
Expected: 3
Found : 1

Example 5 (equal)

var amount = 135.25m;
amount.Satisfy(a => a == 135m);

Fail with: 135,25 Should Satisfy (a => a == 135)

but

var name = "ErmAnegildo";
name.Satisfy(a => a == "Ermenegildo");

Fail with :

"ErmAnegildo" Should Satisfy (a => a == "Ermenegildo")
Strings differ at position 4.
ErmAnegildo
Ermenegildo
___^_______

Example 6 (complex predicate)

var actual = "somexxing";
actual.Satisfy(a => a.StartsWith("some") && a.Contains("TH") && a.EndsWith("ing"));

As you can see the assertion is composed by three conditions where only one will fail. The failure message will be:

"somexxing" Should Satisfy (a => a.Contains("TH"))

The same assertion but using “somexxING”, as actual value, will fail with:

"somexxING" Should Satisfy (a => a.Contains("TH"))
And
"somexxING" Should Satisfy (a => a.EndsWith("ing"))

Another example using a more “real” case:

var users = new UsersRepository();
users.Where(u => u.IsActive)
.Satisfy(a => a.Count() == 3 && a.Any(u => u.Name == "John") && a.Any(u => u.Name == "Fabio"));

The class UsersRepository is a IRepository<User> and the User class implements ToString returning the Name property. The repository contains three active users and does not contain an active User named Fabio. The failure message is:

[John, Frank, Marcus] Should Satisfy (a => a.Any(u => u.Name == "Fabio"))

Conclusions

If you are involved in various projects where one use MsTests another use xUnit another use NUnit you don’t need to remember which is the name of the Assertion class nor the syntax of the assertion itself, nor if the first parameter is the expected or the actual… what you need is only write “.Satisfy(” and continue writing pure C# predicate.

Satisfy your test with Sharp Tests Ex.

15 November 2009

Refactorizing tests

I had read, in some place on the cloud, that SharpTestsEx make the test more verbose even if it is more readable.

In NHibernate.Validator (NHV) we are using #TestsEx. After implements some new features I’m improving some stuff where I’m needing a little breaking change.

This is an existing test using classic NUnit syntax:

[Test]
public void CreditCard()
{
CreditCard card = new CreditCard();
card.number = "1234567890123456";
IClassValidator classValidator = GetClassValidator(typeof(CreditCard));
InvalidValue[] invalidValues = classValidator.GetInvalidValues(card);
Assert.AreEqual(1, invalidValues.Length);
card.number = "541234567890125"; //right CC (luhn compliant)
invalidValues = classValidator.GetInvalidValues(card);
Assert.AreEqual(0, invalidValues.Length);
card.ean = "9782266156066";
invalidValues = classValidator.GetInvalidValues(card);
Assert.AreEqual(0, invalidValues.Length);
card.ean = "9782266156067";
invalidValues = classValidator.GetInvalidValues(card);
Assert.AreEqual(1, invalidValues.Length);
}

The breaking change is about the return value of GetInvalidValues : in NHV1.2.0 the method will return IEnumerable<InvalidValue>.

Refactoring step 1

Same but compileable.

[Test]
public void CreditCard()
{
CreditCard card = new CreditCard();
IClassValidator classValidator = GetClassValidator(typeof(CreditCard));

card.number = "1234567890123456";
Assert.That(classValidator.GetInvalidValues(card), Is.Not.Empty);

card.number = "541234567890125"; //right CC (luhn compliant)
Assert.That(classValidator.GetInvalidValues(card), Is.Empty);

card.ean = "9782266156066";
Assert.That(classValidator.GetInvalidValues(card), Is.Empty);

card.ean = "9782266156067";
Assert.That(classValidator.GetInvalidValues(card), Is.Not.Empty);
}
Refactoring step 2
[Test]
public void CreditCard()
{
CreditCard card = new CreditCard();
var classValidator = GetClassValidator(typeof(CreditCard));

card.number = "1234567890123456";
classValidator.GetInvalidValues(card).Should().Not.Be.Empty();

card.number = "541234567890125"; //right CC (luhn compliant)
classValidator.GetInvalidValues(card).Should().Be.Empty();

card.ean = "9782266156066"; //right EAN
classValidator.GetInvalidValues(card).Should().Be.Empty();

card.ean = "9782266156067"; //wrong EAN
classValidator.GetInvalidValues(card).Should().Not.Be.Empty();
}

Now, using SharpTestsEx, we can run the same test with xUnit, MsTests, MbUnit (if/when we will need/want change the unit test framework) and I can’t see where it is more verbose.

Refactoring step 3
[Test]
public void GivingValidState_NoInvalidValues()
{
var card = new CreditCard {Number = "541234567890125", Ean = "9782266156066"};
var classValidator = GetClassValidator(typeof(CreditCard));

classValidator.GetInvalidValues(card).Should().Be.Empty();
}

[Test]
public void GivingInvalidState_HasInvalidValues()
{
var card = new CreditCard {Number = "1234567890123456", Ean = "9782266156067"};
var classValidator = GetClassValidator(typeof(CreditCard));

classValidator.GetInvalidValues(card).Should().Have.Count.EqualTo(2);
}

Perhaps SharpTestsEx is a little bit more verbose, in some cases, but with your help we can improve it.

27 September 2009

Testing DAOs : the SetUpFixture Attribute

Usually I’m testing DAOs for CRUD operations. Using NHibernate, as persistent layer, what we are testing, in practice, is the mapping and all behavior we have defined in it (cascade, associations, types, user-types, custom-collections and so on).

For CRUD operation I mean single entity instance CRUD without test complex queries (to test complex-queries I’m using a different test suite with a Well-Known-Data-Base).

Testing NHibernate DAO implementation

The first step is the test of the generic/base implementation of the DAO. To test it I’m mocking NHibernate.

[Test]
public void Get_call_Get()
{
// Arrange
var sessionFactory = new Mock<ISessionFactory>();
var session = new Mock<ISession>();
sessionFactory.Setup(x => x.GetCurrentSession()).Returns(session.Object);

// Act
var dao = new Dao<FakeEntity, int>(sessionFactory.Object);
dao.Get(123);

// Assert
session.Verify(x => x.Get<FakeEntity>(It.Is<int>(id => id == 123)));
}

The CRUD test

A simple integration CRUD test may look like this:

[TestFixture]
public class MagazineTest
{
[Test]
public void MinimalCrud()
{
const int poid = 1;
var m = new Magazine(poid) {Title = "some title"};

var dao = new EntityDao<Magazine>(ServiceLocator.Current.GetInstance<ISessionFactory>());

using (new PersistenceRequest())
{
dao.MakePersistent(m);
ActionAssert.NotThrow(()=> dao.MakePersistent(m));
}

using (new PersistenceRequest())
{
var e = dao.Get(poid);
e.Should().Not.Be.Null();
e.Title.Should().Be.EqualTo("some title");
}

using (new PersistenceRequest())
{
var e = dao.Get(poid);
e.Title = "different title";
}

// should update through NHibernate's UoW
using (new PersistenceRequest())
{
var e = dao.Get(poid);
e.Title.Should().Be.EqualTo("different title");
}

// Delete
using (new PersistenceRequest())
{
var e = dao.Get(poid);
dao.MakeTransient(e);
}

using (new PersistenceRequest())
{
var e = dao.Get(poid);
e.Should().Be.Null();
}
}
}

The PersistenceRequest is an utility class I’m using to simulate the behaviour of the IHttpModule implementing the session-per-request pattern.

Note, the test-fixture does not inherit from a base class and does not have a any SetUp nor TearDown but indeed it need, at least, the configuration of the ServiceLocator, the configuration of NHibernate, the creation of schema, and so on.

For the whole CRUD-test-suite I want execute the configuration of the ServiceLocator, the configuration of NHibernate and its SessionFactory, just only one time and not before execute each test-fixture.

The SetUpFixture Attribute

Since few versions NUnit has a very useful feature: the SetUpFixture Attribute.TestingDaoCrud



To have only one initialization, for all my CRUD-tests, I’m putting all test-fixtures starting from a specific namespace (in the image the namespace is “Cruds”) where I have the implementation of the class, marked with the [SetUpFixture], responsible to create the context for all CRUD tests.


The implementation of the CRUD context look like:
[SetUpFixture]
public class CrudTestContext
{
private WindsorContainer container;

[SetUp]
public void Configure_NHibernate_and_ServiceLocator()
{
container = new WindsorContainer();
container.Register(Component.For<IServiceLocator>()
.Instance(new WindsorServiceLocator(container)));
ServiceLocator.SetLocatorProvider(() => container.Resolve<IServiceLocator>());

container.Register(Component.For<ISessionWrapper>()
.ImplementedBy<FakeSessionWrapper>());
container.Register(Component.For<IConfigurationProvider>()
.ImplementedBy<NhTestConfigurationProvider>());
container.Register(Component.For<ISessionFactoryProvider>()
.ImplementedBy<SessionFactoryProvider>());
container.Register(Component.For<ISessionFactory>()
.Instance(container.GetService<ISessionFactoryProvider>().GetFactory(null)));
}

[TearDown]
public void Close_NHibernate()
{
container.Dispose();
}
}

public class NhTestConfigurationProvider : DefaultSessionFactoryConfigurationProvider
{
public NhTestConfigurationProvider()
{
AfterConfigure += ValidateOrCreateSchema;
}

private void ValidateOrCreateSchema(object sender, ConfigurationEventArgs e)
{
try
{
new SchemaValidator(e.Configuration).Validate();
}
catch (HibernateException)
{
var export = new SchemaExport(e.Configuration);
export.Drop(false, true);
export.Create(false, true);
}
}
}

If you want use the [SetUpFixture] you must use a NUnit2.5 compatible test-runner (ReSharper 4.5 does not support it).

UPDATE : I'm sorry, ReSharper 4.5 does SUPPORT it.

23 September 2009

Sharp Tests Ex 0.3.0 : fluent and lambda assertions for MsTests, NUnit and xUnit

#TestsEx 0.3.0 was released yesterday.

News

The first news is that #TestsEx is no more a “one-man-show”; Jason Diamond is now part of the team.

The second news is that the new syntax, based on lambda expression, is now available (similar to the one available in NUnitEx). You can see an example in the download page.

var var2 = 2;
2.Satisfy(a => var2 == a);
1.Satisfy(a => a == 1 || a != 0);

The mayor advantage of the “Satisfy syntax” is that it is pure C#; perhaps is less readable but you don’t need to know the name of an assertion and its “extensible limit” is the same you have in C#. Even if this feature is available and can be used right now, we are working to improve the failure message.

The breaking change

Perhaps this is the first time I’m happy to announce a breaking change. Starting from this release, to use #TestsEx extensions, you must specify the using clause.

using SharpTestsEx;

Why ? #TestsEx, now can be used with your preferred unit test framework.

We are supporting MsTests, NUnit and xUnit.

For MsTests

You must add the reference to SharpTestsEx.MSTest.dll in your test project.

For NUnit

You must add the reference to SharpTestsEx.NUnit.dll in your test project.

For xUnit

You must add the reference to SharpTestsEx.xUnit.dll in your test project.

For others

For others frameworks you can use SharpTestsEx.dll but, probably, you will see SharpTestsEx in the stack trace of the failure message in your test runner.

If you are working in various projects, using various unit tests frameworks, now you have one more reason to use #TestsEx.

Important

Sharp Tests Extensions is a compendium of commons “extensible extensions” to work with your preferred unit test framework and not another test framework.

The Syntax overview is available here.

Happy testing!!

01 September 2009

Test runner poll : results

My conclusion is:

Developers prefer solutions integrated with IDE to run tests during development.

24 August 2009

NHibernate battle

Sorry but I can’t write this in english.

Bueno el guerrero, como se dice en la ciudad porteña, “arrugó”.

Miren este lindo post y las dos páginas de comentarios. A parte el ataco personal a Oren (aka Ayende) está muy claro que el sitio nació con el intento de publicizar un producto comercial.

Mis preguntas fueron:

You said "We've shown our product wins almost all the competitors on CUD tests", which is "your product" ?
Can you confirm that the code of the test of "your product" represent the best optimization you can do ?

A nuestro aspirante guerrero, y comercial promoter, le costó un poco mandarme el link del producto comercial y a la segunda pregunta contestó de la siguiente manera:

No, obviously, I can't confirm this. It will be much better this month. On the other hand, all we did was enough to show there is a lot of room for performance optimizations.

En Buenos Aires eso se nombra : “arrugar”.

En otro blog el chico pide que quien le diga que su test de performance está muy cercano a un MDTD (Monkey Driven Test Development), y por lo tanto no significativo, me pide que nosotros seamos quien provea un test que represente la realidad, lo cual es muy grave. ¿Estamos hablando de alguien que pretende publicitar un producto comercial sin tener idea de como crear un test de performance usando casos reales? ¿Que tendría que esperarme de ese producto?

Mirando parte del test me quedó claro que, deliberadamente o no, nisiquiera aplicaron la best practices que están claramente descriptas en las reference de NHibernate y no solo no aplicaron cosas como la descriptas en esta wiki si no que directamente la pasaron como algo no suportado por NHibernate. Yo no se como son las legislaciones internacionales pero eso, en Italia, estaría penalizado como “publicidad engañosa”.

Igual hay que felicitar al chico porque : No importa que se hable bien o mal lo importante es que se hable del producto… alguien va a caer seguro.

23 August 2009

NHibernate Perfomance: Analisys

In this post I will show the results of the previous post from another point of view hoping it would be useful to Gergely Orosz to understand how work with NHibernate to have better performance for his test (in that post you can download the original code).

The environment

Pentium D840, 3GB ram, winXP, MsSQL2008Express, .NET3.5, NHibernate2.1.0GA.

The domain is the same:

domain

where each Company has 24 Employees and each employee has 24 Reports (save a company mean save 601 entities).

Storing data

The StoreData test is basically a bulk insertion, of the domain, importing data from XML. To have better performance, in bulk inserts, there are basically two “tricks” as described in NHibernate reference (see Chapter 12): the adonet.batch_size and the StatelessSession. If you know how work the batcher, studying the code or watching the SQL log or reading this post, you can even change your code to improve performances having less round trips.

I haven’t used an “extreme” configuration (batch_size=500) but the result is:

To save 24 Companies, that mean 14424 entities, my code toke 39 roundtrips (in 5 transactions).

This result mean ~3050 entities per second, with normal behavior, and ~5300 entities per second using compiled queries (note the domain is something with parent-child relationship and a big NVARCHAR and not the same used by ORMBattle.NET).

If I play a little bit more, with the code, I may have even better performance.

Read All

Here I can show the code:

IList<NHCompany> result;
using (var session = Sf.OpenSession())
{
result = session.GetNamedQuery("NHCompany.All").List<NHCompany>();
}
foreach (NHCompany company in result)
{
writer.WriteLine(company);
foreach (NHEmployee employee in company.Employees)
{
writer.WriteLine(employee);
foreach (NHReport report in employee.Reports)
{
writer.WriteLine(report);
}
}
}

As you can see “read all” mean literally read-all and then show results in a log file. The difference here is that I’m loading 24 companies with all his employees and all reports (again 14424 entities) in only one roundtrip and only one SQL.

Read by ID

Again the code:

foreach (Company company in companies)
{
NHCompany foundCompany;
using (ISession session = Sf.OpenSession())
{
foundCompany = session.GetNamedQuery("NHCompany.One")
.SetInt32("pId", company.Id).UniqueResult<NHCompany>();
}

writer.WriteLine(foundCompany);
foreach (var foundEmployee in foundCompany.Employees)
{
writer.WriteLine(foundEmployee);
foreach (var foundReport in foundEmployee.Reports)
{
writer.WriteLine(foundReport);
}
}
}

Which sense has this test I don’t know, by the way it is loading again each company (24) with all his employees and all reports (again 14424 entities) but, in my implementation, in only 24 roundtrips.

Update

foreach (NHCompany company in companies)
{
company.Name += valueToAdd;
foreach (NHEmployee employee in company.Employees)
{
employee.Name += valueToAdd;
foreach (NHReport report in employee.Reports)
{
report.Text = valueToAdd + report.Text;
}
}
session.Update(company);
}

This code is updating each entity (again 14424) and I’m doing it in 5 transactions. Thanks to this test I found a missed feature in NHibernate (the code is there but the configuration does not allow its usage) because, so far, this code is working using 49 roundtrips per each company when we can obtain the same final result with 39 roundtrips in total (for all 14424). As you can see I’m using a normal ISession (you can see it because there is only a session.Update and StateLessSession does not work with cascade).

Even if NH2.1.0GA is performing this test in 49 roundtrips per each company, the final result is ~1550 updates per second, with normal behavior, and ~2450 updates per second using compiled queries.

Delete

public override void DeleteData()
{
using (var session = Sf.OpenStatelessSession())
using (var tx = session.BeginTransaction())
{
session.CreateQuery("delete from NHCompany").ExecuteUpdate();
tx.Commit();
}
}

Well… is there something to say here ?

It is an entirely database clean in only one SQL and only one roundtrip in only one transaction.

Conclusions

I’m sorry with Gergely because his fault was “only” to publish the wrong post in the wrong moment; as I said before, in other moment my reaction would be only close the browser.

Anyway my opinion about MDTD continuing being the same (MDTD = Monkey Driven Test Development).

17 August 2009

Test runner poll

I need your help to have a better sample for this poll:

You can choose more than one options.

Thanks.

15 August 2009

Developing #TestsEx

I’m developing some new features in SharpTestsEx.

This is the test:

[TestMethod]
public void GetMessage()
{
var ass = new OrAssertion<int>(new AssertionStub<int>("Left message"),
new AssertionStub<int>("Right message"));

var lines = ass.GetMessage(1, null)
.Split(new[] {Environment.NewLine}, StringSplitOptions.None);

lines.Should().Have.SameSequenceAs("(Left message)", "Or", "(Right message)");
}

and, after the first implementation this was the failure message

Failure

Clear without run in debug… I love it!!!

12 August 2009

#TestsEx Apla2 was released

Sharp Tests Ex Alpha2 was released today (download).

In the wiki is now available the Syntax overview.

One of the challenge of this version was rewrite all failure messages to magnify the cause of the failing test.

stringStart

stringNull

StringComparison

RegEx

UniqueValues

Ordered

SameValuesAs

Similar messages are available for all other assertions.

The next step.Should().Be. the syntax for lambda based assertions as:

const int y = 2;
const int z = 4;
4.Should().Satisfy(x => x == y * y);
2.Should().Satisfy(x => x == z / y);

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!!

11 August 2009

NUnit2.5.2 was released

NUnit 2.5.2 was released yesterday.

More than some bug fix and so on it has some new syntax for exception testing.

The release note is available here.

Ok, time for a new release of NUnitEx (perhaps tonight).

08 August 2009

#TestsEx: who was born first the chicken or the egg?

I’m refactoring and improving #TestsEx.

For serialization assertion I found that the message was not so clear if the actual value, under test, is null.

So I wrote this new test before change framework code:

[TestMethod]
public void SerializableNullShouldThrowClearException()
{
Seri actual = null;
ActionAssert.Throws<ArgumentException>(()=> actual.Should().Be.BinarySerializable())
.Message.ToLowerInvariant().Should().Contain("can't check serialization for (null) value");
ActionAssert.Throws<ArgumentException>(() => actual.Should().Be.XmlSerializable())
.Message.ToLowerInvariant().Should().Contain("can't check serialization for (null) value");
}

So… I’m testing #TestsEx using #TestsEx assertions.

Who was born first the chicken or the egg ?

07 August 2009

SharpTestsEx Alpha1: MsTests Extensions

#TestsEx is a set of extensible extensions to work with MsTests. The main target is write short assertions where the Visual Studio intellisense is your guide.

The story

In the lasts two days I remembered why I’m not using MsTests. When I began working with VisualStudio, was using the Express edition that does not have the MsTests suite. One of my customer wants use MsTests because “it is fully integrated and I don’t need to buy/use something else”. When I tried to create a simple test only to try MsTests… surprise surprise I have discovered the state of the art; Oh my God!! Pretty good front end, pretty good runner, very few Attributes to define tests, a not understandable UnitTest generator and, even worst, a very small set of assertions. Ok… I know, I’m an addict of NUnitEx but MsTests seems to stay at the same state of some jurassic NUnit version… Critic without a solution ?

Introduction

Before start a new framework, I began a little proof of concept to understand which are the extensions point of MsTests and… (again) surprise surprise MsTests is a monolithic piece of code no OO : static classes with implementation in static methods and few utilities classes declared internal… again… Oh my God!! perhaps, in Microsoft, some team should talk with some other team.

Manos a la obra

The first step was create a real easy extensible Assertion. Easy extensible… perhaps it should not need to be inherited

public Assertion(string predicate, TE expected, Func<TA, bool> match,
Func<MessageBuilderInfo<TA, TE>, string> messageBuilder)

After that was only a matter of write code.

The state of the art

Even if this is the first alpha the project is ready to be used. It need some improvement about Failure Messages and, over all, your ideas.

The #TestsEx project is here. Download.

Happy testing, even in MsTests, with SharpTestsEx32x32White #TestsEx