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" />
<PackageVersion Include="Jds.TestingUtils.Randomization" Version="0.9.0" />
<PackageReference Include="Jds.TestingUtils.Randomization" />
paket add Jds.TestingUtils.Randomization --version 0.9.0
#r "nuget: Jds.TestingUtils.Randomization, 0.9.0"
#:package Jds.TestingUtils.Randomization@0.9.0
#addin nuget:?package=Jds.TestingUtils.Randomization&version=0.9.0
#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.Sharedinstance ofIRandomizationSource, which generates random values usingSystem.Random.Shared. ThisIRandomizationSourceis 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 of3to6Guidvalues.
- Creates an
Select a Random Item or Enumeration Value
IRandomizationSource.RandomEnumValue<TEnum>()- Selects a pseudo-random value from the
enumof 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
.Itemfrom 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
.Keyfrom 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
stringoflengthcharacters, using providedchars. Random selections fromcharsare concatenated until reachinglengthcharacters.
- Generates a pseudo-random
IRandomizationSource.RandomString(int length, IReadOnlyList<string> strings)- Generates a pseudo-random
stringoflengthcharacters, using providedstrings. Random selections fromstringsare concatenated until reachinglengthcharacters. The result is truncated tolengthcharacters.
- Generates a pseudo-random
IRandomizationSource.RandomStringLatin(int length, bool uppercase = false, bool alphanumeric = false)- Generates a pseudo-random
stringoflengthcharacters using ASCII Latin characters. Usesa-zby default. Ifuppercase, usesA-Z. Ifalphanumeric, also includes0-9with either casing.
- Generates a pseudo-random
Generate a Random Hexadecimal String (e.g., certificate thumbprint)
IRandomizationSource.Hexadecimal(int length)- Generates a pseudo-random hexadecimal (
0throughf, lowercase) string.
- Generates a pseudo-random hexadecimal (
IRandomizationSource.HashSha256()- Generates a
64-character hexadecimal (0throughf, lowercase) string.
- Generates a
IRandomizationSource.HashSha384()- Generates a
96-character hexadecimal (0throughf, lowercase) string.
- Generates a
IRandomizationSource.HashSha512()- Generates a
128-character hexadecimal (0throughf, 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.Userwill be adot-atomform oflocal-part(see RFC-2822 section 3.4.1). The generatedSystem.Net.Mail.MailAddress.Hostwill 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
stringaccording toaddr-spec(see RFC-2822 section 3.4.1). The generatedlocal-partwill be ofdot-atomform (see RFC-2822 section 3.4.1). The generateddomainwill be ofdot-atomform (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
stringaccording 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
stringURL according to RFC-3986 URI syntax. Thehostsegment 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 maxLengthand uses a Markov Chain model, derived fromsources, to generate sequences ofTof up to lengthmaxLength.- The
chainLengthdetermines how manyTare 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 maxLengthand uses a Markov Chain model, derived fromsources, to generate strings of up to lengthmaxLength.- The
chainLengthdetermines how many characters in each inputstringare 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
chainLengthdetermines 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
stringbased upon a Markov Chain model, derived fromsources..- The
chainLengthdetermines how many characters in each inputstringare 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
stringofparagraphParameters.WordCountwords, broken into a random number of sentences. Each word in the paragraph is no more thanparagraphParameters.MaxWordLengthcharacters.
- Generates a paragraph
IRandomizationSource.LoremIpsumSentence((int WordCount, int MaxWordLength) sentenceParameters)- Generates a sentence
stringofsentenceParameters.WordCountwords, each word no more thansentenceParameters.MaxWordLengthcharacters. Sentences always begin with a capital letter and end with a period (.).
- Generates a sentence
IRandomizationSource.LoremIpsumWord(int maxLength)- Generates a word
stringof no more thanmaxLengthcharacters.
- 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
DateTimewithin theageRangespecified, relative torelativeTo. If not provided,ageRangedefaults to(MinAgeInYears: 18, MaxAgeInYearsExclusive: 96). If not provided,relativeTodefaults toDateTime.UtcNow.
- Generates a date of birth
IRandomizationSource.DemographicsForenameUsa(int maxLength)- Generates a forename
stringof no more thanmaxLengthcharacters. Generated names have an initial capital letter and all subsequent characters are lowercase.
- Generates a forename
IRandomizationSource.DemographicsSurnameUsa(int maxLength)- Generates a surname
stringof no more thanmaxLengthcharacters. 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
staticmethod 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
Bindto replace the stateful randomization source with a new stateful randomization source derived from current state. This is an uncommonIStatefulRandomizationSourceoperation, normally only used when swapping the underlyingIRandomizationSource.
- Use
IStatefulRandomizationSource<TStateCurrent,TStateNew>.Map(Func<TStateCurrent,TStateNew>)- Use
Mapto 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. 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. |
-
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 | 2,136 | 10/5/2024 | |
| 0.8.0 | 1,369 | 6/25/2024 | |
| 0.7.0 | 1,050 | 11/12/2023 | |
| 0.6.0 | 3,921 | 5/16/2023 | |
| 0.5.0 | 1,037 | 1/10/2023 | |
| 0.5.0-build-20220414-050254... | 323 | 4/14/2022 | |
| 0.4.0 | 1,488 | 2/19/2022 | |
| 0.4.0-build-20220214-011232... | 291 | 2/14/2022 | |
| 0.3.0 | 627 | 2/14/2022 | |
| 0.3.0-build-20220214-010752... | 319 | 2/14/2022 | |
| 0.3.0-build-20220214-004124... | 324 | 2/14/2022 | |
| 0.3.0-build-20220208-010440... | 320 | 2/8/2022 | |
| 0.2.0 | 536 | 2/8/2022 | |
| 0.2.0-build-20220208-005756... | 303 | 2/8/2022 | |
| 0.2.0-build-20220206-223707... | 302 | 2/6/2022 | |
| 0.2.0-build-20220206-212627... | 326 | 2/6/2022 | |
| 0.2.0-build-20220204-031004... | 350 | 2/4/2022 | |
| 0.1.0 | 607 | 2/4/2022 | |
| 0.1.0-build-20220204-024107... | 327 | 2/4/2022 | |
| 0.0.0-build-20220204-022926... | 327 | 2/4/2022 | |
| 0.0.0-build-20220204-021830... | 325 | 2/4/2022 | |
| 0.0.0-build-20220202-013346... | 350 | 2/2/2022 |