Minggu, 23 Januari 2011

The Weekly Source Code 58 - Generating (Database) Test Data with AutoPoco and Entity Framework Code First


I was messing around with Entity Framework Code First for data access recently (what I like to call EF Magic Unicorn) and had a need to create a bunch of test data. Such a chore. It's totally no fun and I always end up slapping the keyboard thinking that someone else should be slapping the keyboard. Test data for 10 instances of a class is easy, but 1000 is some how less inspiring.

Sure, there's lots of software I could buy to solve a problem like that, but meh. I dug around some and found an open source framework called AutoPoco from Rob Ashton (@robashton). First, awesome name. I like using open source projects with cool names. It's kind of like reading a book with a great cover. Makes you feel good jumping in. Then, I started working with it and realized there's some substance to this modest little library. All the better, right?

AutoPoco's CodePlex project says:

AutoPoco is a highly configurable framework for the purpose of fluently building readable test data from Plain Old CLR Objects

Here's the general idea. You need 100 of something (or 5, or whatever) setup a certain way, so you ask AutoPoco to construct a bunch of you, and it's so. It's that easy.

For example, please get me 1000 objects of type SimpleUser and make their FirstName's all "Bob.":

IList<SimpleUser> users = session.List<SimpleUser>(1000).Impose(x => x.FirstName, "Bob").Get();


Here's where it really shines, though:



session.List<SimpleUser>(100)
.First(50)
.Impose(x => x.FirstName, "Rob")
.Impose(x => x.LastName, "Ashton")
.Next(50)
.Impose(x => x.FirstName, "Luke")
.Impose(x => x.LastName, "Smith")
.All().Random(25)
.Impose(x => x.Role,roleOne)
.Next(25)
.Impose(x => x.Role,roleTwo)
.Next(50)
.Impose(x => x.Role, roleThree)
.All()
.Invoke(x => x.SetPassword("Password1"))
.Get();


This says:




Create 100 users

The first 50 of those users will be called Rob Ashton


The last 50 of those users will be called Luke Smith


25 Random users will have RoleOne


A different 25 random users will have RoleTwo


And the other 50 users will have RoleThree


And set the password on every single user to Password1




Effectively, the sky's the limit. You can also give AutoPoco more advanced requirements like 'make emails meet these requirements," or "call this method when it's time to get a password." The idea being not just to make test data, but to make somewhat meaningful test data.



This got me thinking that since we're using POCOs (Plain Ol' CLR Objects) that I could use this not only for Unit Tests but also Integration Tests and Smoke Tests. I could use this to generate test data in a database. All the better to use this with the new Entity Framework stuff that also uses POCOs.



For example:



public void MakeTestData()
{
IGenerationSessionFactory factory = AutoPocoContainer.Configure(x =>
{
x.Conventions(c => { c.UseDefaultConventions(); });
x.AddFromAssemblyContainingType<SimpleUser>();
});

IGenerationSession session = factory.CreateSession();

IList<SimpleUser> users = session.List<SimpleUser>(1000)
.First(500)
.Impose(x => x.FirstName, "Bob")
.Next(500)
.Impose(x => x.FirstName, "Alice")
.All()
.Impose(x => x.LastName, "Hanselman")
.Random(250)
.Impose(x => x.LastName, "Blue")
.All().Random(400)
.Impose(x => x.LastName, "Red")
.All()
.Get();

SimpleUserDatabase db = new SimpleUserDatabase();
foreach (SimpleUser s in users)
{
db.Users.Add(s);
}
db.SaveChanges();
}


And boom, I've got 1000 users in my little database.



I've talked to the author, Rob, and I think that the Session creation and Factory stuff could be made smaller, and the loop at the bottom could be reduced a line or two. Rob's a practical guy, and I look forward to where AutoPoco goes next! All in all, what a useful library. I can see myself using this a lot.



You can get AutoPoco from CodePlex, or even better, from inside Visual Studio using NuGet (http://nuget.org) via "install-package autopoco."



Enjoy! This library has 36 downloads, but deserves a few orders of magnitudes more. I'll do my best to showcase more open source libraries that deserve attention (and more importantly, to be used!) going forward. Feel free to email me suggestions of insanely useful libraries.



© 2010 Scott Hanselman. All rights reserved.

Tidak ada komentar: