Metody generowanie testowych danych w .NET

Częstym problemem – szczególnie podczas tworzenia aplikacji typu Proof of Concept jest szybkie generowanie danych testowych.
W mojej aplikacji – CyberHome – chciałem sprawdzić wydajność bibliotek do automatycznego mapowania jednej klasy na drugą, skąd jednak wziąć wystarczająca ilość danych testowych? Jest do tego kilka wartościowych narzędzi.

nBuilder

nBuilder – to bardzo wygodna i prosta w obsłudze biblioteka, niestety nie rozwijana od 2012 roku.
Instalacja:

Install-Package NBuilder

Przykład użycia:

var products = Builder<Person>.CreateListOfSize(10).Build();

Spowoduje utworzenie 10-elementowej listy obiektów klasy Person z wypełnionymi właściwościami.
Polecam lekturę wiki projektu i dokumentu na GitHubie – jest tam dostępne wiele przydatnych przykładów, np. generowanie danych z określonymi wartościami atrybutów:

var products = Builder<Product>
            .CreateListOfSize(10)
            .WhereAll()
                .Have(x => x.PriceBeforeTax = generator.Next(50, 1000))
            .Build();

Możemy też generować chierarchie obiektów:

var hierarchySpec = Builder<HierarchySpec<Category>>.CreateNew()
                .With(x => x.AddMethod = (parent, child) => parent.AddChild(child))
                .With(x => x.Depth = 5)
                .With(x => x.MaximumChildren = 10)
                .With(x => x.MinimumChildren = 5)
                .With(x => x.NamingMethod = (cat, title) => cat.Title = "Category " + title)
                .With(x => x.NumberOfRoots = 10).Build();
            Builder<Category>.CreateListOfSize(2500).BuildHierarchy(hierarchySpec);

Podsumowanie:
Podstawowa wadą nBuildera jest losowość generowanych encji oraz niezbyt rozbudowane możliwości konfiguracji.
Do większości zastosowań jednak wystarczy. NBuilder jest szybki, prosty w obsłudze i wygodny.

Faker.js i Bogus

Być może część z Was słyszała o projekcie faker.js  (GitHub) umożliwia on generowanie całkiem sensownych, konkretnych danych, a nie – jak nBuilder – przypadkowych.
API umożliwia generowanie wszystkich danych, których najczęściej potrzebujemy, dostępne są następujące kategorie:

  • address
  • commerce
  • company
  • date
  • finance
  • hacker
  • helpers
  • image
  • internet
  • lorem
  • name
  • phone
  • random
  • system

Jeśli kogoś intrygują niektóre nazwy – zapraszam na stronę projektu celem wypróbowania do czego służą. 🙂
Brian Chavez stworzył .NETowy port do Faker.js o polsko brzmiącej nazwie Bogus (od ang. podrobiony), używa się tego bardzo przyjemnie i szybko:

install-Package Bogus

Na gitHubie jest przejrzysta dokumentacja oraz liczne przykłady.
Poniżej krótka prezentacja kilku możliwości:

var testUsers = new Faker<User>()
    //Optional: Call for objects that have complex initialization
    .CustomInstantiator(f => new User(userIds++, f.Random.Replace("###-##-####")))
    //Basic rules using built-in generators
    .RuleFor(u => u.FirstName, f => f.Name.FirstName())
    .RuleFor(u => u.LastName, f => f.Name.LastName())
    .RuleFor(u => u.Avatar, f => f.Internet.Avatar())
    .RuleFor(u => u.UserName, (f, u) => f.Internet.UserName(u.FirstName, u.LastName))
    .RuleFor(u => u.Email, (f, u) => f.Internet.Email(u.FirstName, u.LastName))
    .RuleFor(u => u.SomethingUnique, f => $"Value {f.UniqueIndex}")
    //Use an enum outside scope.
    .RuleFor(u => u.Gender, f => f.PickRandom<Gender>())
    //Use a method outside scope.
    .RuleFor(u => u.CartId, f => Guid.NewGuid())
    //Compound property with context, use the first/last name properties
    .RuleFor(u => u.FullName, (f, u) => u.FirstName + " " + u.LastName)
    //And composability of a complex collection.
    .RuleFor(u => u.Orders, f => testOrders.Generate(3).ToList())
    //After all rules are applied finish with the following action
    .FinishWith((f, u) =>
        {
            Console.WriteLine("User Created! Id={0}", u.Id);
        });
var user = testUsers.Generate();
Console.WriteLine(user.DumpAsJson());

Bogus umożliwia generowanie danych w rożnych językach, w tym po polsku!
Mamy również gotową klasę Person modelującą większość powszechnych atrybutów osoby – bardzo przydatne w testach!
Podsumowanie:
Bogus jest szybki, ciągle rozwijany i ma duże możliwości konfiguracji; dodając do tego przejrzystą dokumentację i dobry kontakt z autorem – wyłania się nam bardzo dobry framework do generowanie testowych danych dla naszych aplikacji.
Na koniec krótki przykład z mojego programu:

   var persons = new Faker<PersonEntity>()
                .RuleFor(x => x.Name, f => f.Name.FirstName())
                .RuleFor(x => x.Age, f => f.Random.Number(18, 65))
                .RuleFor(x => x.Salary, f => f.Finance.Amount(1000, 5000))
                .RuleFor(x => x.Office, f => new Office { Description = f.Lorem.Text(), OpeningHours = f.Date.Past() })
                .Generate(200000).ToList();

Generowanie 200 000 instancji klasy trwa mniej niż 7 sec!


Artykuł w ukazuje się w ramach projektu CyberHome tworzonego w ramach akcji DajSięPoznać.


 

3 odpowiedzi na “Metody generowanie testowych danych w .NET”

  1. Pingback: Repozytorium | langusblog

Leave a Reply