Brian McKeiver's Blog

Generate Realistic Test Data in Kentico


Introduction

Recently I wanted to play around with some user specific scenarios in my Kentico instance for a presentation that I was working on. To do that I needed a Kentico 9 instance with a lot of various users, user settings, and role associations already setup. After firing up a few instances of Visual Studio and running locally, I realized that I didn't have any good sandboxes to play in. So I bit the bullet, and started down the path of automating the creation of a few hundred users.

I figured that there was no way it would take more than just a few minutes to do this task. It’s just creating a few users in Kentico which is like 4 or 5 lines of code in a for loop, right? As it turns out, there is a good way to do this, and then an even better way to do it using some freely available NuGet packages.

 

Generating Test Data in an Ok Way

As any good Kentico developer would do, I fired up a fresh instance and started working with the normal UserInfoProvider and UserInfo objects that the Kentico API is famous for. And indeed after a few short minutes I have some really vanilla code to work with.

 

string siteName = SiteContext.CurrentSiteName;
 
for (int i=0; i<100; i++)
{
    // Creates a new user object
    UserInfo newUser = new UserInfo();
 
    // Sets the user properties
    newUser.FullName = "first lastname";
    newUser.Email = "test@test.com";
    newUser.UserName = newUser.Email;
    newUser.PreferredCultureCode = "en-us";
    newUser.Enabled = true;
    
    // Inserts the users to the database
    UserInfoProvider.SetUserInfo(newUser);
 
    //Associates the user to the site
    UserInfoProvider.AddUserToSite(newUser.UserName, siteName);
 
    //Registers analytics for new user registration
    AnalyticsHelper.LogRegisteredUser(siteName, newUser);
}

 

We’ve all seen code like this before, maybe even in the Kentico 9 API examples that are available. The problem is that in this code the username is hard coded and that generates an error in Kentico the second time through the loop. Also way more importantly, if you correct that error by adding in an unique incrementor to the username, every user basically looks the exact same.

 

Kentico 9 Users

 

This sample data doesn’t really help me for my needs where I really wanted to look at more realistic data. So on to something better.

 

Doing it a Much Better Way with Faker.NET

After a bit of internet searching I stumbled upon Faker.NET. This free library is a C# version of a widely used Ruby project called faker. The library allows the user to generate realistic looking names, addresses, phone numbers, emails, locations and more. It’s pretty amazing and available via a simple NuGet package command in .NET.

 

Install-Package Faker.NET

 

With this library installed I can now change the guts of the code to:

 

string siteName = SiteContext.CurrentSiteName;
bool logOnlineMarketing = AnalyticsHelper.AnalyticsEnabled(siteName);
 
for (int i=0; i<100; i++)
{
    // Creates a new user object
    UserInfo newUser = new UserInfo();
 
    // Sets the user properties
    newUser.FullName = Faker.Name.FullName();
    newUser.Email = Faker.Internet.Email();
    newUser.UserName = newUser.Email;
    newUser.PreferredCultureCode = "en-us";
    newUser.Enabled = true;
    
    // Inserts the users to the database
    UserInfoProvider.SetUserInfo(newUser);
 
    //Associates the user to the site
    UserInfoProvider.AddUserToSite(newUser.UserName, siteName);
 
    if (logOnlineMarketing)
    {
        //Registers analytic hit for new user registration
        AnalyticsHelper.LogRegisteredUser(siteName, newUser);
    }
}

 

Running this code results in the following set of users being created in the system:

 

Kentico 9 Users with Realistic Test Data

 

As you can see the faker static objects like .Name.First(), .Name.Last(), .Name.FullName(), and .Internet.Email() are the magic. These objects use some sort of voodoo magic to generate realistic looking names and email addresses. There are tons of options for other objects like locations, phone numbers, and other cool things that you can use to populate just about any kind of normal string value in a web application. Pretty cool eh?

 

Pro Tip: There is also a great Data Generator for On-line Marketing data already in Kentico 9.

 

Doing it the Best way with Faker.NET and NBuilder

For loops are so 1970’s right? With all the LINQ rage that is happening today, who wants to write such old school syntax? Enter NBuilder, another third party NuGet package out there. NBuilder allows you to rapidly create test data, automatically assigning values to properties and public fields that are of type of the built in .NET data types (int, string etc). Really both NBuilder and Faker have been around for a long time and are nothing that new, but they were new to me, so I thought I would share.

Again to get the NBuilder package you just have to fire up the NuGet package manager console and run the following command:

 

Install-Package NBuilder

 

Utilizing NBuilder gets us to code that looks like this:

 

string siteName = SiteContext.CurrentSiteName;
bool logOnlineMarketing = AnalyticsHelper.AnalyticsEnabled(siteName);
 
//Very important to not jam in auto values that we don't want for NBuilder
BuilderSetup.AutoNameProperties = false;
 
//Create the new list of users
var users = Builder<UserInfo>.CreateListOfSize(100).All()
    .With(u => u.FullName = Faker.Name.FullName())
    .With(u => u.Email = Faker.Internet.Email())
    .With(u => u.UserName = u.Email)
    .With(u => u.PreferredCultureCode = "en-us")
    .With(u => u.Enabled = true)
.Build();
 
foreach (UserInfo user in users)
{    
    // Inserts the users to the database
    UserInfoProvider.SetUserInfo(user);
 
    //Associates the user to the site
    UserInfoProvider.AddUserToSite(user.UserName, siteName);
 
    if (logOnlineMarketing)
    {
        //Registers analytic hit for new user registration
        AnalyticsHelper.LogRegisteredUser(siteName, user);
    }
}

 

The reason that I liked NBuilder is the fact that it is a very clean way to generate a list of objects in bulk. It gives you some fluent style syntax and is meant to work with persistent storage (mainly Entity Framework) like the Kentico database. The results of running the code above is exactly the same as the previous example, but cleaner and more readable.

One special note is that if you don't add the AutoNameProperties to false line, NBuilder tries to fill in all the values of the object it can, including things like ObjectID and ObjectGUID. This is bad news for the Kentico API. So make sure you don't forget it.

Another nice bonus of NBuilder is the very nice utility method it has, RandomGenerator(). Using this object allows you to quickly work with a random object to randomize property values. This comes in handy with things like DateTimes and data relationships (think CMS Role associations or CMS Site Associations). Basically you can use code like the following to randomize the create date and/or last logged on date of the users. Again this is all in an effort to have realistic test data in your Kentico site.

 

var users = UserInfoProvider.GetUsers().WhereEquals("UserPrivilegeLevel"0);
 
var daysGenerator = new RandomGenerator();
 
foreach (UserInfo user in users)
{
    user.UserCreated = DateTime.Now.AddDays(-daysGenerator.Next(1600));
    UserInfoProvider.SetUserInfo(user);
}

 

Running this code will get you a result with not only randomly created names, but also random CreatedOn dates for the users.

 

Kentico 9 Users with Realistic Test Data with Created

 

Conclusion

All of the kudos do belong to the library authors of Faker.NET, NBuilder, and of course the Kentico API. You could also use this approach for unit testing and automated QA tasks. In fact my QA Specialist at BizStream has been nagging me for months now to create something like this for him when we test our e-commerce sites.

And yes, in case your curious, I do have more of this type of code written to generate registered e-commerce customers, customer addresses, and e-commerce orders. I think it is going to help with proving all of the custom payment gateway and custom tax providers that we write for our e-commerce sites. I'm happy with it at least. I would have relied on the aforementioned data generator in Kentico 9. however it does not generate anything realistic because it hard codes the total price of an order. I wanted to actually use our custom code to do that.

As you can see it is pretty easy to generate large amounts of realistic test data in Kentico without too much effort. Let me know what you think in the comments.