QuickFuzzr 0.1.1

dotnet add package QuickFuzzr --version 0.1.1
                    
NuGet\Install-Package QuickFuzzr -Version 0.1.1
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="QuickFuzzr" Version="0.1.1" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="QuickFuzzr" Version="0.1.1" />
                    
Directory.Packages.props
<PackageReference Include="QuickFuzzr" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add QuickFuzzr --version 0.1.1
                    
#r "nuget: QuickFuzzr, 0.1.1"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package QuickFuzzr@0.1.1
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=QuickFuzzr&version=0.1.1
                    
Install as a Cake Addin
#tool nuget:?package=QuickFuzzr&version=0.1.1
                    
Install as a Cake Tool

Generating Objects

A simple object.

Use Fuzz.One<T>(), where T is the type of object you want to generate.

  • The primitive properties of the object will be automatically filled in using the default (or replaced) generators.

  • The enumeration properties of the object will be automatically filled in using the default (or replaced) Fuzz.Enum<T> generator.

  • The object properties will also be automatically filled in using the default (or replaced) generators, similar to calling Fuzz.One<TProperty>() and setting the value using Apply (see below) explicitly.

  • Also works for properties with private setters.

  • Can generate any object that has a parameterless constructor, be it public, protected, or private.

  • The overload Fuzz.One<T>(Func<T> constructor) allows for specific constructor selection.

Ignoring properties.

Use the Fuzz.For<T>().Ignore<TProperty>(Expression<Func<T, TProperty>> func) method chain.

F.i. :

Fuzz.For<SomeThingToGenerate>().Ignore(s => s.Id)

The property specified will be ignored during generation.

Derived classes generated also ignore the base property.

Sometimes it is useful to ignore all properties while generating an object.
For this use Fuzz.For<SomeThingToGenerate>().IgnoreAll()

IgnoreAll() does not ignore properties on derived classes, even inherited properties.

**Note πŸ˜—* The Ignore(...) combinator does not actually generate anything, it only influences further generation.

Customizing properties.

Use the Fuzz.For<T>().Customize<TProperty>(Expression<Func<T, TProperty>> func, Generator<TProperty>) method chain.

F.i. :

Fuzz.For<SomeThingToGenerate>().Customize(s => s.MyProperty, Fuzz.Constant(42))

The property specified will be generated using the passed in generator.

An overload exists which allows for passing a value instead of a generator.

Derived classes generated also use the custom property.

*Note πŸ˜— The Customize combinator does not actually generate anything, it only influences further generation.

Customizing constructors.

Use the Fuzz.For<T>().Construct<TArg>(Expression<Func<T, TProperty>> func, Generator<TProperty>) method chain.

F.i. :

Fuzz.For<SomeThing>().Construct(Fuzz.Constant(42))

Subsequent calls to Fuzz.One<T>() will then use the registered constructor.

Various overloads exist :

  • Fuzz.For<T>().Construct<T1, T2>(Generator<T1> g1, Generator<T2> g2)

  • Fuzz.For<T>().Construct<T1, T2>(Generator<T1> g1, Generator<T2> g2, Generator<T3> g3)

  • Fuzz.For<T>().Construct<T1, T2>(Generator<T1> g1, Generator<T2> g2, Generator<T3> g3, Generator<T4> g4)

  • Fuzz.For<T>().Construct<T1, T2>(Generator<T1> g1, Generator<T2> g2, Generator<T3> g3, Generator<T4> g4, Generator<T5> g5)

After that, ... you're on your own.

Or use the factory method overload:
Fuzz.For<T>().Construct<T>(Func<T> ctor)

*Note πŸ˜— The Construct combinator does not actually generate anything, it only influences further generation.

Many objects.

Use The .Many(int number) generator extension.

The generator will generate an IEnumerable<T> of int number elements where T is the result type of the extended generator.

