QuickGenerate

Random Test Data Anyone?

7 commentsWritten on March 20th, 2011 by
Categories: QuickGenerate

I'm working on some NHibernate examples (which will be publicly available in a few weeks) and i needed some random test data. Luckily for me, i could just use Mark Meyers' QuickGenerate project to do the job for me.

Check out this code:

    public static class TestData
    {
        private static DomainGenerator WithAddress(DomainGenerator generator)
        {
            return generator
                .With<Address>(options => options.For(address => address.Street, new StringGenerator(1, 100)))
                .With<Address>(options => options.For(address => address.City, new StringGenerator(1, 100)))
                .With<Address>(options => options.For(address => address.Country, new StringGenerator(1, 100)));
        }

        private static DomainGenerator EmployeeGenerator(ISession session)
        {
            return WithAddress(new DomainGenerator())
                .With<Employee>(options => options.Ignore(employee => employee.Id))
                .OneToOne<Employee, Address>((employee, address) => employee.Address = address)
                .With<Employee>(options => options.For(employee => employee.FirstName, new StringGenerator(1, 50)))
                .With<Employee>(options => options.For(employee => employee.LastName, new StringGenerator(1, 75)))
                .With<Employee>(options => options.For(employee => employee.Title, new StringGenerator(1, 50)))
                .With<Employee>(options => options.For(employee => employee.Phone, new StringGenerator(1, 15)))
                .ForEach<Employee>(employee => session.Save(employee));
        }

        public static void Create(ISession session)
        {
            var customers = WithAddress(new DomainGenerator())
                .With<Customer>(options => options.Ignore(customer => customer.Id))
                .OneToOne<Customer, Address>((customer, address) => customer.Address = address)
                .With<Customer>(options => options.For(customer => customer.DiscountPercentage, new DoubleGenerator(0, 25)))
                .ForEach<Customer>(customer => session.Save(customer))
                .Many<Customer>(20, 40)
                .ToArray();

            var managers = EmployeeGenerator(session).Many<Employee>(2);

            var employees = EmployeeGenerator(session)
                .ForEach<Employee>(employee => Maybe.Do(() => managers.PickOne().AddSubordinate(employee)))
                .Many<Employee>(20)
                .ToArray();

            var suppliers = WithAddress(new DomainGenerator())
                .With<Supplier>(options => options.Ignore(supplier => supplier.Id))
                .OneToOne<Supplier, Address>((supplier, address) => supplier.Address = address)
                .With<Supplier>(options => options.For(supplier => supplier.Website, new StringGenerator(1, 100)))
                .Many<Supplier>(20)
                .ToArray();

            var products = new DomainGenerator()
                .With<ProductSource>(options => options.Ignore(productsource => productsource.Id))
                .ForEach<ProductSource>(productsource => session.Save(productsource))
                .With<Product>(options => options.Ignore(product => product.Id))
                .With<Product>(options => options.Ignore(product => product.Version))
                .With<Product>(options => options.For(
                    product => product.Category,
                    ProductCategory.Beverages,
                    ProductCategory.Condiments,
                    ProductCategory.DairyProducts,
                    ProductCategory.Produce))
                .With<Product>(g => g.Method<double>(1, 10, (product, d) => product.AddSource(suppliers.PickOne(), d)))
                .With<Product>(options => options.For(product => product.Name, new StringGenerator(1, 50)))
                .ForEach<Product>(product => session.Save(product))
                .Many<Product>(30)
                .ToArray();

            WithAddress(new DomainGenerator())
                .With<OrderItem>(options => options.Ignore(item => item.Id))
                .With<OrderItem>(options => options.For(item => item.Product, products))
                .With<Order>(options => options.Ignore(order => order.Id))
                .OneToMany<Order, OrderItem>(1, 20, (order, item) => order.AddItem(item))
                .With<Order>(options => options.For(order => order.Customer, customers))
                .With<Order>(options => options.For(order => order.Employee, employees))
                .OneToOne<Order, Address>((order, address) => order.DeliveryAddress = address)
                .ForEach<Order>(order => session.Save(order))
                .Many<Order>(200);

            session.Flush();
        }
    }

This populates my test-database with:

  • Between 20 and 40 customers, which have a DiscountPercentage value between 0 and 25
  • 2 Managers
  • 20 employees, some of them assigned to one of the managers, some of them without a manager
  • 20 suppliers
  • 30 products, each of which will have between 1 and 10 sources (= link with supplier and a cost)
  • 200 orders which are linked to the created customers and employees, and contain between 1 and 10 items using any of the 30 products that were also created

Pretty nifty and useful :) Of course, the vast majority of the data is entirely random at this point, but it's possible to use pre-defined values as well.

Thanks to Mark for fixing both my code as well as his on such short notice ;)