GithubHelp home page GithubHelp logo

tynamix / objectfiller.net Goto Github PK

View Code? Open in Web Editor NEW
76.0 76.0 34.0 3.46 MB

The .NET ObjectFiller fills the properties of your .NET objects with random data

Home Page: http://objectfiller.net

License: MIT License

C# 100.00%
c-sharp data-generator test-automation unittest

objectfiller.net's People

Contributors

blmeyers avatar charlass avatar gitter-badger avatar herrloesch avatar jiaxuyang avatar lichtel avatar twenzel avatar tynamix avatar weitzhandler avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

objectfiller.net's Issues

Randomizer should be able to create collection even plugins or setups are used.

Randomizer.Create has currently three overloads. One so we can use plugins, one to define a Setup and one to create a collection of elements.

This is a bit unhandy because it means that we are not able to create collections with specific setups or plugins. That's why we need two additional overloads. one for collections and plugins, as well as one for collections and setups.

I guess it's not usefull to have an overload with setup and plugin.

Please write Type overload for methods too

Hi

Thanks for your awesome library.

I want to use you library but I need some overload. You method is pure generic but I think it is better to have Type based and PropertyInfo based overload. for example

.OnType(typeof(Person)).Use()
OnProperty(PropertyInfo of FirstName).Use()
and ...

because some one like me use your library for set objects in Runtime and need Type instead of Generice model

please create Type overloads for all generic methods too.

Provide a way to create Setups without the need of a filler.

Current we need to do something like this to create a setup:

        var categoryFiller = new Filler<Category>();
        var categorySetup = categoryFiller.Setup().OnType<int>().Use(new IntRange(1, 100)).Result;

It would be nice to skip the Filler and create a setup like this:

        var categorySetup = Setup<Category>.OnType<int>().Use(new IntRange(1, 100)).Result;

Add setup to ignore all complex types.

When I am testing with entity classes generated by Entity Framework, it would be nice to ignore all complex types because these complex types are often references to other data tables and the actual data is mostly stored as numbers or strings.

We could check if a type is a reference type and not string and ignore it than.

Do we want to remove optional parameters?

I saw that we are using optional parameters in our public API. For example in Lipsum:

public Lipsum(LipsumFlavor flavor, int paragraphs = 3, int minSentences = 3, int maxSentences = 8, 160 int minWords = 10, int maxWords = 50, int? seed = null)

Optional parameters are compiled into the Client library. This might cause Problems if we change them, which why they shouldn't be used in public APIs. On the other hand it's annoying to replace them with overloads.

My question is now: Do we want to replace all optional parameters with overloads to stay save or do we want to keep them as they are, even with possible side effects?

Automatically fill a type that inherits from List<T>

I'm using your handy ObjectFiller for unit testing legacy code. This legacy code includes a lot of classes that inherit from List. Some of these list types include additional properties to fill. Please consider adding more support for such types.

public class EntityA
{
    public string Name { get; set; }
    public int ID { get; set; }
    public EntityBList Bs { get; set; }
}
public class EntityB
{
    public string Name { get; set; }
    public Guid ID { get; set; }
}
public class EntityBList : List<EntityB>
{
    public DateTime SomeDate { get; set; }
}

My ultimate goal is to call new Filler<EntityA>().Create() and get back an EntityA object whose Bs property has both SomeDate filled and also has some EntityB items whose properties are filled. As is, I end up manually coding the EntityBList handling using something like this:
Setup().OnProperty(x => x.Bs).Use(delegate () { EntityBList ebl = new EntityBList(); ebl.SomeDate = DateTime.Now; Filler<EntityB> fb = new Filler<EntityB>(); ebl.AddRange(fb.Create(4)); return ebl; }); Since we have a great many of these types, that ends up being a lot of code.

I think this would require several enhancements.

First, Filler doesn't seem to recognize EntityBList as an IList to be filled. Filler sees that this inherits IList. Filler then checks whether the type has generic arguments, but this one does not. It's base class has the generic arguments.

Second, given that it doesn't treat this type as a list, Filler attempts to set the Capacity and Item properties. Those throw exceptions. I can set it up to ignore the Capacity property by using Setup().SetupFor<EntityBList>().OnProperty(x => x.Capacity).IgnoreIt() but have not figured out a way to ignore the special Item property which represents the this[int] indexer.

