Jds.TestingUtils.Randomization
0.9.0
dotnet add package Jds.TestingUtils.Randomization --version 0.9.0
NuGet\Install-Package Jds.TestingUtils.Randomization -Version 0.9.0
<PackageReference Include="Jds.TestingUtils.Randomization" Version="0.9.0" />
paket add Jds.TestingUtils.Randomization --version 0.9.0
#r "nuget: Jds.TestingUtils.Randomization, 0.9.0"
// Install Jds.TestingUtils.Randomization as a Cake Addin #addin nuget:?package=Jds.TestingUtils.Randomization&version=0.9.0 // Install Jds.TestingUtils.Randomization as a Cake Tool #tool nuget:?package=Jds.TestingUtils.Randomization&version=0.9.0
Testing Utils: Randomization
This collection of randomization test utilities supports creating test arrangements.
API Documentation
See API Documentation.
How to Use
All examples below use the thread-safe, static
Jds.TestingUtils.Randomization.Randomizer.Shared
instance ofIRandomizationSource
, which generates random values usingSystem.Random.Shared
. ThisIRandomizationSource
is advised for most tests.If a different algorithm is needed, e.g., a cryptographically strong random number generator is required, consider creating a
Jds.TestingUtils.Randomization.ArrangedRandomizationSource
. It uses providedFunc<IEnumerable<>>
delegates to supply values when requested.If a specific set of random-seeming data is needed, consider creating a
Jds.TestingUtils.Randomization.DeterministicRandomizationSource
. It uses providedIEnumerable<>
sources to supply values when requested.
Add Jds.TestingUtils.Randomization
NuGet Package and Add using
Add Jds.TestingUtils.Randomization
NuGet package to the test project.
Add the extensions to your test files with the following using
statement:
using Jds.TestingUtils.Randomization;
All examples below assume the following additional using
statements:
using System;
using System.Collections.Generic;
using System.Linq;
Generate Pseudo-random Numbers
IRandomizationSource.Boolean()
- Gets a pseudo-random
bool
.
- Gets a pseudo-random
IRandomizationSource.Byte()
- Gets a pseudo-random
byte
, greater than or equal tobyte.MinValue
, and less thanbyte.MaxValue
.
- Gets a pseudo-random
IRandomizationSource.ByteInRange(byte minInclusive, byte maxExclusive)
- Gets a pseudo-random
byte
, greater than or equal tominInclusive
, and less thanmaxExclusive
.
- Gets a pseudo-random
IRandomizationSource.Double()
- Gets a pseudo-random
double
, usingIRandomizationSource.NextDouble
. The value should be greater than or equal to0.0
, and less than1.0
.
- Gets a pseudo-random
IRandomizationSource.Float()
- Gets a pseudo-random
float
, usingIRandomizationSource.NextFloat
. The value should be greater than or equal to0.0
, and less than1.0
.
- Gets a pseudo-random
IRandomizationSource.Int()
- Gets a pseudo-random
int
, usingIRandomizationSource.NextIntInRange
. The value should be greater than or equal toint.MinValue
, and less thanint.MaxValue
.
- Gets a pseudo-random
IRandomizationSource.IntInRange(int minInclusive, int maxExclusive)
- Gets a pseudo-random
int
, usingIRandomizationSource.NextIntInRange
. The value should be greater than or equal tominInclusive
, and less thanmaxExclusive
.
- Gets a pseudo-random
IRandomizationSource.IntNegative()
- Gets a pseudo-random
int
, usingIRandomizationSource.NextIntInRange
. The value should be greater than or equal toint.MinValue
, and less than0
.
- Gets a pseudo-random
IRandomizationSource.IntPositive()
- Gets a pseudo-random
int
, usingIRandomizationSource.NextIntInRange
. The value should be greater than or equal to0
, and less thanint.MaxValue
.
- Gets a pseudo-random
IRandomizationSource.Long()
- Gets a pseudo-random
long
, usingIRandomizationSource.NextLongInRange
. The value should be greater than or equal tolong.MinValue
, and less thanlong.MaxValue
.
- Gets a pseudo-random
IRandomizationSource.LongInRange(long minInclusive, long maxExclusive)
- Gets a pseudo-random
long
, usingIRandomizationSource.NextLongInRange
. The value should be greater than or equal tominInclusive
, and less thanmaxExclusive
.
- Gets a pseudo-random
IRandomizationSource.LongNegative()
- Gets a pseudo-random
long
, usingIRandomizationSource.NextLongInRange
. The value should be greater than or equal tolong.MinValue
, and less than0
.
- Gets a pseudo-random
IRandomizationSource.LongPositive()
- Gets a pseudo-random
long
, usingIRandomizationSource.NextLongInRange
. The value should be greater than or equal to0
, and less thanlong.MaxValue
.
- Gets a pseudo-random
IRandomizationSource.UShort()
- Gets a pseudo-random
ushort
.
- Gets a pseudo-random
Generate a Random Number of Generated Items
IRandomizationSource.Enumerable<T>(Func<T> factory, int inclusiveMinCount, int exclusiveMaxCount)
IRandomizationSource.Enumerable<T>(Func<int, T> factory, int inclusiveMinCount, int exclusiveMaxCount)
- Creates an
IEnumerable<T>
of a randomly-generated length using values provided by a factory method. - Example:
Randomizer.Shared.Enumerable(Guid.NewGuid, 3, 7)
- which would generate a sequence of3
to6
Guid
values.
- Creates an
Select a Random Item or Enumeration Value
IRandomizationSource.RandomEnumValue<TEnum>()
- Selects a pseudo-random value from the
enum
of type specified (TEnum
). - Example:
Randomizer.Shared.RandomEnumValue<System.Net.HttpStatusCode>()
- Selects a pseudo-random value from the
IRandomizationSource.RandomListItem<T>(IReadOnlyList<T> items)
IReadOnlyList<T>.GetRandomItem<T>()
- Selects a pseudo-random item from provided
items
. - Example:
Randomizer.Shared.RandomListItem(System.Linq.Enumerable.Range(1, 20).ToArray())
- Selects a pseudo-random item from provided
Select a Weighted Random Item or Dictionary Key
IRandomizationSource.RandomListItem<T>(IReadOnlyList<(T Item, double Weight)> weightedItems)
IRandomizationSource.RandomListItem<T>(IReadOnlyList<(T Item, int Weight)> weightedItems)
IReadOnlyList<(T Key, double Weight)>.GetWeightedRandomItem<T>()
IReadOnlyList<(T Key, int Weight)>.GetWeightedRandomItem<T>()
- Selects a pseudo-random
.Item
from providedweightedItems
; item selection is weighted based upon relative.Weight
. - Example:
- Selects a pseudo-random
Randomizer.Shared.WeightedRandomListItem(
new[] { ("Sure", 1000), ("Likely", 500), ("Possible", 200), ("Unlikely", 50), ("Rare", 5), ("Apocryphal", 1) }
);
IRandomizationSource.GetWeightedRandomKey<T>(IReadOnlyDictionary<T, double> weightedKeys)
IRandomizationSource.GetWeightedRandomKey<T>(IReadOnlyDictionary<T, int> weightedKeys)
IReadOnlyDictionary<T, double>.GetWeightedRandomKey<T>()
IReadOnlyDictionary<T, int>.GetWeightedRandomKey<T>()
- Selects a pseudo-random
.Key
from providedweightedItems
; item selection is weighted based upon relative.Value
. - Example:
- Selects a pseudo-random
Randomizer.Shared.WeightedRandomKey(new Dictionary<string, double>
{
{ "North", 0.4 }, { "East", 0.1 }, { "West", 0.1 }, { "South", 0.4 }
});
Generate a Random String
IRandomizationSource.RandomString(int length, IReadOnlyList<char> chars)
- Generates a pseudo-random
string
oflength
characters, using providedchars
. Random selections fromchars
are concatenated until reachinglength
characters.
- Generates a pseudo-random
IRandomizationSource.RandomString(int length, IReadOnlyList<string> strings)
- Generates a pseudo-random
string
oflength
characters, using providedstrings
. Random selections fromstrings
are concatenated until reachinglength
characters. The result is truncated tolength
characters.
- Generates a pseudo-random
IRandomizationSource.RandomStringLatin(int length, bool uppercase = false, bool alphanumeric = false)
- Generates a pseudo-random
string
oflength
characters using ASCII Latin characters. Usesa
-z
by default. Ifuppercase
, usesA
-Z
. Ifalphanumeric
, also includes0
-9
with either casing.
- Generates a pseudo-random
Generate a Random Hexadecimal String (e.g., certificate thumbprint)
IRandomizationSource.Hexadecimal(int length)
- Generates a pseudo-random hexadecimal (
0
throughf
, lowercase) string.
- Generates a pseudo-random hexadecimal (
IRandomizationSource.HashSha256()
- Generates a
64
-character hexadecimal (0
throughf
, lowercase) string.
- Generates a
IRandomizationSource.HashSha384()
- Generates a
96
-character hexadecimal (0
throughf
, lowercase) string.
- Generates a
IRandomizationSource.HashSha512()
- Generates a
128
-character hexadecimal (0
throughf
, lowercase) string.
- Generates a
Generate a Mail Address
IRandomizationSource.MailAddress()
IRandomizationSource.MailAddress(int length)
- Generates a pseudo-random
System.Net.Mail.MailAddress
. The generatedSystem.Net.Mail.MailAddress.User
will be adot-atom
form oflocal-part
(see RFC-2822 section 3.4.1). The generatedSystem.Net.Mail.MailAddress.Host
will be adomain
(see RFC-1035 section 2.3.1).
- Generates a pseudo-random
IRandomizationSource.MailAddressAddrSpec(int length)
IRandomizationSource.MailAddressAddrSpec((int LocalPartLength, int DomainLength) componentLengths)
- Generates a pseudo-random
string
according toaddr-spec
(see RFC-2822 section 3.4.1). The generatedlocal-part
will be ofdot-atom
form (see RFC-2822 section 3.4.1). The generateddomain
will be ofdot-atom
form (see RFC-2822 section 3.4.1), and its value will be generated as a RFC-1035 section 2.3.1domain
.
- Generates a pseudo-random
Generate a Domain
IRandomizationSource.DomainName(int length)
IRandomizationSource.DomainName(IReadOnlyList<int> domainLabelLengths)
- Generates a pseudo-random
string
according todomain
(see RFC-1035 section 2.3.1).
- Generates a pseudo-random
Generate a URL
IRandomizationSource.RandomUrl(int hostLength, int pathLength = 0, int queryLength = 0, int fragmentLength = 0, string scheme = "https", int? port = null)
- Generates a pseudo-random
string
URL according to RFC-3986 URI syntax. Thehost
segment is generated usingIRandomizationSource.DomainName(int length)
.
- Generates a pseudo-random
Generate an IP Address
IRandomizationSource.IpV4(byte? octet1 = null, byte? octet2 = null, byte? octet3 = null, byte? octet4 = null)
- Generates a pseudo-random IP v4 address.
IRandomizationSource.IpV6(ushort? piece1 = null, ushort? piece2 = null, ushort? piece3 = null, ushort? piece4 = null, ushort? piece5 = null, ushort? piece6 = null, ushort? piece7 = null, ushort? piece8 = null)
- Generates a pseudo-random IP v6 address.
Generate a Sequence of Items from a Markov Chain Model
IRandomizationSource.CreateMarkovGenerator(IReadOnlyCollection<IReadOnlyList<T>> sources, int chainLength = 1) where T : notnull, IEquatable<T>
- Generates a
Func<int, IReadOnlyList<T>>
which accepts anint maxLength
and uses a Markov Chain model, derived fromsources
, to generate sequences ofT
of up to lengthmaxLength
.- The
chainLength
determines how manyT
are grouped to determine Markov Chain probability.
- The
- Generates a
IRandomizationSource.CreateMarkovGenerator(IEnumerable<string> sources, int chainLength = 1)
- Generates a
Func<int, string>
which accepts anint maxLength
and uses a Markov Chain model, derived fromsources
, to generate strings of up to lengthmaxLength
.- The
chainLength
determines how many characters in each inputstring
are grouped to determine Markov Chain probability.
- The
- Example uses: create a random word or name generator using a list of example words or names.
- Example:
- Generates a
var exampleFruitNames = new[]
{
"apple", "apricot", "avocado", "banana", "blackberry", "blackcurrant", "blueberry", "boysenberry", "cantaloupe",
"caper", "cherry", "cranberry", "elderberry", "fig", "gooseberry", "grape", "grapefruit", "guava", "jujube",
"kiwi", "kumquat", "lemon", "lime", "lychee", "mango", "mulberry", "olive", "orange", "papaya", "pear",
"persimmon", "pineapple", "plantain", "plum", "pomegranate", "raspberry", "starfruit", "strawberry", "tangerine",
"watermelon"
};
Func<int, string> fruitGenerator = Randomizer.Shared.CreateMarkovGenerator(sources: exampleFruitNames, chainLength: 2);
string generatedFruit = fruitGenerator(maxLength: 12);
string possiblyLongerGeneratedFruit = fruitGenerator(maxLength: 20);
string likelyShorterGeneratedFruit = fruitGenerator(maxLength: 6);
IRandomizationSource.GenerateRandomMarkov<T>(IReadOnlyCollection<IReadOnlyList<T>> sources, int? maxLength = null, int chainLength = 1)
- Generates a
IReadOnlyList<T>
based upon a Markov Chain model, derived fromsources
.- The
chainLength
determines how many items in each inputIReadOnlyList<T>
are grouped to determine Markov Chain probability.
- The
- Use
IRandomizationSource.CreateMarkovGenerator()
(above), instead of this function, unless only a single value is needed.- The resources needed to generate the Markov Chain model are non-trivial. This function creates a new model each time it is executed, consuming both computational and memory resources.
- Generates a
IRandomizationSource.GenerateRandomMarkov(IEnumerable<string> sources, int? maxLength = null, int chainLength = 1)
- Generates a
string
based upon a Markov Chain model, derived fromsources
..- The
chainLength
determines how many characters in each inputstring
are grouped to determine Markov Chain probability.
- The
- Use
IRandomizationSource.CreateMarkovGenerator()
(above), instead of this function, unless only a single value is needed.- The resources needed to generate the Markov Chain model are non-trivial. This function creates a new model each time it is executed, consuming both computational and memory resources.
- Example uses: create a random word or name generator using a list of example words or names.
- Example:
- Generates a
var exampleFruitNames = new[]
{
"apple", "apricot", "avocado", "banana", "blackberry", "blackcurrant", "blueberry", "boysenberry", "cantaloupe",
"caper", "cherry", "cranberry", "elderberry", "fig", "gooseberry", "grape", "grapefruit", "guava", "jujube",
"kiwi", "kumquat", "lemon", "lime", "lychee", "mango", "mulberry", "olive", "orange", "papaya", "pear",
"persimmon", "pineapple", "plantain", "plum", "pomegranate", "raspberry", "starfruit", "strawberry", "tangerine",
"watermelon"
};
string similarGeneratedFruit = Randomizer.Shared.GenerateRandomMarkov(sources: exampleFruitNames, maxLength: 12, chainLength: 2);
string slightlySimilarGeneratedFruit = Randomizer.Shared.GenerateRandomMarkov(sources: exampleFruitNames, maxLength: 20, chainLength: 1);
string verySimilarGeneratedFruit = Randomizer.Shared.GenerateRandomMarkov(sources: exampleFruitNames, maxLength: 15, chainLength: 3);
Generate a Word, Sentence, or Paragraph (Lorem Ipsum)
The Lorem Ipsum random generators create Latin-like words, sentences, and paragraphs. They use Markov Chain models trained on multiple Latin sources: the traditional Lorem Ipsum excerpts of Cicero's De Finibus Bonorum et Malorum, and excerpts of René Descartes's Meditationes de Prima Philosophia.
IRandomizationSource.LoremIpsumParagraph((int WordCount, int MaxWordLength) paragraphParameters)
- Generates a paragraph
string
ofparagraphParameters.WordCount
words, broken into a random number of sentences. Each word in the paragraph is no more thanparagraphParameters.MaxWordLength
characters.
- Generates a paragraph
IRandomizationSource.LoremIpsumSentence((int WordCount, int MaxWordLength) sentenceParameters)
- Generates a sentence
string
ofsentenceParameters.WordCount
words, each word no more thansentenceParameters.MaxWordLength
characters. Sentences always begin with a capital letter and end with a period (.
).
- Generates a sentence
IRandomizationSource.LoremIpsumWord(int maxLength)
- Generates a word
string
of no more thanmaxLength
characters.
- Generates a word
Generate User Demographics
The name generators use Markov Chain models trained on public census and government data.
IRandomizationSource.DemographicsBirthDateTime(DateTime? relativeTo = null)
IRandomizationSource.DemographicsBirthDateTime((int MinAgeInYears, int MaxAgeInYearsExclusive) ageRange, DateTime? relativeTo = null)
- Generates a date of birth
DateTime
within theageRange
specified, relative torelativeTo
. If not provided,ageRange
defaults to(MinAgeInYears: 18, MaxAgeInYearsExclusive: 96)
. If not provided,relativeTo
defaults toDateTime.UtcNow
.
- Generates a date of birth
IRandomizationSource.DemographicsForenameUsa(int maxLength)
- Generates a forename
string
of no more thanmaxLength
characters. Generated names have an initial capital letter and all subsequent characters are lowercase.
- Generates a forename
IRandomizationSource.DemographicsSurnameUsa(int maxLength)
- Generates a surname
string
of no more thanmaxLength
characters. Generated names have an initial capital letter and all subsequent characters are lowercase.
- Generates a surname
Create a Custom Domain-Specific Language to Generate Complex or Custom Types
This library does not provide a domain-specific language. However, by creating your own static
methods extending IStatefulRandomizationSource<TState>
(where TState
should be your generator options), you can easily construct a domain-specific language to generate complex or custom types.
This library's unit tests include an example Domain-Specific Language which generates characters for a role-playing game. The documented example illustrates:
- creating a randomization state object (to provide configuration)
- creating a domain value object (the thing we want to generate)
- creating a domain-specific language (a
static
method extendingIStatefulRandomizationSource<TState>
which used the configuration and generated the value object)- creating unit tests which use the domain-specific language
This functionality was already possible by extending IRandomizationSource
with methods accepting parameters. However, IStatefulRandomizationSource<TState>
provides greater flexibility. By embedding state object types into your extension methods, you can simplify verbose generator method signatures.
The IStatefulRandomizationSource<TState>
extends IRandomizationSource
with a public TState State { get; }
property.
Construction
Use Randomizer.WithState()
static methods to create a new stateful randomizer based upon an initial state value.
Use the .WithState(TState initialState)
extension method on IRandomizationSource
to create a derived stateful randomizer using that randomization source instance.
Modifying State
In some scenarios, you may want to modify the existing randomization source state (e.g., when designing a "builder" interface). This is handled using some monadic methods.
It is intended that the state values used in a randomization source are immutable. When the state needs to change, the following monadic methods allow you to derive a new
IStatefulRandomizationSource<TState>
using the current state value.
IStatefulRandomizationSource<TStateCurrent,TStateNew>.Bind(Func<TStateCurrent,IStatefulRandomizationSource<TStateNew>>)
- Use
Bind
to replace the stateful randomization source with a new stateful randomization source derived from current state. This is an uncommonIStatefulRandomizationSource
operation, normally only used when swapping the underlyingIRandomizationSource
.
- Use
IStatefulRandomizationSource<TStateCurrent,TStateNew>.Map(Func<TStateCurrent,TStateNew>)
- Use
Map
to replace the state contained within the stateful randomization source with a new state (which may be of the same type or another). This is the most common state operation.
- Use
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net6.0 is compatible. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. 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. |
-
net6.0
- No dependencies.
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
Version | Downloads | Last updated | |
---|---|---|---|
0.9.0 | 141 | 10/5/2024 | |
0.8.0 | 621 | 6/25/2024 | |
0.7.0 | 831 | 11/12/2023 | |
0.6.0 | 1,850 | 5/16/2023 | |
0.5.0 | 920 | 1/10/2023 | |
0.5.0-build-20220414-050254... | 203 | 4/14/2022 | |
0.4.0 | 1,371 | 2/19/2022 | |
0.4.0-build-20220214-011232... | 163 | 2/14/2022 | |
0.3.0 | 479 | 2/14/2022 | |
0.3.0-build-20220214-010752... | 179 | 2/14/2022 | |
0.3.0-build-20220214-004124... | 179 | 2/14/2022 | |
0.3.0-build-20220208-010440... | 182 | 2/8/2022 | |
0.2.0 | 399 | 2/8/2022 | |
0.2.0-build-20220208-005756... | 174 | 2/8/2022 | |
0.2.0-build-20220206-223707... | 176 | 2/6/2022 | |
0.2.0-build-20220206-212627... | 199 | 2/6/2022 | |
0.2.0-build-20220204-031004... | 205 | 2/4/2022 | |
0.1.0 | 469 | 2/4/2022 | |
0.1.0-build-20220204-024107... | 199 | 2/4/2022 | |
0.0.0-build-20220204-022926... | 204 | 2/4/2022 | |
0.0.0-build-20220204-021830... | 215 | 2/4/2022 | |
0.0.0-build-20220202-013346... | 205 | 2/2/2022 |