An overload exists (.Many(int min, int max) where the number of elements is in between the specified arguments.

ToArray.

Use The .ToArray() generator extension.

The Many generator above returns an IEnumerable. This means it's value would be regenerated if we were to iterate over it more than once. Use ToArray to fix the IEnumerable in place, so that it will return the same result with each iteration. It can also be used to force evaluation in case the IEnumerable is not enumerated over because there's nothing in your select clause referencing it.

Inheritance.

Use The Fuzz.For<T>().GenerateAsOneOf(params Type[] types) method chain.

F.i. :

Fuzz.For<SomeThingAbstract>().GenerateAsOneOf(
	typeof(SomethingDerived), typeof(SomethingElseDerived))

When generating an object of type T, an object of a random chosen type from the provided list will be generated instead.

**Note πŸ˜—* The GenerateAsOneOf(...) combinator does not actually generate anything, it only influences further generation.

ToList.

Use The .ToList() generator extension.

Similar to the ToArray method. But instead of an Array, this one returns a, you guessed it, List.

Replacing Primitive Generators

Use the .Replace() extension method.

Example

var generator =
	from _ in Fuzz.Constant(42).Replace()
	from result in Fuzz.One<SomeThingToGenerate>()
	select result;

When executing above generator it will return a SomeThingToGenerate object where all integers have the value 42.

Replacing a primitive generator automatically impacts its nullable counterpart.

Replacing a nullable primitive generator does not impacts it's non-nullable counterpart.

Replacements can occur multiple times during one generation :

var generator =
	from _ in Fuzz.Constant(42).Replace()
	from result1 in Fuzz.One<SomeThingToGenerate>()
	from __ in Fuzz.Constant(666).Replace()
	from result2 in Fuzz.One<SomeThingToGenerate>()
	select new[] { result1, result2 };

When executing above generator result1 will have all integers set to 42 and result2 to 666.

*Note πŸ˜— The Replace combinator does not actually generate anything, it only influences further generation.


Generating Hierarchies

Relations.

In the same way one can Customize primitives, this can also be done for references.

E.g. :

var generator =
	from product in Fuzz.One<ProductItem>()
	from setProduct in Fuzz.For<OrderLine>().Customize(orderline => orderline.Product, product)
	from orderline in Fuzz.One<OrderLine>()
	select orderline;

In case of a one-to-many relation where the collection is inaccessible, but a method is provided for adding the many to the one, we can use the Apply method, which is explained in detail in the chapter 'Other Useful Generators'. E.g. :

var generator =
	from order in Fuzz.One<Order>()
	from addLine in Fuzz.For<OrderLine>().Apply(order.AddOrderLine)
	from lines in Fuzz.One<OrderLine>().Many(20).ToArray()
	select order;

Note the ToArray call on the orderlines. This forces enumeration and is necessary because the lines are not enumerated over just by selecting the order.

If we were to select the lines instead of the order, ToArray would not be necessary.

Relations defined by constructor injection can be generated using the One<T>(Func<T> constructor) overload. E.g. :

var generator =
	from category in Fuzz.One<Category>()
	from subCategory in Fuzz.One(() => new SubCategory(category)).Many(20)
	select category;

Depth Control.

As mentioned in the A simple object section: β€œThe object properties will also be automatically filled in.” However, this automatic population only applies to the first level of object properties. Deeper properties will remain null unless configured otherwise.
So if we have the following class :

public class NoRecurse { }
public class Recurse
{
	public Recurse Child { get; set; }
	public NoRecurse OtherChild { get; set; }
	public override string ToString()
	{
		var childString =
			Child == null ? "<null>" : Child.ToString();
		var otherChildString =
			OtherChild == null ? "<null>" : "{ NoRecurse }";
		return $"{{ Recurse: Child = {childString}, OtherChild = {otherChildString} }}";
	}
}

If we then do :

Console.WriteLine(Fuzz.One<Recurse>().Generate().ToString());

It outputs :

{ Recurse: Child = <null>, OtherChild = { NoRecurse } }

While this may seem counter-intuitive, it is an intentional default to prevent infinite recursion or overly deep object trees. Internally, a DepthConstraint(int Min, int Max) is registered per type. The default values are new(1, 1).
Revisiting our example we can see that both types have indeed been generated with these default values.

You can control generation depth per type using the .Depth(min, max) combinator.
For instance:

var generator =
	from _ in Fuzz.For<Recurse>().Depth(2, 2)
	from recurse in Fuzz.One<Recurse>()
	select recurse;
Console.WriteLine(generator.Generate().ToString());

Outputs:

{ Recurse: Child = { Recurse: Child = <null>, OtherChild = { NoRecurse } }
, OtherChild = { NoRecurse } 
}

Recap:

Depth(1, 1)
{ Recurse: Child = <null>, OtherChild = { NoRecurse } }

Depth(2, 2)
{ Recurse: 
	Child = { Recurse: Child = <null>, OtherChild = { NoRecurse } },
  	OtherChild = { NoRecurse } 
}

Depth(3, 3)
{ Recurse: 
	Child = { Recurse: 
		Child = { Recurse: Child = <null>, OtherChild = { NoRecurse } },
        OtherChild = { NoRecurse } },
  	OtherChild = { NoRecurse } 
}

Using for instance .Depth(1, 3) allows the generator to randomly choose a depth between 1 and 3 (inclusive) for that type. This means some instances will be shallow, while others may be more deeply nested, introducing variability within the defined bounds.

**Note πŸ˜—* The Depth(...) combinator does not actually generate anything, it only influences further generation.

Trees.

Depth control together with the .GenerateAsOneOf(...) combinator mentioned above and the previously unmentioned TreeLeaf<T>() one allows you to build tree type hierarchies.
Given the canonical abstract Tree, concrete Branch and Leaf example model, we can generate this like so:

var generator =
	from _d in Fuzz.For<Tree>().Depth(1, 3)
	from _i in Fuzz.For<Tree>().GenerateAsOneOf(typeof(Branch), typeof(Leaf))
	from _l in Fuzz.For<Tree>().TreeLeaf<Leaf>()
	from tree in Fuzz.One<Tree>()
	select tree;

Our leaf has an int value property, so the following:

Console.WriteLine(generator.Generate().ToString());

Would output something like:

Node(Leaf(31), Node(Leaf(71), Leaf(10)))

**Note πŸ˜—* The TreeLeaf<T>() combinator does not actually generate anything, it only influences further generation.


Other Useful Generators

Apply.

Use the .Apply<T>(Func<T, T> func) extension method.

Applies the specified Function to the generated value, returning the result. F.i. Fuzz.Constant(41).Apply(i => i + 1) will return 42.

Par example, when you want all decimals to be rounded to a certain precision :

var generator = 
	from _ in Fuzz.Decimal().Apply(d => Math.Round(d, 2)).Replace()
	from result in Fuzz.One<SomeThingToGenerate>()
	select result;

An overload exists with signature Apply<T>(Action<T> action). This is useful when dealing with objects and you just don't want to return said object. E.g. Fuzz.One<SomeThingToGenerate>().Apply(session.Save).

This function also exists as a convention instead of a generator.

E.g. Fuzz.For<SomeThingToGenerate>().Apply(session.Save).

In this case nothing is generated but instead the function will be applied to all objects of type T during generation.

There is no Fuzz.For<T>().Apply(Func<T, T> func) as For can only be used for objects, so there is no need for it really.

Lastly the convention based Apply has an overload which takes another generator. This generator then provides a value which can be used in the action parameter.

E.g. :

var parents = ...
Fuzz.For<SomeChild>().Apply(Fuzz.ChooseFrom(parents), (child, parent) => parent.Add(child))

Picking an element out of a range.

Use Fuzz.ChooseFrom<T>(IEnumerable<T> values).

Picks a random value from a list of options.

F.i. Fuzz.ChooseFrom(new []{ 1, 2 }) will return either 1 or 2.

A helper method exists for ease of use when you want to pass in constant values as in the example above.

I.e. : Fuzz.ChooseFromThese(1, 2)

Another method provides a semi-safe way to pick from what might be an empty list.

I.e. : Fuzz.ChooseFromWithDefaultWhenEmpty(new List<int>()), which returns the default, in this case zero.

You can also pick from a set of Generators.

I.e. : Fuzz.ChooseGenerator(Fuzz.Constant(1), Fuzz.Constant(2))

Generating unique values.

Use the .Unique(object key) extension method.

Makes sure that every generated value is unique.

When asking for more unique values than the generator can supply, an exception is thrown.

Multiple unique generators can be defined in one 'composed' generator, without interfering with eachother by using a different key.

When using the same key for multiple unique generators all values across these generators are unique.

An overload exist taking a function as an argument allowing for a dynamic key.

Filtering generated values.

Use the .Where(Func<T, bool>) extension method.

Makes sure that every generated value passes the supplied predicate.

Casting Generators.

Various extension methods allow for casting the generated value.

  • .AsString() : Invokes .ToString() on the generated value and casts the generator from Generator<T> to Generator<string>. Useful f.i. to generate numeric strings.

  • .AsObject() : Simply casts the generator itself from Generator<T> to Generator<object>. Mostly used internally.

  • .Nullable() : Casts a Generator<T> to Generator<T?>. In addition generates null 1 out of 5 times.

  • .Nullable(int timesBeforeResultIsNullAproximation) : overload of Nullable(), generates null 1 out of timesBeforeResultIsNullAproximation times .

How About Null(s)?

Various extension methods allow for influencing null generation.

  • .Nullable() : Casts a Generator<T> to Generator<T?>. In addition generates null 1 out of 5 times.

Used for value types.

  • .Nullable(int timesBeforeResultIsNullAproximation) : overload of Nullable(), generates null 1 out of timesBeforeResultIsNullAproximation times .

  • .NullableRef() : Casts a Generator<T> to Generator<T?>. In addition generates null 1 out of 5 times.

Used for reference types, including string.

  • .NullableRef(int timesBeforeResultIsNullAproximation) : overload of NullableRef(), generates null 1 out of timesBeforeResultIsNullAproximation times .

'Generating' constants.

Use Fuzz.Constant<T>(T value).

This generator is most useful in combination with others and is used to inject constants into combined generators.

'Never return null.

Use the .NeverReturnNull() extension method.`.

Only available on generators that provide Nullable<T> values, this one makes sure that, you guessed it, the nullable generator never returns null.


The Primitive Generators

Integers.

Use Fuzz.Int().

The overload Fuzz.Int(int min, int max) generates an int higher or equal than min and lower than max.

Throws an ArgumentException if min > max.

The default generator is (min = 1, max = 100).

Can be made to return int? using the .Nullable() combinator.

  • int is automatically detected and generated for object properties.

  • Int32 is automatically detected and generated for object properties.

  • int? is automatically detected and generated for object properties.

Chars.

Use Fuzz.Char().

No overload exists.

The default generator always generates a char between lower case 'a' and lower case 'z'.

Can be made to return char? using the .Nullable() combinator.

  • char is automatically detected and generated for object properties.

  • char? is automatically detected and generated for object properties.

Strings.

Use Fuzz.String().

The generator always generates every char element of the string to be between lower case 'a' and lower case 'z'.

The overload Fuzz.String(int min, int max) generates an string of length higher or equal than min and lower than max.

The Default generator generates a string of length higher than 0 and lower than 10.

  • string is automatically detected and generated for object properties.

Can be made to return string? using the .NullableRef() combinator.

Booleans.

Use Fuzz.Bool().

No overload exists.

The default generator generates True or False.

Can be made to return bool? using the .Nullable() combinator.

  • bool is automatically detected and generated for object properties.

  • bool? is automatically detected and generated for object properties.

Decimals.

Use Fuzz.Decimal().

The overload Fuzz.Decimal(decimal min, decimal max) generates a decimal higher or equal than min and lower than max.

Throws an ArgumentException if min > max.

The default generator is (min = 1, max = 100).

Can be made to return decimal? using the .Nullable() combinator.

  • decimal is automatically detected and generated for object properties.

  • decimal? is automatically detected and generated for object properties.

DateTimes.

Use Fuzz.DateTime().

The overload Fuzz.DateTimes(DateTime min, DateTime max) generates a DateTime higher or equal than min and lower than max.

The default generator is (min = new DateTime(1970, 1, 1), max = new DateTime(2020, 12, 31)).

Can be made to return DateTime? using the .Nullable() combinator.

  • DateTime is automatically detected and generated for object properties.

  • DateTime? is automatically detected and generated for object properties.

Longs.

Use Fuzz.Long().

The overload Fuzz.Long(long min, long max) generates a long higher or equal than min and lower than max.

Throws an ArgumentException if min > max.

The default generator is (min = 1, max = 100).

Can be made to return long? using the .Nullable() combinator.

  • long is automatically detected and generated for object properties.

  • Int64 is automatically detected and generated for object properties.

  • long? is automatically detected and generated for object properties.

Doubles.

Use Fuzz.Double().

The overload Fuzz.Double(double min, double max) generates a double higher or equal than min and lower than max.

Throws an ArgumentException if min > max.

The default generator is (min = 1, max = 100).

Can be made to return double? using the .Nullable() combinator.

  • double is automatically detected and generated for object properties.

  • double? is automatically detected and generated for object properties.

Floats.

Use Fuzz.Float().

The overload Fuzz.Float(float min, float max) generates a float higher or equal than min and lower than max.

Throws an ArgumentException if min > max.

The default generator is (min = 1, max = 100).

Can be made to return float? using the .Nullable() combinator.

  • float is automatically detected and generated for object properties.

  • float? is automatically detected and generated for object properties.

Guids.

Use Fuzz.Guid().

There is no overload.

The default generator never generates Guid.Empty.

Can be made to return Guid? using the .Nullable() combinator.

  • Guid is automatically detected and generated for object properties.

  • Guid? is automatically detected and generated for object properties.

Shorts.

Use Fuzz.Short().

The overload Fuzz.Short(short min, short max) generates a short higher or equal than min and lower than max.

The default generator is (min = 1, max = 100).

Can be made to return short? using the .Nullable() combinator.

  • short is automatically detected and generated for object properties.

  • short? is automatically detected and generated for object properties.

TimeSpans.

Use Fuzz.TimeSpan().

The overload Fuzz.TimeSpan(int max) generates a TimeSpan with Ticks higher or equal than 1 and lower than max.

The default generator is (max = 1000).

Can be made to return TimeSpan? using the .Nullable() combinator.

  • TimeSpan is automatically detected and generated for object properties.

  • TimeSpan? is automatically detected and generated for object properties.

Enums.

Use Fuzz.Enum<T>(), where T is the type of Enum you want to generate.

No overload exists.

The default generator just picks a random value from all enemeration values.

  • An Enumeration is automatically detected and generated for object properties.

  • A nullable Enumeration is automatically detected and generated for object properties.

  • Passing in a non Enum type for T throws an ArgumentException.


Creating Custom Generators

How To

Any function that returns a value of type Generator<T> can be used as a generator.

Generator is defined as a delegate like so :

public delegate IResult<TValue> Generator<out TValue>(State input)

So f.i. to define a generator that always returns the number forty-two we need a function that returns the following :

return s => new Result<State, int>(42, s);

As you can see from the signature a state object is passed to the generator. This is where the random seed lives. If you want any kind of random, it is advised to use that one, like so :

return s => new Result<State, int>(s.Random.Next(42, 42), s);

See also : Creating a counter generator.


Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • net8.0

    • No dependencies.

NuGet packages (1)

Showing the top 1 NuGet packages that depend on QuickFuzzr:

Package Downloads
QuickAcid

Drop it in acid. Look for gold. Like alchemy, but reproducible.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.1.1 165 8/6/2025
0.1.0 184 7/19/2025