Third, I suspect that Filler either treats the type as a list to be filled or treats it as an object whose properties should be filled, and not both. I'd want it to fill the list and also fill the properties.

We do also have a couple types that inherit from Dictionary<>. It'd be nice to cover those in the same way.

ObjectFiller fails to fill IReadOnlyCollection

Given the following class:

public class Order
{
    public IReadOnlyCollection<string> OrderLines { get; set; }
}

Filling it by running the following code fails.

var filler = new Filler<Order>();
var order = filler.Create();

The following exception is thrown:

System.InvalidOperationException: This operation is only valid on generic types.
   at System.RuntimeType.GetGenericTypeDefinition()
   at Tynamix.ObjectFiller.Filler`1.<>c.<TypeIsCollection>b__13_0(Type x)
   at System.Linq.Enumerable.Any[TSource](IEnumerable`1 source, Func`2 predicate)
   at Tynamix.ObjectFiller.Filler`1.TypeIsCollection(Type type)
   at Tynamix.ObjectFiller.Filler`1.CreateAndFillObject(Type type, FillerSetupItem currentSetupItem, HashStack`1 typeTracker)
   at Tynamix.ObjectFiller.Filler`1.FillInternal(Object objectToFill, HashStack`1 typeTracker)
   at Tynamix.ObjectFiller.Filler`1.Create()

Using an ICollection<string> instead works.

Nullable Enumerations can't be generated

An InvalidOperationException is thrown if a class has a nullable enumeration:

public class MyClass { public MyEnum? TheEnum {get; set; } }

public enum MyEnum { A, B, C }

Randomizer.Create(); <-- Exception

Same happens with the filler class.

Merging setup information based on inheritance and implementation

Would it be possible for to create a filler and merge the setup with another filler allowing the class to configure a filler aginst one interface and merge it where that interface inherits the other. This same method could also be used where a class inherits another.

For example:
public interface ITrackable { DateTime Timestamp {get;set;} }
public interface IPerson: ITrackable { string Name {get;set;} }
var person = FillerSetup.Create<IPerson()...
var trackable FillerSetup.Create<ITrackable>()...
person.Merge(trackable)

Get current setup from FluentAPI

It would be good if there is a possibility to get the current setup which was made with the fluentAPI from the objectfiller to reuse it.

Exception when creating a collection of simple objects

I wanted to create a list of objects. They must be of type object. I was not able to create them with Randomizer.Create(110) because there was no type Object registered.

Exception:

System.TypeInitializationException : Der Typeninitialisierer für "System.Object" hat eine Ausnahme verursacht.
----> System.Exception : The type [Object] was not registered in the randomizer.
bei Tynamix.ObjectFiller.Filler1.GetRandomValue(Type propertyType, FillerSetupItem setupItem) bei Tynamix.ObjectFiller.Filler1.CreateAndFillObject(Type type, FillerSetupItem currentSetupItem, HashStack1 typeTracker) bei Tynamix.ObjectFiller.Filler1.Create()
bei Tynamix.ObjectFiller.Filler`1.Create(Int32 count)

Then I tried this setup:

            Filler<object> objectFiller = new Filler<object>();
            objectFiller.Setup().OnType<object>().CreateInstanceOf<string>();

with this call:

objectFiller.Create(110)

and got the same Exception.

Create untyped Randomizer Plugins

For complex scenarios it is good to have plugins which decide by their own if they can be used for a specific type or not.

This is not possible with IRandomizerPlugin because of its concrete typing. That's why it would be nice to have a IRandomizePlugin without typing but with an additional method to check if it can be used.

For example I have following class:

public class Address
{
      public string Street { get; set; }
      ...
}

Currently it Is not possible to call:

Randomizer<Address>.Create(new Mnemonic());

because Mnemonic is of type IRandomizerPlugin and not IRandomizerPlugin

.

The dynamic version of the plugin must then be referenced for each type and property within our resolution routine.

The signature of the plugin could look like:

public interface IRandomizerPlugin
{
        bool CanBeUsedOn(Type type);

       object GetData();
}

