Coder Social home page Coder Social logo

Comments (9)

oddbear avatar oddbear commented on May 14, 2024 6

Actual I think a better approach would be to have another method on the Faker class, similar to RuleFor, where we can extend the Faker with a ruleset.

This will not break the "pipeline", and could therefore be better with other features.
I think some great rules to extend the Faker with could be:

  • Add common names, like 'firstname' (done before the RuleFor rules).
  • Add something to everything (ex. garbage like string GUIDs on properties without rules)
  • Enforce DataAnnotations, (ex. only pick (or get a substring) of names less than MaxLenght, StringLenght etc.)
    Other features that could be nice, would be to insert some statistics to create failures(like some would be null, instead for firstname). And something like AutoFixture.

I don't see that this would be "mixable" with inheritance. But if the Faker had another method, that could take a set with rules, including predefined. This might be feasible.

Ex. :

//Need better namings, cleanup, etc.
void Main()
{
   var common = new CommonNames();
   var clients = new Faker<Test>()
      .RuleForKnown(common) //Something like this.
      .RuleFor(u => u.Something, f => f.Finance.Account());
      //could add something like:
      //.RulesForKnown(new DummyValues())
      //.RulesForKnown(new DataAnotations())

   clients.Generate().Dump();
}

public class Faker<T> : Bogus.Faker<T> //Implement body directly in Bogus.Faker<T>
   where T : class
{
   public Faker<T> RuleForKnown(CommonNames ruleSet)
   {
      if (ruleSet == null)
         return this;

      var properties = typeof(T).GetProperties();

      foreach (var rule in ruleSet.GetRules())
         foreach (var property in rule.Key.Invoke(properties))
            base.Actions.Add(base.currentRuleSet, property.Name, new Bogus.PopulateAction<T>
            {
               Action = (a, b) => rule.Value(FakerHub),
               RuleSet = base.currentRuleSet,
               PropertyName = property.Name
            });
      
      return this;
   }
}

public class CommonNames
{
   private readonly Dictionary<Func<PropertyInfo[], PropertyInfo[]>, Func<Bogus.Faker, object>> _rules;
   
   public CommonNames()
   {
      _rules = new Dictionary<Func<PropertyInfo[], PropertyInfo[]>, Func<Bogus.Faker, object>>();
      
      _rules[Filter("FirstName")] = f => f.Person.FirstName;
      _rules[Filter("LastName")] = f => f.Person.LastName;
      _rules[Filter("SurName")] = f => f.Person.LastName;
   }

   public Func<PropertyInfo[], PropertyInfo[]> Filter(string name)
      => propertyInfo => FilterPropertyName(propertyInfo, name ?? string.Empty);

   private PropertyInfo[] FilterPropertyName(PropertyInfo[] properties, string name)
      => properties
         .Where(p => name.Equals(p.Name, StringComparison.OrdinalIgnoreCase))
         .ToArray();

   public IEnumerable<KeyValuePair<Func<PropertyInfo[], PropertyInfo[]>, Func<Bogus.Faker, object>>> GetRules()
      => _rules.AsEnumerable();
}

public class Test
{
   public string FirstName { get; set; }
   public string LASTNAME { get; set; }
   public string surname { get; set; }
   public string Something { get; set; }
}

from bogus.

oddbear avatar oddbear commented on May 14, 2024 3

As the Faker has virtual methods for generate/validate/etc., this might be best to implement as something like inheritance from Faker (ex. AutoFaker), with overrides of those methods?

Edit:
It's a easy hack. A example of the direction I would have liked here:

void Main()
{
   var clients = new AutoFaker<Test>()
      .RuleFor(u => u.Something, f => f.Finance.Account());
	
   clients.Generate().Dump();
}

