Skip to content

Instantly share code, notes, and snippets.

@aivascu
Created June 16, 2021 23:25
Show Gist options
  • Save aivascu/89883f34ea1a3bc0109bfa2328b55288 to your computer and use it in GitHub Desktop.
Save aivascu/89883f34ea1a3bc0109bfa2328b55288 to your computer and use it in GitHub Desktop.
Combinatorial names generator
public class CombinatorialNames : IEnumerable<FullName>
{
private readonly IEnumerable<FullName> names;
public CombinatorialNames(IEnumerable<string> firstNames, IEnumerable<string> lastNames)
{
names =
from firstName in firstNames
from lastName in lastNames
select new FullName(firstName, lastName);
}
public IEnumerator<FullName> GetEnumerator()
{
return names.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
public class LoopingSequenceGenerator<T> : ISpecimenBuilder
{
private readonly IEnumerable<T> items;
private IEnumerator<T> enumerator;
public LoopingSequenceGenerator(IEnumerable<T> items)
{
this.items = items;
enumerator = this.items.GetEnumerator();
}
public object Create(object request, ISpecimenContext context)
{
if (request is not Type type || type != typeof(T)) return new NoSpecimen();
if (!enumerator.MoveNext()) ResetEnumerator();
return enumerator.Current;
}
private void ResetEnumerator()
{
enumerator.Dispose();
enumerator = items.GetEnumerator();
enumerator.MoveNext();
}
}
public class PersonCustomization : ICustomization
{
private readonly IEnumerable<string> firstNames;
private readonly IEnumerable<string> lastNames;
public PersonCustomization(IEnumerable<string> firstNames, IEnumerable<string> lastNames)
{
this.firstNames = firstNames;
this.lastNames = lastNames;
}
public void Customize(IFixture fixture)
{
fixture.Customizations.Add(
new PersonGenerator(
new LoopingSequenceGenerator<FullName>(
new CombinatorialNames(firstNames, lastNames))));
}
}
public class PersonGenerator : ISpecimenBuilder
{
public PersonGenerator(ISpecimenBuilder nameGenerator)
{
NameGenerator = nameGenerator;
}
public ISpecimenBuilder NameGenerator { get; }
public object Create(object request, ISpecimenContext context)
{
if (request is not Type type || type != typeof(Person))
return new NoSpecimen();
var nameResult = NameGenerator.Create(typeof(FullName), context);
if (nameResult is not FullName(var firstName, var lastName))
return new NoSpecimen();
return new Person(firstName, lastName);
}
}
public record FullName(string FirstName, string LastName);
public record Person(string FirstName, string LastName);
[Fact]
public void GeneratesCombinatorialNames()
{
var firstNames = new[] {"Jake", "Lana"};
var lastNames = new[] {"Gates", "Morris"};
var fixture = new Fixture().Customize(new PersonCustomization(firstNames, lastNames));
var expected1 = new[]
{
new Person("Jake", "Gates"),
new Person("Jake", "Morris"),
new Person("Lana", "Gates")
};
var expected2 = new[]
{
new Person("Lana", "Morris"),
new Person("Jake", "Gates"),
new Person("Jake", "Morris")
};
var people1 = fixture.CreateMany<Person>();
var people2 = fixture.CreateMany<Person>();
Assert.Equal(expected1, people1.ToArray());
Assert.Equal(expected2, people2.ToArray());
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment