Skip to content

Commit

Permalink
All unit tests passing with localized randomizer. #100
Browse files Browse the repository at this point in the history
  • Loading branch information
bchavez committed Nov 4, 2017
1 parent dec7a15 commit da37d08
Show file tree
Hide file tree
Showing 19 changed files with 529 additions and 217 deletions.
1 change: 1 addition & 0 deletions Source/Bogus.Tests/Bogus.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@
<Compile Include="ExtensionTests\ExtensionTest.cs" />
<Compile Include="FluentTests.cs" />
<Compile Include="GitHubIssues\Issue10.cs" />
<Compile Include="GitHubIssues\Issue100.cs" />
<Compile Include="GitHubIssues\Issue13.cs" />
<Compile Include="GitHubIssues\Issue23.cs" />
<Compile Include="GitHubIssues\Issue45.cs" />
Expand Down
180 changes: 180 additions & 0 deletions Source/Bogus.Tests/GitHubIssues/Issue100.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
using System;
using System.Linq;
using System.Threading.Tasks;
using Bogus.DataSets;
using FluentAssertions;
using Xunit;
using Xunit.Abstractions;

namespace Bogus.Tests.GitHubIssues
{
public class Issue100 : SeededTest
{
private readonly ITestOutputHelper console;

public Issue100(ITestOutputHelper console)
{
this.console = console;
}

[Fact]
public void dataset_test()
{
var c = new Commerce
{
Random = new Randomizer(54321)
};

c.Product().Should().Be("Shirt");
Randomizer.Seed = new Random(7331);
c.Product().Should().Be("Soap");

Randomizer.Seed = new Random(1337);
c.Random = new Randomizer(54321);

c.Product().Should().Be("Shirt");
Randomizer.Seed = new Random(3173);
c.Product().Should().Be("Soap");
}

[Fact]
public void faker_test()
{
var f = new Faker()
{
Random = new Randomizer(54321)
};

f.Commerce.Product().Should().Be("Shirt");
Randomizer.Seed = new Random(7331);
f.Commerce.Product().Should().Be("Soap");

Randomizer.Seed = new Random(1337);
f.Random = new Randomizer(54321);

f.Commerce.Product().Should().Be("Shirt");
Randomizer.Seed = new Random(3173);
f.Commerce.Product().Should().Be("Soap");
}

[Fact]
public void randomizer_twice()
{
var r = new Randomizer(88);
Enumerable.Range(1, 4)
.Select(i => r.Number(1, 3))
.Should().Equal(3, 2, 1, 2);

r = new Randomizer(88);
Enumerable.Range(1, 4)
.Select(i => r.Number(1, 3))
.Should().Equal(3, 2, 1, 2);
}

[Fact]
public void faker_test_2()
{
var f = new Faker();
f.Random = new Randomizer(88);

Enumerable.Range(1, 4)
.Select(i => f.Random.Number(1, 3))
.Should().Equal(3, 2, 1, 2);

f.Random = new Randomizer(88);

Enumerable.Range(1, 4)
.Select(i => f.Random.Number(1, 3))
.Should().Equal(3, 2, 1, 2);
}

[Fact]
public void simple_faker_t_test()
{
var orderFaker = new Faker<Examples.Order>()
.UseSeed(88)
.RuleFor(o => o.Quantity, f =>
{
return f.Random.Number(1, 3);
});

var order = orderFaker.Generate();

order.Quantity.Should().Be(3);

orderFaker.UseSeed(88);

order = orderFaker.Generate();

order.Quantity.Should().Be(3);
}

[Fact]
public void complex_faker_t_test()
{
Randomizer.Seed = new Random(7331);

var orderFaker = new Faker<Examples.Order>()
.UseSeed(88)
.RuleFor(o => o.OrderId, f => f.IndexVariable++)
.RuleFor(o => o.Quantity, f => f.Random.Number(1, 3))
.RuleFor(o => o.Item, f => f.Commerce.Product());

var items = Enumerable.Range(1, 4)
.Select(i => orderFaker.Generate())
.ToArray();

console.WriteLine(items.DumpString());

items.Select(i => i.OrderId).Should().Equal(0, 1, 2, 3);

CheckSequence(items);

//using the same seed again should
//reset the state.
orderFaker.UseSeed(88);
//and it should override a set seeded test
Randomizer.Seed = new Random(1337);

items = Enumerable.Range(1, 4)
.Select(i => orderFaker.Generate())
.ToArray();

items.Select(i => i.OrderId).Should().Equal(4, 5, 6, 7);

console.WriteLine(items.DumpString());

CheckSequence(items);
}

//[Fact]
//public void parallel_determinism()
//{
// var orderFaker = new Faker<Examples.Order>()
// .RuleFor(o => o.OrderId, f => f.IndexVariable++)
// .RuleFor(o => o.Quantity, f => f.Random.Number(1, 3))
// .RuleFor(o => o.Item, f => f.Commerce.Product());

// var orders = ParallelEnumerable.Range(1, 5)
// .Select(threadId =>
// orderFaker
// .UseSeed(88)
// .Generate(4).ToArray()
// ).ToArray();

// foreach( var orderOfFour in orders )
// {
// CheckSequence(orderOfFour);
// }
//}

private void CheckSequence(Examples.Order[] items)
{
items.Select(i => i.Item)
.Should().Equal("Tuna", "Pants", "Shoes", "Soap");

items.Select(i => i.Quantity)
.Should().Equal(3, 1, 3, 2);
}
}
}
2 changes: 1 addition & 1 deletion Source/Bogus.Tests/RuleSetTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ public void should_throw_error_when_strict_mode_is_set()
var goodCustomers = testCustomers.Generate(5, "Good");
goodCustomers.Dump();
};
act.ShouldThrow<InvalidOperationException>();
act.ShouldThrow<ValidationException>();
}

[Fact]
Expand Down
4 changes: 2 additions & 2 deletions Source/Bogus.Tests/StrictModeTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public void should_throw_exception_on_incomplete_rules()
.RuleFor(o => o.Quantity, f => f.Random.Number(2, 5));

testOrders.Invoking(faker => faker.Generate())
.ShouldThrow<InvalidOperationException>();
.ShouldThrow<ValidationException>();
}

[Fact]
Expand All @@ -29,7 +29,7 @@ public void should_not_throw_exception_on_complete_rule_set()
.RuleFor(o => o.OrderId, f => f.Random.Number());

testOrders.Invoking(faker => faker.Generate())
.ShouldNotThrow<InvalidOperationException>();
.ShouldNotThrow<ValidationException>();
}

[Fact]
Expand Down
58 changes: 46 additions & 12 deletions Source/Bogus/DataSet.cs
Original file line number Diff line number Diff line change
@@ -1,14 +1,38 @@
using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using Bogus.Bson;
using Bogus.Platform;

namespace Bogus
{
public interface IHasRandomizer
{
Randomizer Random { set; }
}
public class SeedNotifier<T> where T : class, IHasRandomizer
{
private List<T> registry = new List<T>();

public U Flow<U>(U item) where U : class, T, IHasRandomizer
{
this.registry.Add(item);
return item;
}

public void Notify(Randomizer r)
{
foreach( var item in registry )
{
item.Random = r;
}
}
}

/// <summary>
/// Data set methods that access the BSON database of locales.
/// </summary>
public class DataSet : ILocaleAware
public class DataSet : ILocaleAware, IHasRandomizer
{
/// <summary>
/// Resolves the 'category' type of a dataset type; respects the 'DataCategory' attribute.
Expand All @@ -28,19 +52,29 @@ public DataSet(string locale = "en")
this.Locale = locale;

this.Category = ResolveCategory(this.GetType());

this.Random = new Randomizer();
}

/// <summary>
/// The Randomizer
/// </summary>
public Randomizer Random { get; set; }

/// <summary>
/// The category name inside the locale
/// </summary>
protected string Category { get; set; }
protected SeedNotifier<DataSet> Notifier = new SeedNotifier<DataSet>();

private Randomizer randomizer;

/// <summary>
/// The Randomizer
/// </summary>
public Randomizer Random
{
get => this.randomizer ?? (this.Random = new Randomizer());
set
{
this.randomizer = value;
this.Notifier.Notify(value);
}
}

/// <summary>
/// The category name inside the locale
/// </summary>
protected string Category { get; set; }

/// <summary>
/// Current locale of the data set.
Expand Down
3 changes: 1 addition & 2 deletions Source/Bogus/DataSets/Address.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public class Address : DataSet
/// <param name="locale"></param>
public Address( string locale = "en" ) : base( locale )
{
this.Name = new Name( locale );
this.Name = this.Notifier.Flow(new Name(locale));
}

/// <summary>
Expand All @@ -38,7 +38,6 @@ public string City()
{
return GetFormattedValue( "city" );
}



/// <summary>
Expand Down
2 changes: 1 addition & 1 deletion Source/Bogus/DataSets/Company.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public class Company : DataSet
/// <param name="locale"></param>
public Company(string locale = "en") : base(locale)
{
this.Name = new Name(locale);
this.Name = this.Notifier.Flow(new Name(locale));
}

/// <summary>
Expand Down
2 changes: 1 addition & 1 deletion Source/Bogus/DataSets/Internet.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public class Internet : DataSet
/// <param name="locale"></param>
public Internet(string locale = "en") : base(locale)
{
this.Name = new Name(locale);
this.Name = this.Notifier.Flow(new Name(locale));
this.userAgentGenerator = new UserAgentGenerator( () => this.Random);
}

Expand Down
2 changes: 1 addition & 1 deletion Source/Bogus/DataSets/System.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ public System(string locale = "en") : base(locale)
}

protected Lorem Lorem = null;
private Dictionary<string, BObject> lookup;
private Dictionary<string, BObject> lookup;
private BArray mimes;
private string[] exts;
private string[] types;
Expand Down
3 changes: 1 addition & 2 deletions Source/Bogus/Extensions/ExtensionsForBrazil.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ namespace Bogus.Extensions.Brazil
/// </summary>
public static class ExtensionsForBrazil
{
private static Randomizer r = new Randomizer();
private static readonly int[] CpfWeights = { 10, 9, 8, 7, 6, 5, 4, 3, 2 };
private static readonly int[] CnpjWeights = { 2, 3, 4, 5, 6, 7, 8, 9, 2, 3, 4, 5, 6 };

Expand All @@ -24,7 +23,7 @@ public static string Cpf(this Person p)
return p.context[Key] as string;
}

var digits = r.Digits(9);
var digits = p.Random.Digits(9);
var sum1 = digits.Zip(CpfWeights, (d, w) => d * w)
.Sum();

Expand Down
4 changes: 2 additions & 2 deletions Source/Bogus/Extensions/ExtensionsForCanada.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public static string Sin(this Person p)
//bit verbose, but works. :)
//could be mathematically simplified.
//brute forced this one. yeah.
//
//d
//should pass basic validation, but only some
//numbers dont start with 8 etc.

Expand All @@ -38,7 +38,7 @@ public static string Sin(this Person p)
0 — Not used (Canada Revenue may assign fictitious SIN numbers beginning with zero to taxpayers who do not have SINs)
*/

var r = new Randomizer();
var r = p.Random;
//get 8 numbers
var numbers = r.Digits(8);

Expand Down
2 changes: 1 addition & 1 deletion Source/Bogus/Extensions/ExtensionsForDenmark.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public static string Cpr(this Person p)
return p.context[Key] as string;
}

var r = new Randomizer();
var r = p.Random;
var final = $"{p.DateOfBirth:ddMMyy}-{r.Replace("####")}";

p.context[Key] = final;
Expand Down
2 changes: 1 addition & 1 deletion Source/Bogus/Extensions/ExtensionsForFinland.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public static string Henkilötunnus(this Person p)
// string "0123456789ABCDEFHJKLMNPRSTUVWXY". For example, 311280888 divided by 31
// gives the remainder as 30, and since A=10, B=11, etc. ending up with Y=30.

var r = new Randomizer();
var r = p.Random;

var year = p.DateOfBirth.Year;

Expand Down
Loading

0 comments on commit da37d08

Please sign in to comment.