The Database Populator Framework follows the same idea of DbMonster (or at least, was partially inspired from it). The purpose of the framework is to provide a flexible (and smart) set of random data generators to populate your database.
Why ?
If you plan to do database testing, the solution are not much: use transaction, create/kill database after each unit test, clean up after each test or use the new technique using Enterprise Services.
The objective of DPF is not to test the database but provide "food" for your unit test. By generating data randomly (satisfying the constraint), you do not need to clean up and you will avoid test clashing on each other. Moreover, you can also use the DPF to test your database under load.
Random but no dumb
In order to generate data for testing database, you need to take into accounts the constraints on the columns and between the tables. By providing a DataSet representing you database, the framework analyses it and create a set of generators. The data generated satisfies all the constraint. Of course, each row generator can be customized for your own needs, but in general, the information contained in the dataset is enough.
The ideas
The idea are rather simple:
The generation of a new row is made inside a ITablePopulator as follows:
The first bits
The first bits of the framework is located in the MbUnit.Framework.Data namespace. Althout the framework still needs work, the first example is running and is quite promising.
I have built a simple database containing User - Order - Product - OrderProduct:
this.dataSet=new DataSet(); DataTable users=dataSet.Tables.Add("Users"); DataColumn userID = users.Columns.Add("UserID",typeof(int)); DataColumn userName=Users.Columns.Add("UserName",typeof(string)); DataColumn userName.AllowDBNull=false; DataTable orders=dataSet.Tables.Add("Orders"); DataColumn orderID=orders.Columns.Add("OrderID",typeof(int)); DataColumn orderDate = orders.Columns.Add("OrderDate",typeof(DateTime)); DataColumn oUserID = orders.Columns.Add("UserID",typeof(int)); DataTable products=dataSet.Tables.Add("Products"); DataColumn productID=products.Columns.Add("ProductID",typeof(int)); DataColumn productName = products.Columns.Add("ProductName",typeof(string)); DataColumn productPrice = products.Columns.Add("ProductPrice",typeof(decimal)); DataTable orderProducts=dataSet.Tables.Add("OrderProducts"); DataColumn opOrderID=orderProducts.Columns.Add("OrderID",typeof(int)); DataColumn opProductID=orderProducts.Columns.Add("ProductID",typeof(int)); DataColumn quantity=orderProducts.Columns.Add("Quantity",typeof(int)); // pks users.Constraints.Add("PK_Users",userID,true); orders.Constraints.Add("PK_Orders",orderID,true); products.Constraints.Add("PK_Products",productID,true); orderProducts.Constraints.Add("PK_OrderProducts", new DataColumn[]{ opOrderID, opProductID} ,true); // fks orders.Constraints.Add("FK_Orders_Users",userID,oUserID); orderProducts.Constraints.Add("FK_OrderProducts_Orders",orderID,opOrderID); orderProducts.Constraints.Add("FK_OrderProducts_Products",productID,opProductID);
This database is easily populated using the DPF:
// creating populator IDatabasePopulator pop=new DatabasePopulator(); // anaylising internal structure this.pop.Populate(this.db.DataSet);
After that, you can customize the behavior of every data generator. Once this is done, you are ready to "feed" your database:
//getting the users table populator ITablePopulator userPop = pop.Tables[users]; // adding new row users.Rows.Add( userPop.Generate() );
Page rendered at Monday, October 13, 2008 11:37:58 AM UTC
Disclaimer The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.