public class AutoFaker<T> : Faker<T>
   where T : class
{
   private string _autofakerset;

   public AutoFaker()
   {
      _autofakerset = Guid.NewGuid().ToString();
      var properties = typeof(T).GetProperties();
      var firstname = properties.SingleOrDefault(p => "FirstName".Equals(p.Name, StringComparison.OrdinalIgnoreCase));
      if (firstname != null)
      {
         var propName = firstname.Name;

         base.Actions.Add(_autofakerset, propName, new PopulateAction<T>
         {
            Action = (a, b) => base.FakerHub.Person.FirstName,
            RuleSet = currentRuleSet,
            PropertyName = propName
         });
      }
   }
	
   public override T Generate(string ruleSets = null)
   {
      var instance = base.Generate(_autofakerset);
      base.Populate(instance, ruleSets);
      return instance;
   }
}

public class Test
{
   public string FirstName { get; set; }
   public string Something { get; set; }
}

from bogus.

bchavez avatar bchavez commented on May 14, 2024 2

Hi Everyone,

A special member of our community, @nickdodd79, is working on the core implementation of Bogus' Auto Population feature. Soon you'll be able to create instances of interfaces and abstract classes where interface/abstract class fields/properties are populated with Bogus' data sets. Basically, you'll be able to create a whole reference graph of objects with Bogus.

If you'd like to comment on the public API that is currently being formulated for this feature, please let us know in #74. We'd like to hear from everyone so we can get an over-arching view of how you'd expect to use the auto-population features in your projects.

Many thanks,

💭 🔍 "I want to know... what you're thinking..."

from bogus.

salixzs avatar salixzs commented on May 14, 2024

I believe this is great idea. I would very much welcome it.
Also usual suspects, like "firstname", "lastname", "surname" :-)

from bogus.

gdimauro avatar gdimauro commented on May 14, 2024

I've just implemented a helper class for using attributes for generating rules directly from entities. Just going to use this extensively in a very big app. Here an example:

[Fixtures(Locale = "it", Strict = true)]
public partial class Persona : TenantBaseEntity
{
public const string FixturesRuleSetPersonaGiuridica = "PersonaGiuridica";
public const string FixturesRuleSetPersonaFisica = "PersonaFisica";

[Fixture(null, RuleSets = FixturesRuleSetPersonaGiuridica)]
[Fixture("@=Name.FirstName()")]
public virtual string Nome { get; set; }

[Fixture(null, RuleSets = FixturesRuleSetPersonaGiuridica)]
[Fixture("@=Name.LastName(Bogus.DataSets.Name.Gender.Male)")]
public virtual string Cognome { get; set; }

...

from bogus.

opoani avatar opoani commented on May 14, 2024

Hi. This sounds great are there any examples/documentations based on this helper ?

from bogus.

bchavez avatar bchavez commented on May 14, 2024

I like your ideas @oddbear the last example almost looks like a good starting point for a decent implementation.

Some other API names I like (in order):

Faker<T>
  .ApplyConvention(new AutoNameConvention())
  .UseConvention(new AutoNameConvention()) 
  .AddConvention(new AutoNameConvention())
  .Conventions(new AutoNameConvention())

  .RuleConvention(new AutoNameConvention())
  .UsingConvention(new AutoNameConvention()) 
  .ByConvention

Then maybe have AutoFaker<T> have all built-in conventions applied. People could then pick Faker<T> or AutoFaker<T>.

AutoFaker<T> would be the dual of Faker<T> where Faker<T> would be where users build-rules up from scratch. AutoFaker<T> would have conventions applied (and any missing properties rules after conventions could be filled in by default with randomness), and users would work from a full ruleset overriding only the ones they care about.

☁️ ☀️ Bassnectar - Chasing Heaven - Into the Sun

from bogus.

SimonCropp avatar SimonCropp commented on May 14, 2024

@bchavez looks like this one should be closed?

from bogus.

bchavez avatar bchavez commented on May 14, 2024

@SimonCropp sounds good to me.

For those looking for an automatic solution, please checkout AutoBogus:
https://github.com/nickdodd79/AutoBogus

from bogus.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.