Automatically Generating Multi-Language & Convention Based Test Objects With NAuto

After many years of writing boilerplate test models, random string generators and test builder pattern objects, my colleague Andrew Jutton and I have put together a collection of really useful test helpers into a new open source project called NAuto.

There are a number of really cool features which we believe are massively beneficial and time saving when writing unit and integration tests.

Please check out the project documentation site http://amido.github.io/NAuto/.

 

I’ll create a series of posts showing off the features and benefits as I’m really proud of it and truly believe people will love using it. Please grab the NuGet package and have a play, all feedback will be greatly appreciated.

 

To whet your appetites, here’s just one of the features…

 

NAuto.AutoBuild Overview

One of the key features of NAuto is AutoBuild.

It will take pretty much any models including deep object graphs and quickly populate them with data, even if the model contains complex lists, dictionaries, custom types and types without default constructors.

It will also let you easily switch characters sets between numerous languages such as:

  • English
  • Traditional Chinese
  • Russian
  • German
  • Pinyin
  • Spanish
  • Italian
var testModel = NAuto.AutoBuild<TestModel>()
    .Construct()
    .Build();
var testModel = NAuto.AutoBuild<TestModel>()
    .Configure(x => x.DefaultLanguage = Language.Russian)
    .Construct()
    .Build();

Overriding & Conditionals

The generated data can easily be overridden using the With method. there a number of useful overloads but a simple example would look like the following:

var testModel = NAuto.AutoBuild<TestModel>()
    .Construct()
    .With(x => x.LastName = "MyOverridenLastName")
    .Build();

You can also use conditional statements to control how data is generated:

var testModel = NAuto.AutoBuild<TestModel>()
    .Construct()
    .If(x => x.FirstName == "Joe")
    .Then(x => x.ContactDetails.EmailAddress = "joe.bloggs@test.com")
    .Build();

 

AutoBuilder Conventions

The AutoBuilder accepts a configuration object which can be used to tweak how data is created, whilst this is a necessary feature, a much more interesting and powerful way to control AutoBuilder is by utilising the conventions configuration.

There are a number of different and more efficient ways to add a convention to AutoBuilder which I’ll cover in future posts, for now I just want to show what they look like and how useful they are.

A typical convention looks like the following (see the .AddConvention line):

var testModel = NAuto.AutoBuild<TestModel>()
    .Configure(x => x.DefaultLanguage = Language.Russian)
    .AddConvention(ConventionFilterType.Contains, "email", typeof(string), c => NAuto.GetRandomPropertyType(PropertyType.Email))
    .Construct()
    .ToJson();

Instead of calling Build() I have called ToJson(), the resulting output from this call is:

{
  "firstName": "Угдрг",
  "lastName": "Йшц",
  "contactDetails": {
    "emailAddress": "жф9ш1з2ц4а8н23ецб@19дтха8рчу4лмви.com"
  }
}

For clarity, here is the TestModel class:

      public class TestModel
    {
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public ContactDetails ContactDetails { get; set; }
    }

    public class ContactDetails
    {
        public string EmailAddress { get; set; }
    }

As you can see, for any property no matter how deep in the object graph (max depth limit can be configured), if the property is a string and contains the text “email”, a random email address is generated using the NAuto.GetRandomPropertyType method.

You might notice that the first name and last name are in Propercase and only contain russian alpha characters, this is because AutoBuilder comes with a predefined set of conventions which you can use or discard if not required.

 

Anyway, please check it out and let me know what you think.

The project will continue to improve overtime and should not disappear into the open source ether as it is a library we use at work.

Have fun.

Sean.

7 Comments

  • Havent You tried Autofixture? :)

  • Hi Mic,

    Definitely, and NBuilder. both really cool libraries and I like them both.

    The AutoBuild feature certainly contains very similar functionality, especially as it is generally utilising the test builder pattern so inevitably they all look pretty similar.

    The main differences are around approach, configuration and syntax which were mainly driven through how we work.

    Inevitably NBulider and AutoFixture are far more mature libraries and I would certainly still use them on projects, this library just has a few features that make the way we are testing a little easier.

    If you get chance though, have a play and see what you think :)

    Cheers,

    Sean.

  • How does this play with Entity Framework (circular references etc)? I've had limited success with AutoFixture - an EF model autobuilder is something that I have been after for a while...

  • Hi Alex,

    I've been out on the beers tonight so can't try it out at the moment but I'm 100% sure it will populate the model fine and will not stack overflow as there is a configurable max depth that the library will go to - defaults to 5 levels deep.

    What it doesn't do though it set the parent property to the actual parent, it will just construct and randomize a new object. If what you need is the parent property being set to the actual parent, let me know as it sounds like a relatively simple feature to add to the next release.

    Cheers,

    Sean.

  • I ran some test using NAuto on our domain objects. In some cases we define our own collection objects that inherit from Collect. Then in our constructors we take a typed list. Using NAuto it fails to populate our custom collection objects. I was going to take a look at your source code but I don't see it published.

  • Hi Mark, the source is on GIT Hub https://github.com/amido/NAuto

    Collection wise at the moment it supports arrays, generic lists and dictionaries, we do plan to do more work on handling collections in the future but the majority of the time the 3 mentioned collections are the most typical we use, hence the support.

    I'll certainly add your scenario to our trello list

    Cheers,

    Sean.

  • 6Lh2kx I appreciate you sharing this article.Really looking forward to read more.

Comments have been disabled for this content.