The basic advantage is, that one plugin can be used for multiple types.

Randomizer for type URI is missing

There is no default randomizer for type URI. Here is one prepared and can be included to objectfiller.

	public class RandomUri : IRandomizerPlugin<Uri>
	{
		/// <summary>
		/// Gets random data for type <see cref="Uri" />
		/// </summary>
		/// <returns>Random data for type <see cref="Uri" /></returns>
		public Uri GetValue()
		{
			var http = Randomizer<bool>.Create() ? "http" : "https";
			var www = Randomizer<bool>.Create() ? "www." : string.Empty;
			var host = Randomizer<string>.Create(new MnemonicString(1)).ToLower();
			var domain = Randomizer<string>.Create(new RandomListItem<string>("de", "com", "org", "uk", "gov", "fr", "ru"));
			string relativePath = string.Empty;
			if (Randomizer<bool>.Create())
			{
				var relativeElements =Randomizer<int>.Create(new IntRange(1, 4));
				for (int i = 0; i < relativeElements; i++)
				{
					relativePath += $"/{Randomizer<string>.Create(new MnemonicString(1)).ToLower()}";
				}
			}

			UriBuilder u = new UriBuilder(http, $"{www}{host}.{domain}{relativePath}");
			return u.Uri;
		}
	}

Shorter strings by default

When I generate a string then I get usually something like this by default: "Tabedojimij Vedezosodul magoserotom gowatafumim Dibopaselim sorokesosoj Kirugisebob vorowavucob Jatalefihup gunirapejol Jibucelonez Jabebuwujuw Kajafijacuk wahikokakef Bicakujakiw Lenutekovaf sojabecojas banegikumet ziwagemihuj Vazatotudon"

That's not wrong but I usualy only need a short phrase like "Tabedojimij". I would suggest that we change the default behaviour of the filler so it creates only one word when no setup for strings is given.

Add Setup to ignore all properties, except configured.

Thanks to Entity Framewok, I am currently in a situation where I need to ignore more properties than I actually need for a test. It would be nice to have a method where I can say, that the Filler should ignore every thing which is not configured explicitly.

Unable to cast object of type 'HashSet' to type 'IList'

Hi,

I have an object with a property of type 'HashSet'.

When I try to fill it, the following exception occurs:

Unable to cast object of type 'System.Collections.Generic.HashSet`1[System.String]' to type 'System.Collections.IList'.

In the source code a check is made against 'IEnumerable', and if true, a cast to 'IList' is made, which causes an exception.

Creating new plugin / Getting types registered in the randomizer.

Hello. I ran into an issue when trying to fill in a System.Drawing.Color value using object filler.
Here's the error message that happens when running the test:

System.Exception : The type [Color] was not registered in the randomizer.

Here's the stacktrace:

Result StackTrace:  
at Tynamix.ObjectFiller.Filler`1.GetRandomValue(Type propertyType, FillerSetupItem setupItem)
at Tynamix.ObjectFiller.Filler`1.CreateAndFillObject(Type type, FillerSetupItem currentSetupItem, HashStack`1 typeTracker)
at Tynamix.ObjectFiller.Filler`1.FillInternal(Object objectToFill, HashStack`1 typeTracker)
at Tynamix.ObjectFiller.Filler`1.Create()

To attempt to solve this issue, I followed the documentation listed on how to make a plugin, and my code is as follows:

        public class argbColorPlugin : IRandomizerPlugin<Color>
        {
            private readonly Random r = new Random();
            private readonly List<Color> allColors =
            new List<Color>()
            {
                System.Drawing.Color.Beige,
                System.Drawing.Color.FromArgb(new IntRange(0, 255).GetValue(), new IntRange(0, 255).GetValue(), new IntRange(0, 255).GetValue(), new IntRange(0, 255).GetValue())
            };

            public Color GetValue()
            {
                return allColors[r.Next(0, allColors.Count)];
            }
        }

Even after calling the plugin instead of passing in a Color, it still has the same error.

Here's how I'm calling it:

.OnProperty(x => x.FontColor).Use(new argbColorPlugin().GetValue())

It's in the middle of a bunch of other properties, mostly floats, but a couple other object types are present. All of the rest of them seem to work pretty well.

Is there something that I'm supposed to do in order to register the type in the randomizer?
Thanks!

Please add unlimited mergeable setup

    public class User
    {
        public int Id { get; set; }
        public Person Person { get; set; }
        public List<string> Phones { get; set; }

    }

    public class Person
    {
        public Guid Id { get; set; }
        public int No { get; set; }
        public string NationalCode { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public DateTime BirthDate { get; set; }
   }
            Filler<Person> pFiller = new Filler<Person>();
            var fillerSetup = pFiller.Setup()
                .OnType<string>().Use("PERSON");

            Filler<User> uFiller = new Filler<User>();
            pFiller.Setup(fillerSetup.Result)
                .OnType<string>().Use("USER");

            User p = uFiller.Create();

above example does not work I can not merge Persons filler with Users filler. (I dont want to use SetupFor<>)
Can you provide this feature ? of course unlimited Setup() for multiple merge

Error when setting up strings with numerals

I have following code which will fail on Create:

        var filler = new Filler<Address>();
        filler.Setup().OnProperty(x => x.Id).Use("1");

        this.address = filler.Create();

Id is a string in which numerals are stored like 1, 2 or 3. It seems that the filler tries to convert the number into an integer and is then unable to assign this number to the actual string.

Configuration by template object

I have following classes without any inheritance:

public class Position
{
    public int Company;
    public int LeaseNumber;
    public decimal Costs; 
}
public class SubPostion
{
   public int LeaseNumber;
   public int InventoryNumber;
   public string Status;
}

These will be joined in the database based on the LeaseNumber. Therefor I would like to create SubPositions based on the data of positions by using the Position object as some kind of template object so that properties that have the same name in both classes will get the same data.

var position = Randomizer<Position>.Create();
var setup = FillerSetup.Create<SubPosition>().UseTemplate(position).Result;
var subPositions = Randomizer<SubPosition>.Create(setup, 10);

In the case above, all subPositions have random data for InventoryNumber and Status but the same LeaseNumber as the Position object.

It is important, that the template object does not need to be of the same type as the objects are I want to create. Thus we need to check for each property if the template has a property with the same name.

Filler cannot instantiate classes with bool? types

if I have class like this:

class TestClass
{
    public int? MyNullableInt { get; set; }
    public bool MyBool { get; set; }
}

everything seems fine, and filler creates new instance

new Filler<TestClass>().Create(); //everything OK! :)

but if I change bool to bool?

class TestClass
{
    public int? MyNullableInt { get; set; }
    public bool? MyNullableBool { get; set; }
}

Filler crashes

new Filler<TestClass>().Create(); //System.Exception was thrown (with message, The type [Nullable`1] was not registered in the randomizer.) 

Of course, I can work around this, by writing

var filler = new Filler<TestClass>();
filler.Setup().OnType<bool?>().Use(new bool[] { true, false });
var testClass = filler.Create();

but I believe that to do so should not be necessary

Lipsum Randomizer is not random enough

Using the following code, allmost all instances of Foo have the same description text (sometime there are two versions of text in those 1000 instances):

var foos = new Filler<Foo>();
filler.Setup()
    .OnProperty(foo => foo.Description)
    .Use(new Lipsum(LipsumFlavor.LoremIpsum))
    .Create(1000);

Be default I would have expected that they all have a different text.

The reason why this happens is probably because the Lipsum randomizer creates a new Random instance at the beginning of each GetValue() call (with the same seed, because in most cases Environment.TickCount has the same value for all 1000 calls).

Instead it should create the Random instance in the Lipsum constructor store it in a field and use that same istance for each random.Next() call inside GetValue()

I can work around this issue by doing:

var seed = 0;
var filler = new Filler<Todo>();
filler.Setup()
    .OnProperty(t => t.Description)
    .Use(() =>new Lipsum(LipsumFlavor.ChildHarold, seed++).GetValue()))
    .Create(1000);

Plugins should be assignable to collection types

It would be nice if I could assign plugins to collections of corresponding values. I have following setup:

var filterFiller = new Filler<FilterVM>();
filterFiller.Setup()
     .OnProperty(x => x.Countries).Use(new CountryName());

CountryName can not be assigned to Countries because Countries is a collection of strings and the plugin implements IRandomizerPlugin. It would need to implement IRandomizerPlugin<IEnumerbale> to work.

I guess it would be best if the filler could automatically use a IRandomizerPlugin on collections no matter if it is written for collections or not otherwise we have to implement two Interfaces with each plugin.

Allow to specify a seed to get allways the same data.

When using objectfiller with tests, it might be necessary to use allways the same data. A full fledged filler setup is to much in this case, because we would like to generate data to keep the amount of code low, but this data should be generated allways the same way to make sure that the tests run the same ways each and every time.

Error Message:A strongly-named assembly is required

I wanted to use your library in my Unittests but it doesn't start.
ObjectFiller was added with nuget to my Project, which is a project with a strong name.
System.IO.FileLoadException : Could not load file or assembly 'Tynamix.ObjectFiller, Version=1.5.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. A strongly-named assembly is required. (Exception from HRESULT: 0x80131044)
Would it be possible to publish ObjectFiller with a strong name on nuget?

Add option to ignore inherited properties

Today I built a search form where I added additional Information for the the UI by inheriting the view model from the actual model:

public class Filter
{
    public string Name { get; set; }
}
public class FilterViewModel : Filter
{
   public string[] AvailableNames {get; set; }
}

In this case it would be nice to have an option so the filler generates only data for the ViewModel.

It could be handled the same way as "IgnoreUnknownTypes".

var filterFiller = new Filler<FilterViewModel >();
filterFiller.Setup().IgnoreInheritance();

Every plugin should have a parameterless constructor with default values

It would be good to just use a plugin without additional settings.
For example if you want to use the MnemonicString plugin you have to setup at least the word count.
We should change this, that every plugin would also work with a parameterless constructor.
Another advantage is, that we can use the IRandomizer plugins as constructable type parameters.

IgnoreInheritance does not work for reference types

I have following classes:

public class A 
{
    public  string Test { get; set; }
}

public class B
{
    public A MyA {get; set; }
}

public class C : B
{
    public string AnotherProperty {get;set;}
}

I have configured the filler as followed:

var filler = new Filler<C>();
filler.Setup().IgnoreInheritance();
var c = filler.Create();

I woul expect that Cs property "MyA" is null but its actually an empty A.

StackOverflowException with simple filler

Hi,
getting a stack overflow with a reasonably simple setup (for a class with an ICollection defined on it and some properties I don't set up at all, one being of another type); sorry I don't have more time right now but I will investigate and maybe throw a pull request your way if I figure something out.

Just from a cursory look at the code though, would I be right in saying that the SetupManager being static and the Filler calling Clear in the constructor will effectively prevent me from creating several fillers and playing around with them?

Either way, I like the style of the library so maybe I'll contribute with some actual code one of these days :)

Enhancement: Add overload Use method for types and properties to use setups again.

I would like to use setups again for child types like shown in following test. I've allready tried to implement it but was not able to in short of type because the Use method of the parent does not seem to have information about the child type.

        public class Parent
        {
            public Child Child { get; set; }
        }

        public class Child
        {
            public int Value { get; set; }
        }

        [TestMethod]
        public void UseSetupsAgainForPropertyConfigurations()
        {
            int givenValue = Randomizer<int>.Create();

            var childFiller = new Filler<Child>();
            var childSetup = childFiller.Setup().OnProperty(x => x.Value).Use(givenValue).Result;

            var parentFiller = new Filler<Parent>();
            parentFiller.Setup().OnProperty(x => x.Child).Use(childSetup);

            var parent = parentFiller.Create();
            Assert.AreEqual(givenValue, parent.Child.Value);
        }

Bug with Thread Safe Random Support

There's currently a bug with the implementation of thread safe random access that was committed. It uses a static constructor to initialize a ThreadStatic marked field, which will cause subsequent threads to throw a null reference exception. Initialization at the field level or static constructor level for a ThreadStatic field will only ever run once on the first thread to reach the type, any subsequent threads will access an uninitialized variable.

This is an important feature to my company's usage of the library and we were hoping to avoid maintaining a fork just for this change, so I'm submitting a pull request to add a new unit test and correct the bug. More details in the PR (#61)

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.