From 76264c44cab406ffb4cbfcfb1f52753334823bf5 Mon Sep 17 00:00:00 2001 From: Rob Moore Date: Thu, 14 May 2015 17:37:02 +0200 Subject: [PATCH 01/86] Cleaned up Builder tests Also found a bug where Set wasn't virtual so didn't work with list building --- README.md | 2 - TestStack.Dossier.Tests/BuilderBuildTests.cs | 72 --------------- ...istTests.cs => Builder_CreateListTests.cs} | 90 +++++++++---------- .../Builder_CreateNewTests.cs | 74 +++++++++++++++ .../Builders/BasicCustomerBuilder.cs | 2 +- .../Builders/StudentViewModelBuilder.cs | 29 ------ .../Factories/AllPropertiesFactoryTests.cs | 27 ++++++ .../Factories/AutoFixtureFactoryTests.cs | 27 ++++++ .../Factories/ConstructorFactoryTests.cs | 27 ++++++ .../Factories/FactoryTests.cs | 88 ------------------ .../PublicPropertySettersFactoryTests.cs | 26 ++++++ .../Stubs/Examples/MixedAccessibilityDto.cs | 25 ++++++ .../Stubs/ViewModels/InstructorViewModel.cs | 32 ------- .../TestStack.Dossier.Tests.csproj | 12 +-- .../Factories/ConstructorFactory.cs | 42 ++------- ...ory.cs => PublicPropertySettersFactory.cs} | 2 +- .../Lists/EnsureAllMethodsVirtual.cs | 2 +- TestStack.Dossier/Reflector.cs | 40 ++++++++- TestStack.Dossier/TestDataBuilder.cs | 2 +- TestStack.Dossier/TestStack.Dossier.csproj | 2 +- 20 files changed, 307 insertions(+), 316 deletions(-) delete mode 100644 TestStack.Dossier.Tests/BuilderBuildTests.cs rename TestStack.Dossier.Tests/{BuilderBuildListTests.cs => Builder_CreateListTests.cs} (52%) create mode 100644 TestStack.Dossier.Tests/Builder_CreateNewTests.cs delete mode 100644 TestStack.Dossier.Tests/Builders/StudentViewModelBuilder.cs create mode 100644 TestStack.Dossier.Tests/Factories/AllPropertiesFactoryTests.cs create mode 100644 TestStack.Dossier.Tests/Factories/AutoFixtureFactoryTests.cs create mode 100644 TestStack.Dossier.Tests/Factories/ConstructorFactoryTests.cs delete mode 100644 TestStack.Dossier.Tests/Factories/FactoryTests.cs create mode 100644 TestStack.Dossier.Tests/Factories/PublicPropertySettersFactoryTests.cs create mode 100644 TestStack.Dossier.Tests/Stubs/Examples/MixedAccessibilityDto.cs delete mode 100644 TestStack.Dossier.Tests/Stubs/ViewModels/InstructorViewModel.cs rename TestStack.Dossier/Factories/{PublicPropertiesFactory.cs => PublicPropertySettersFactory.cs} (93%) diff --git a/README.md b/README.md index f0b394d..ff2645c 100644 --- a/README.md +++ b/README.md @@ -79,8 +79,6 @@ Prior to v2.0 this library was known as NTestDataBuilder. } } -Note that overriding the BuildObject is optional. It can be useful to do this if you want full control over how your object is constructed, for example if you want to use a particular constructor. If you don't choose to override this method then Dossier will create the object for you. - 3. Use the builder in a test, e.g. var customer = new CustomerBuilder().WithFirstName("Robert").Build(); diff --git a/TestStack.Dossier.Tests/BuilderBuildTests.cs b/TestStack.Dossier.Tests/BuilderBuildTests.cs deleted file mode 100644 index 87530a8..0000000 --- a/TestStack.Dossier.Tests/BuilderBuildTests.cs +++ /dev/null @@ -1,72 +0,0 @@ -using System; -using Shouldly; -using TestStack.Dossier.Tests.Builders; -using TestStack.Dossier.Tests.Stubs.Entities; -using TestStack.Dossier.Tests.Stubs.ViewModels; -using Xunit; - -namespace TestStack.Dossier.Tests -{ - public class BuilderBuildTests - { - [Fact] - public void GivenBasicBuilder_WhenCallingBuildExplicitly_ThenReturnAnObject() - { - var builder = Builder.CreateNew(); - - var customer = builder.Build(); - - customer.ShouldBeOfType(); - } - - [Fact] - public void GivenBuilder_WhenCallingSetExplicitly_ShouldOverrideValues() - { - var builder = Builder.CreateNew() - .Set(x => x.FirstName, "Pi") - .Set(x => x.LastName, "Lanningham") - .Set(x => x.YearJoined, 2014); - - var customer = builder.Build(); - - customer.FirstName.ShouldBe("Pi"); - customer.LastName.ShouldBe("Lanningham"); - customer.YearJoined.ShouldBe(2014); - } - - [Fact] - public void GivenBasicBuilder_WhenCallingBuildImplicitly_ThenReturnAnObject() - { - Customer customer = Builder.CreateNew(); - - customer.ShouldBeOfType(); - } - - [Fact] - public void GivenBuilder_WhenCallingSetImplicitly_ShouldOverrideValues() - { - Customer customer = Builder.CreateNew() - .Set(x => x.FirstName, "Pi") - .Set(x => x.LastName, "Lanningham") - .Set(x => x.YearJoined, 2014); - - customer.FirstName.ShouldBe("Pi"); - customer.LastName.ShouldBe("Lanningham"); - customer.YearJoined.ShouldBe(2014); - } - - [Fact] - public void GivenBuilder_WhenBuildingObjectWithCtorAndPrivateSetters_ShouldSetPrivateSetters() - { - var id = Guid.NewGuid(); - InstructorViewModel instructor = Builder.CreateNew() - .Set(x => x.FirstName, "Pi") - .Set(x => x.LastName, "Lanningham") - .Set(x => x.Id, id); - - instructor.FirstName.ShouldBe("Pi"); - instructor.LastName.ShouldBe("Lanningham"); - instructor.Id.ShouldBe(id); - } - } -} \ No newline at end of file diff --git a/TestStack.Dossier.Tests/BuilderBuildListTests.cs b/TestStack.Dossier.Tests/Builder_CreateListTests.cs similarity index 52% rename from TestStack.Dossier.Tests/BuilderBuildListTests.cs rename to TestStack.Dossier.Tests/Builder_CreateListTests.cs index 458e112..5674463 100644 --- a/TestStack.Dossier.Tests/BuilderBuildListTests.cs +++ b/TestStack.Dossier.Tests/Builder_CreateListTests.cs @@ -4,15 +4,15 @@ using Shouldly; using TestStack.Dossier.DataSources.Generators; using TestStack.Dossier.Lists; -using TestStack.Dossier.Tests.Builders; using TestStack.Dossier.Tests.Stubs.ViewModels; using Xunit; namespace TestStack.Dossier.Tests { - public class BuilderBuildListTests + // ReSharper disable once InconsistentNaming + public class Builder_CreateListTests { - private DateTime _enrollmentDate = new DateTime(2004, 9, 9); + private readonly DateTime _enrollmentDate = new DateTime(2004, 9, 9); [Fact] public void GivenANormalBuilderInstance_WhenCallingIsListBuilderProxy_ThenReturnFalse() @@ -31,65 +31,65 @@ public void GivenAListBuilderProxyInstance_WhenCallingIsListBuilderProxy_ThenRet } [Fact] - public void GivenListOfBuilders_WhenCallingBuildListExplicitly_ThenAListOfEntitiesOfTheRightSizeShouldBeReturned() + public void GivenListOfBuilders_WhenCallingBuildListExplicitly_ThenAListOfObjectsOfTheRightSizeShouldBeReturned() { var builders = Builder.CreateListOfSize(5); - var entities = builders.BuildList(); + var objects = builders.BuildList(); - entities.Count.ShouldBe(5); + objects.Count.ShouldBe(5); } [Fact] - public void GivenListOfBuilders_WhenCallingBuildListImplicitly_ThenAListOfEntitiesOfTheRightSizeShouldBeReturned() + public void GivenListOfBuilders_WhenCallingBuildListImplicitly_ThenAListOfObjectsOfTheRightSizeShouldBeReturned() { - List entities = Builder.CreateListOfSize(5); + List objects = Builder.CreateListOfSize(5); - entities.Count.ShouldBe(5); + objects.Count.ShouldBe(5); } [Fact] - public void GivenListOfBuilders_WhenCallingBuildListExplicitly_ThenAListOfEntitiesOfTheRightTypeShouldBeReturned() + public void GivenListOfBuilders_WhenCallingBuildListExplicitly_ThenAListOfObjectsOfTheRightTypeShouldBeReturned() { var builders = Builder.CreateListOfSize(5); - var entities = builders.BuildList(); + var objects = builders.BuildList(); - entities.ShouldBeAssignableTo>(); + objects.ShouldBeAssignableTo>(); } [Fact] - public void GivenListOfBuilders_WhenCallingBuildListImplicitly_ThenAListOfEntitiesOfTheRightTypeShouldBeReturned() + public void GivenListOfBuilders_WhenCallingBuildListImplicitly_ThenAListOfObjectsOfTheRightTypeShouldBeReturned() { - List entities = Builder.CreateListOfSize(5); + List objects = Builder.CreateListOfSize(5); - entities.ShouldBeAssignableTo>(); + objects.ShouldBeAssignableTo>(); } [Fact] - public void GivenListOfBuilders_WhenCallingBuildListExplicitly_ThenAListOfUniqueEntitiesShouldBeReturned() + public void GivenListOfBuilders_WhenCallingBuildListExplicitly_ThenAListOfUniqueObjectsShouldBeReturned() { var builders = Builder.CreateListOfSize(5); - var entities = builders.BuildList(); + var objects = builders.BuildList(); - entities.ShouldBeUnique(); + objects.ShouldBeUnique(); } [Fact] - public void GivenListOfBuilders_WhenCallingBuildListImplicitly_ThenAListOfUniqueEntitiesShouldBeReturned() + public void GivenListOfBuilders_WhenCallingBuildListImplicitly_ThenAListOfUniqueObjectsShouldBeReturned() { - List entities = Builder.CreateListOfSize(5); + List objects = Builder.CreateListOfSize(5); - entities.ShouldBeUnique(); + objects.ShouldBeUnique(); } [Fact] - public void GivenListOfBuildersWithCustomisation_WhenBuildingEntitiesExplicitly_ThenTheCustomisationShouldTakeEffect() + public void GivenListOfBuildersWithCustomisation_WhenBuildingObjectsExplicitly_ThenTheCustomisationShouldTakeEffect() { var generator = new SequentialGenerator(0, 100); - var list = StudentViewModelBuilder.CreateListOfSize(3) - .All().With(b => b.WithFirstName(generator.Generate().ToString())); + var list = Builder.CreateListOfSize(3) + .All().With(b => b.Set(x => x.FirstName, generator.Generate().ToString())); var data = list.BuildList(); @@ -98,27 +98,27 @@ public void GivenListOfBuildersWithCustomisation_WhenBuildingEntitiesExplicitly_ } [Fact] - public void GivenListOfBuildersWithCustomisation_WhenBuildingEntitiesImplicitly_ThenTheCustomisationShouldTakeEffect() + public void GivenListOfBuildersWithCustomisation_WhenBuildingObjectsImplicitly_ThenTheCustomisationShouldTakeEffect() { var generator = new SequentialGenerator(0, 100); - List data = StudentViewModelBuilder.CreateListOfSize(3) - .All().With(b => b.WithFirstName(generator.Generate().ToString())); + List data = Builder.CreateListOfSize(3) + .All().With(b => b.Set(x => x.FirstName, generator.Generate().ToString())); data.Select(c => c.FirstName).ToArray() .ShouldBe(new[] { "0", "1", "2" }); } [Fact] - public void GivenListOfBuildersWithARangeOfCustomisationMethods_WhenBuildingEntitiesExplicitly_ThenThenTheListIsBuiltAndModifiedCorrectly() + public void GivenListOfBuildersWithComplexCustomisations_WhenBuildingObjectsExplicitly_ThenThenTheListIsBuiltAndModifiedCorrectly() { var i = 0; - var studentViewModels = StudentViewModelBuilder.CreateListOfSize(5) - .TheFirst(1).WithFirstName("First") - .TheNext(1).WithLastName("Next Last") - .TheLast(1).WithLastName("Last Last") - .ThePrevious(2).With(b => b.WithLastName("last" + (++i).ToString())) - .All().WhoEntrolledIn(_enrollmentDate) + var studentViewModels = Builder.CreateListOfSize(5) + .TheFirst(1).Set(x => x.FirstName, "First") + .TheNext(1).Set(x => x.LastName, "Next Last") + .TheLast(1).Set(x => x.LastName, "Last Last") + .ThePrevious(2).With(b => b.Set(x => x.LastName, "last" + (++i).ToString())) + .All().Set(x => x.EnrollmentDate, _enrollmentDate) .BuildList(); studentViewModels.ShouldBeAssignableTo>(); @@ -132,15 +132,15 @@ public void GivenListOfBuildersWithARangeOfCustomisationMethods_WhenBuildingEnti } [Fact] - public void GivenListOfBuildersWithARangeOfCustomisationMethods_WhenBuildingEntitiesImplicitly_ThenThenTheListIsBuiltAndModifiedCorrectly() + public void GivenListOfBuildersWithComplexCustomisations_WhenBuildingObjectsImplicitly_ThenThenTheListIsBuiltAndModifiedCorrectly() { var i = 0; - List studentViewModels = StudentViewModelBuilder.CreateListOfSize(5) - .TheFirst(1).WithFirstName("First") - .TheNext(1).WithLastName("Next Last") - .TheLast(1).WithLastName("Last Last") - .ThePrevious(2).With(b => b.WithLastName("last" + (++i).ToString())) - .All().WhoEntrolledIn(_enrollmentDate); + List studentViewModels = Builder.CreateListOfSize(5) + .TheFirst(1).Set(x => x.FirstName, "First") + .TheNext(1).Set(x => x.LastName, "Next Last") + .TheLast(1).Set(x => x.LastName, "Last Last") + .ThePrevious(2).With(b => b.Set(x => x.LastName, "last" + (++i).ToString())) + .All().Set(x => x.EnrollmentDate, _enrollmentDate); studentViewModels.ShouldBeAssignableTo>(); studentViewModels.Count.ShouldBe(5); @@ -153,17 +153,17 @@ public void GivenListOfBuildersWithARangeOfCustomisationMethods_WhenBuildingEnti } [Fact] - public void WhenBuildingEntitiesExplicitly_ThenTheAnonymousValueFixtureIsSharedAcrossBuilders() + public void WhenBuildingObjectsExplicitly_ThenTheAnonymousValueFixtureIsSharedAcrossBuilders() { - var studentViewModels = StudentViewModelBuilder.CreateListOfSize(5).BuildList(); + var studentViewModels = Builder.CreateListOfSize(5).BuildList(); studentViewModels.Select(x => x.Grade).ShouldBeUnique(); } [Fact] - public void WhenBuildingEntitiesImplicitly_ThenTheAnonymousValueFixtureIsSharedAcrossBuilders() + public void WhenBuildingObjectsImplicitly_ThenTheAnonymousValueFixtureIsSharedAcrossBuilders() { - List studentViewModels = StudentViewModelBuilder.CreateListOfSize(5); + List studentViewModels = Builder.CreateListOfSize(5); studentViewModels.Select(x => x.Grade).ShouldBeUnique(); } diff --git a/TestStack.Dossier.Tests/Builder_CreateNewTests.cs b/TestStack.Dossier.Tests/Builder_CreateNewTests.cs new file mode 100644 index 0000000..9daf39f --- /dev/null +++ b/TestStack.Dossier.Tests/Builder_CreateNewTests.cs @@ -0,0 +1,74 @@ +using System; +using Shouldly; +using TestStack.Dossier.Tests.Stubs.Entities; +using TestStack.Dossier.Tests.Stubs.Examples; +using TestStack.Dossier.Tests.Stubs.ViewModels; +using Xunit; + +namespace TestStack.Dossier.Tests +{ + // ReSharper disable once InconsistentNaming + public class Builder_CreateNewTests + { + [Fact] + public void GivenBuilder_WhenCallingBuildExplicitly_ThenReturnAnObject() + { + var builder = Builder.CreateNew(); + + var viewModel = builder.Build(); + + viewModel.ShouldBeOfType(); + } + + [Fact] + public void GivenBuilder_WhenCallingBuildImplicitly_ThenReturnAnObject() + { + StudentViewModel viewModel = Builder.CreateNew(); + + viewModel.ShouldBeOfType(); + } + + [Fact] + public void GivenBuilderWithModifications_WhenCallingBuildExplicitly_ShouldOverrideValues() + { + var builder = Builder.CreateNew() + .Set(x => x.FirstName, "Pi") + .Set(x => x.LastName, "Lanningham") + .Set(x => x.EnrollmentDate, new DateTime(2000, 1, 1)); + + var customer = builder.Build(); + + customer.FirstName.ShouldBe("Pi"); + customer.LastName.ShouldBe("Lanningham"); + customer.EnrollmentDate.ShouldBe(new DateTime(2000, 1, 1)); + } + + [Fact] + public void GivenBuilderWithModifications_WhenCallingBuildImplicitly_ShouldOverrideValues() + { + StudentViewModel customer = Builder.CreateNew() + .Set(x => x.FirstName, "Pi") + .Set(x => x.LastName, "Lanningham") + .Set(x => x.EnrollmentDate, new DateTime(2000, 1, 1)); + + customer.FirstName.ShouldBe("Pi"); + customer.LastName.ShouldBe("Lanningham"); + customer.EnrollmentDate.ShouldBe(new DateTime(2000, 1, 1)); + } + + [Fact] + public void GivenBuilder_WhenBuildingObjectWithCtorAndPrivateSetters_ShouldSetPrivateSettersByDefault() + { + MixedAccessibilityDto dto = Builder.CreateNew() + .Set(x => x.SetByCtorWithPublicSetter, "1") + .Set(x => x.SetByCtorWithPrivateSetter, "2") + .Set(x => x.NotSetByCtorWithPrivateSetter, "3") + .Set(x => x.NotSetByCtorWithPublicSetter, "4"); + + dto.SetByCtorWithPublicSetter.ShouldBe("1"); + dto.SetByCtorWithPrivateSetter.ShouldBe("2"); + dto.NotSetByCtorWithPrivateSetter.ShouldBe("3"); + dto.NotSetByCtorWithPublicSetter.ShouldBe("4"); + } + } +} \ No newline at end of file diff --git a/TestStack.Dossier.Tests/Builders/BasicCustomerBuilder.cs b/TestStack.Dossier.Tests/Builders/BasicCustomerBuilder.cs index dc6462f..4e3e80d 100644 --- a/TestStack.Dossier.Tests/Builders/BasicCustomerBuilder.cs +++ b/TestStack.Dossier.Tests/Builders/BasicCustomerBuilder.cs @@ -11,7 +11,7 @@ protected override Customer BuildObject() return new Customer("customer1", "First Name", "Last Name", 2013, CustomerClass.Normal); } - public new BasicCustomerBuilder Set(Expression> property, TValue value) + public virtual new BasicCustomerBuilder Set(Expression> property, TValue value) { return base.Set(property, value); } diff --git a/TestStack.Dossier.Tests/Builders/StudentViewModelBuilder.cs b/TestStack.Dossier.Tests/Builders/StudentViewModelBuilder.cs deleted file mode 100644 index d57a028..0000000 --- a/TestStack.Dossier.Tests/Builders/StudentViewModelBuilder.cs +++ /dev/null @@ -1,29 +0,0 @@ -using System; -using TestStack.Dossier.Factories; -using TestStack.Dossier.Tests.Stubs.ViewModels; - -namespace TestStack.Dossier.Tests.Builders -{ - public class StudentViewModelBuilder : TestDataBuilder - { - public virtual StudentViewModelBuilder WithFirstName(string firstName) - { - return Set(x => x.FirstName, firstName); - } - - public virtual StudentViewModelBuilder WithLastName(string lastName) - { - return Set(x => x.LastName, lastName); - } - - public virtual StudentViewModelBuilder WhoEntrolledIn(DateTime enrollmentDate) - { - return Set(x => x.EnrollmentDate, enrollmentDate); - } - - protected override StudentViewModel BuildObject() - { - return BuildUsing(); - } - } -} diff --git a/TestStack.Dossier.Tests/Factories/AllPropertiesFactoryTests.cs b/TestStack.Dossier.Tests/Factories/AllPropertiesFactoryTests.cs new file mode 100644 index 0000000..5e3daab --- /dev/null +++ b/TestStack.Dossier.Tests/Factories/AllPropertiesFactoryTests.cs @@ -0,0 +1,27 @@ +using System; +using Shouldly; +using TestStack.Dossier.Factories; +using TestStack.Dossier.Tests.Stubs.Examples; +using Xunit; + +namespace TestStack.Dossier.Tests.Factories +{ + public class AllPropertiesFactoryTests + { + [Fact] + public void GivenAllPropertiesFactory_WhenBuilding_ThenAllPropertiesSet() + { + MixedAccessibilityDto dto = Builder.CreateNew(new AllPropertiesFactory()); + + // ctor properties + dto.SetByCtorWithPrivateSetter.ShouldNotBe(null); + dto.SetByCtorWithPublicSetter.ShouldNotBe(null); + + // public properties + dto.NotSetByCtorWithPublicSetter.ShouldNotBe(null); + + // private properties + dto.NotSetByCtorWithPrivateSetter.ShouldNotBe(null); + } + } +} diff --git a/TestStack.Dossier.Tests/Factories/AutoFixtureFactoryTests.cs b/TestStack.Dossier.Tests/Factories/AutoFixtureFactoryTests.cs new file mode 100644 index 0000000..3f519e1 --- /dev/null +++ b/TestStack.Dossier.Tests/Factories/AutoFixtureFactoryTests.cs @@ -0,0 +1,27 @@ +using System; +using Shouldly; +using TestStack.Dossier.Factories; +using TestStack.Dossier.Tests.Stubs.Examples; +using Xunit; + +namespace TestStack.Dossier.Tests.Factories +{ + public class AutoFixtureFactoryTests + { + [Fact] + public void GivenAutoFixtureFactory_WhenBuilding_ThenOnlyConstructorAndPublicPropertiesSet() + { + MixedAccessibilityDto dto = Builder.CreateNew(new AutoFixtureFactory()); + + // ctor properties + dto.SetByCtorWithPrivateSetter.ShouldNotBe(null); + dto.SetByCtorWithPublicSetter.ShouldNotBe(null); + + // public properties + dto.NotSetByCtorWithPublicSetter.ShouldNotBe(null); + + // private properties + dto.NotSetByCtorWithPrivateSetter.ShouldBe(null); + } + } +} diff --git a/TestStack.Dossier.Tests/Factories/ConstructorFactoryTests.cs b/TestStack.Dossier.Tests/Factories/ConstructorFactoryTests.cs new file mode 100644 index 0000000..79ef3eb --- /dev/null +++ b/TestStack.Dossier.Tests/Factories/ConstructorFactoryTests.cs @@ -0,0 +1,27 @@ +using System; +using Shouldly; +using TestStack.Dossier.Factories; +using TestStack.Dossier.Tests.Stubs.Examples; +using Xunit; + +namespace TestStack.Dossier.Tests.Factories +{ + public class ConstructorFactoryTests + { + [Fact] + public void GivenConstructorFactory_WhenBuilding_ThenOnlyConstructorPropertiesSet() + { + MixedAccessibilityDto dto = Builder.CreateNew(new ConstructorFactory()); + + // ctor properties + dto.SetByCtorWithPrivateSetter.ShouldNotBe(null); + dto.SetByCtorWithPublicSetter.ShouldNotBe(null); + + // public properties + dto.NotSetByCtorWithPublicSetter.ShouldBe(null); + + // private properties + dto.NotSetByCtorWithPrivateSetter.ShouldBe(null); + } + } +} diff --git a/TestStack.Dossier.Tests/Factories/FactoryTests.cs b/TestStack.Dossier.Tests/Factories/FactoryTests.cs deleted file mode 100644 index c90dc01..0000000 --- a/TestStack.Dossier.Tests/Factories/FactoryTests.cs +++ /dev/null @@ -1,88 +0,0 @@ -using System; -using Shouldly; -using TestStack.Dossier.Factories; -using TestStack.Dossier.Tests.Stubs.Entities; -using TestStack.Dossier.Tests.Stubs.ViewModels; -using Xunit; - -namespace TestStack.Dossier.Tests.Factories -{ - public class FactoryTests - { - [Fact] - public void GivenAllPropertiesFactory_WhenBuilding_ThenAllPropertiesSet() - { - InstructorViewModel instructor = Builder.CreateNew(new AllPropertiesFactory()); - - // ctor properties - instructor.Id.ShouldNotBe(Guid.Empty); - instructor.FirstName.ShouldNotBe(null); - instructor.LastName.ShouldNotBe(null); - - // public properties - instructor.Room.ShouldNotBe(null); - instructor.NumberOfStudents.ShouldNotBe(0); - - // private properties - instructor.Subject.ShouldNotBe(null); - instructor.YearsAtSchool.ShouldNotBe(0); - } - - [Fact] - public void GivenAutoFixtureFactory_WhenBuilding_ThenOnlyConstructorAndPublicPropertiesSet() - { - InstructorViewModel instructor = Builder.CreateNew(new AutoFixtureFactory()); - - // ctor properties - instructor.Id.ShouldNotBe(Guid.Empty); - instructor.FirstName.ShouldNotBe(null); - instructor.LastName.ShouldNotBe(null); - - // public properties - instructor.Room.ShouldNotBe(null); - instructor.NumberOfStudents.ShouldNotBe(0); - - // private properties - instructor.Subject.ShouldBe(null); - instructor.YearsAtSchool.ShouldBe(0); - } - - [Fact] - public void GivenConstructorPropertiesFactory_WhenBuilding_ThenOnlyConstructorPropertiesSet() - { - InstructorViewModel instructor = Builder.CreateNew(new ConstructorFactory()); - - // ctor properties - instructor.Id.ShouldNotBe(Guid.Empty); - instructor.FirstName.ShouldNotBe(null); - instructor.LastName.ShouldNotBe(null); - - // public properties - instructor.Room.ShouldBe(null); - instructor.NumberOfStudents.ShouldBe(0); - - // private properties - instructor.Subject.ShouldBe(null); - instructor.YearsAtSchool.ShouldBe(0); - } - - [Fact] - public void GivenPublicPropertiesFactory_WhenBuilding_ThenOnlyConstructorAndPublicPropertiesSet() - { - InstructorViewModel instructor = Builder.CreateNew(new PublicPropertiesFactory()); - - // ctor properties - instructor.Id.ShouldNotBe(Guid.Empty); - instructor.FirstName.ShouldNotBe(null); - instructor.LastName.ShouldNotBe(null); - - // public properties - instructor.Room.ShouldNotBe(null); - instructor.NumberOfStudents.ShouldBeGreaterThan(0); - - // private properties - instructor.Subject.ShouldBe(null); - instructor.YearsAtSchool.ShouldBe(0); - } - } -} diff --git a/TestStack.Dossier.Tests/Factories/PublicPropertySettersFactoryTests.cs b/TestStack.Dossier.Tests/Factories/PublicPropertySettersFactoryTests.cs new file mode 100644 index 0000000..ff024fe --- /dev/null +++ b/TestStack.Dossier.Tests/Factories/PublicPropertySettersFactoryTests.cs @@ -0,0 +1,26 @@ +using Shouldly; +using TestStack.Dossier.Factories; +using TestStack.Dossier.Tests.Stubs.Examples; +using Xunit; + +namespace TestStack.Dossier.Tests.Factories +{ + public class PublicPropertySettersFactoryTests + { + [Fact] + public void GivenPublicPropertiesFactory_WhenBuilding_ThenOnlyConstructorAndPublicPropertiesSet() + { + MixedAccessibilityDto instructor = Builder.CreateNew(new PublicPropertySettersFactory()); + + // ctor properties + instructor.SetByCtorWithPrivateSetter.ShouldNotBe(null); + instructor.SetByCtorWithPublicSetter.ShouldNotBe(null); + + // public properties + instructor.NotSetByCtorWithPublicSetter.ShouldNotBe(null); + + // private properties + instructor.NotSetByCtorWithPrivateSetter.ShouldBe(null); + } + } +} diff --git a/TestStack.Dossier.Tests/Stubs/Examples/MixedAccessibilityDto.cs b/TestStack.Dossier.Tests/Stubs/Examples/MixedAccessibilityDto.cs new file mode 100644 index 0000000..e6a1782 --- /dev/null +++ b/TestStack.Dossier.Tests/Stubs/Examples/MixedAccessibilityDto.cs @@ -0,0 +1,25 @@ +using System; + +namespace TestStack.Dossier.Tests.Stubs.Examples +{ + public class MixedAccessibilityDto + { + public MixedAccessibilityDto(string setByCtorWithPrivateSetter, string setByCtorWithPublicSetter) + { + SetByCtorWithPrivateSetter = setByCtorWithPrivateSetter; + SetByCtorWithPublicSetter = setByCtorWithPublicSetter; + } + + public string SetByCtorWithPrivateSetter { get; private set; } + public string SetByCtorWithPublicSetter { get; set; } + + // ReSharper disable once UnusedAutoPropertyAccessor.Local + public string NotSetByCtorWithPrivateSetter { get; private set; } + public string NotSetByCtorWithPublicSetter { get; set; } + + public string CalculatedProperty + { + get { return SetByCtorWithPrivateSetter + " " + SetByCtorWithPublicSetter; } + } + } +} \ No newline at end of file diff --git a/TestStack.Dossier.Tests/Stubs/ViewModels/InstructorViewModel.cs b/TestStack.Dossier.Tests/Stubs/ViewModels/InstructorViewModel.cs deleted file mode 100644 index b0db3e9..0000000 --- a/TestStack.Dossier.Tests/Stubs/ViewModels/InstructorViewModel.cs +++ /dev/null @@ -1,32 +0,0 @@ -using System; - -namespace TestStack.Dossier.Tests.Stubs.ViewModels -{ - public class InstructorViewModel - { - public InstructorViewModel(Guid id, string firstName, string lastName) - { - Id = id; - FirstName = firstName; - LastName = lastName; - } - - public Guid Id { get; private set; } - - public string LastName { get; set; } - public string FirstName { get; private set; } - - public string FullName - { - get - { - return FirstName + " " + LastName; - } - } - public string Room{ get; set; } - - public string Subject{ get; private set; } - public int YearsAtSchool { get; private set; } - public int NumberOfStudents { get; set; } - } -} diff --git a/TestStack.Dossier.Tests/TestStack.Dossier.Tests.csproj b/TestStack.Dossier.Tests/TestStack.Dossier.Tests.csproj index ac4666b..c058b00 100644 --- a/TestStack.Dossier.Tests/TestStack.Dossier.Tests.csproj +++ b/TestStack.Dossier.Tests/TestStack.Dossier.Tests.csproj @@ -55,12 +55,14 @@ - - - + + - + + + + @@ -89,7 +91,7 @@ - + diff --git a/TestStack.Dossier/Factories/ConstructorFactory.cs b/TestStack.Dossier/Factories/ConstructorFactory.cs index 391aa2c..fda1efe 100644 --- a/TestStack.Dossier/Factories/ConstructorFactory.cs +++ b/TestStack.Dossier/Factories/ConstructorFactory.cs @@ -1,8 +1,5 @@ using System; using System.Linq; -using System.Linq.Expressions; -using System.Reflection; -using Ploeh.AutoFixture; namespace TestStack.Dossier.Factories { @@ -16,44 +13,17 @@ public virtual TObject BuildObject(TestDataBuilder, new() { - var longestConstructor = typeof(TObject) - .GetConstructors() - .OrderByDescending(x => x.GetParameters().Length) - .FirstOrDefault(); + var longestConstructor = Reflector.GetLongestConstructor(); - if (longestConstructor == null) throw new ObjectCreationException(); + if (longestConstructor == null) + throw new InvalidOperationException("Could not find callable constructor for class " + typeof(TObject).Name); var parameterValues = longestConstructor .GetParameters() - .Select(x => CallGetWithType(x.Name, x.ParameterType, typeof(TObject), typeof(TBuilder), builder)); + .Select(x => Reflector.GetPropertyValueFromTestDataBuilder(x.Name, x.ParameterType, typeof(TObject), typeof(TBuilder), builder)) + .ToArray(); - return (TObject)longestConstructor.Invoke(parameterValues.ToArray()); - } - - private static object CallGetWithType(string propertyName, Type propertyType, Type objectType, Type builderType, object builder) - { - // Make a Func - var expressionDelegateType = typeof(Func<,>).MakeGenericType(objectType, propertyType); - var tObjParameterType = Expression.Parameter(objectType); - - var closedGenericGetMethod = builderType - .GetMethods() - .First(IsGenericGetMethod()) - .MakeGenericMethod(propertyType); - var valueStoredInBuilder = closedGenericGetMethod.Invoke(builder, new object[] - { - Expression.Lambda( - expressionDelegateType, - Expression.Property(tObjParameterType, propertyName), - tObjParameterType) - }); - - return valueStoredInBuilder; - } - - private static Func IsGenericGetMethod() - { - return method => method.Name == "Get" && method.ContainsGenericParameters && method.GetGenericArguments().Length == 1; + return (TObject) longestConstructor.Invoke(parameterValues); } } } \ No newline at end of file diff --git a/TestStack.Dossier/Factories/PublicPropertiesFactory.cs b/TestStack.Dossier/Factories/PublicPropertySettersFactory.cs similarity index 93% rename from TestStack.Dossier/Factories/PublicPropertiesFactory.cs rename to TestStack.Dossier/Factories/PublicPropertySettersFactory.cs index 4af57f3..5c2496c 100644 --- a/TestStack.Dossier/Factories/PublicPropertiesFactory.cs +++ b/TestStack.Dossier/Factories/PublicPropertySettersFactory.cs @@ -5,7 +5,7 @@ namespace TestStack.Dossier.Factories /// /// Creates an instance of an object by setting all public properties but not private properties. /// - public class PublicPropertiesFactory : ConstructorFactory + public class PublicPropertySettersFactory : ConstructorFactory { /// public override TObject BuildObject(TestDataBuilder builder) diff --git a/TestStack.Dossier/Lists/EnsureAllMethodsVirtual.cs b/TestStack.Dossier/Lists/EnsureAllMethodsVirtual.cs index d2ad98e..88bd34b 100644 --- a/TestStack.Dossier/Lists/EnsureAllMethodsVirtual.cs +++ b/TestStack.Dossier/Lists/EnsureAllMethodsVirtual.cs @@ -13,7 +13,7 @@ public void MethodsInspected() public void NonProxyableMemberNotification(Type type, MemberInfo memberInfo) { - if (new[]{"get_Any", "set_Any", "Build", "AsProxy", "Get", "GetOrDefault", "Set", "Has", "get_ListBuilder", "set_ListBuilder", "BuildUsing", "SetFactory"}.Contains(memberInfo.Name)) + if (new[]{"get_Any", "set_Any", "Build", "AsProxy", "Get", "GetOrDefault", "Has", "get_ListBuilder", "set_ListBuilder", "BuildUsing", "SetFactory"}.Contains(memberInfo.Name)) return; throw new InvalidOperationException(string.Format("Tried to build a list with a builder who has non-virtual method. Please make {0} on type {1} virtual.", memberInfo.Name, type.Name)); } diff --git a/TestStack.Dossier/Reflector.cs b/TestStack.Dossier/Reflector.cs index 5e3f51c..80c9185 100644 --- a/TestStack.Dossier/Reflector.cs +++ b/TestStack.Dossier/Reflector.cs @@ -1,9 +1,11 @@ using System; +using System.Linq; using System.Linq.Expressions; using System.Reflection; namespace TestStack.Dossier { + // todo: Cache reflection information once per type for decent performance when building a lot of objects internal static class Reflector { public static string GetPropertyNameFor(Expression> property) @@ -22,9 +24,43 @@ public static string GetPropertyNameFor(Expression() + public static PropertyInfo[] GetSettablePropertiesFor() { - return typeof (TObject).GetProperties(BindingFlags.Public | BindingFlags.Instance); + return typeof (T).GetProperties(BindingFlags.Public | BindingFlags.Instance); + } + + public static ConstructorInfo GetLongestConstructor() + { + return typeof (T) + .GetConstructors() + .OrderByDescending(x => x.GetParameters().Length) + .FirstOrDefault(); + } + + public static object GetPropertyValueFromTestDataBuilder(string propertyName, Type propertyType, Type objectType, Type builderType, object builder) + { + var expressionDelegateType = typeof(Func<,>).MakeGenericType(objectType, propertyType); + var tObjParameterType = Expression.Parameter(objectType); + + var closedGenericGetMethod = builderType + .GetMethods() + .First(IsGenericGetMethod()) + .MakeGenericMethod(propertyType); + + var valueStoredInBuilder = closedGenericGetMethod.Invoke(builder, new object[] + { + Expression.Lambda( + expressionDelegateType, + Expression.Property(tObjParameterType, propertyName), + tObjParameterType) + }); + + return valueStoredInBuilder; + } + + private static Func IsGenericGetMethod() + { + return method => method.Name == "Get" && method.ContainsGenericParameters && method.GetGenericArguments().Length == 1; } } } diff --git a/TestStack.Dossier/TestDataBuilder.cs b/TestStack.Dossier/TestDataBuilder.cs index 5c3e891..3eff09f 100644 --- a/TestStack.Dossier/TestDataBuilder.cs +++ b/TestStack.Dossier/TestDataBuilder.cs @@ -111,7 +111,7 @@ protected virtual void AlterProxy(TObject proxy) {} /// The type of the property /// A lambda expression specifying the property to record a value for /// The value to record - public TBuilder Set(Expression> property, TValue value) + public virtual TBuilder Set(Expression> property, TValue value) { _properties[Reflector.GetPropertyNameFor(property)] = value; return this as TBuilder; diff --git a/TestStack.Dossier/TestStack.Dossier.csproj b/TestStack.Dossier/TestStack.Dossier.csproj index f00abcf..3900525 100644 --- a/TestStack.Dossier/TestStack.Dossier.csproj +++ b/TestStack.Dossier/TestStack.Dossier.csproj @@ -83,7 +83,7 @@ - + From d95116c08339170ee2455c951154a19d1609d802 Mon Sep 17 00:00:00 2001 From: Rob Moore Date: Thu, 14 May 2015 18:33:04 +0200 Subject: [PATCH 02/86] Ensuring factory overrides for Builder work --- .../Builder_CreateListTests.cs | 37 +++++++++++++++++++ .../Builder_CreateNewTests.cs | 16 ++++++++ .../AutoConstructorCustomerBuilder.cs | 2 +- ...ests.cs => CallConstructorFactoryTests.cs} | 4 +- .../TestStack.Dossier.Tests.csproj | 2 +- ...orFactory.cs => CallConstructorFactory.cs} | 6 ++- .../Factories/PublicPropertySettersFactory.cs | 2 +- TestStack.Dossier/TestStack.Dossier.csproj | 2 +- 8 files changed, 63 insertions(+), 8 deletions(-) rename TestStack.Dossier.Tests/Factories/{ConstructorFactoryTests.cs => CallConstructorFactoryTests.cs} (88%) rename TestStack.Dossier/Factories/{ConstructorFactory.cs => CallConstructorFactory.cs} (78%) diff --git a/TestStack.Dossier.Tests/Builder_CreateListTests.cs b/TestStack.Dossier.Tests/Builder_CreateListTests.cs index 5674463..b160da5 100644 --- a/TestStack.Dossier.Tests/Builder_CreateListTests.cs +++ b/TestStack.Dossier.Tests/Builder_CreateListTests.cs @@ -3,7 +3,9 @@ using System.Linq; using Shouldly; using TestStack.Dossier.DataSources.Generators; +using TestStack.Dossier.Factories; using TestStack.Dossier.Lists; +using TestStack.Dossier.Tests.Stubs.Examples; using TestStack.Dossier.Tests.Stubs.ViewModels; using Xunit; @@ -167,5 +169,40 @@ public void WhenBuildingObjectsImplicitly_ThenTheAnonymousValueFixtureIsSharedAc studentViewModels.Select(x => x.Grade).ShouldBeUnique(); } + + public void WhenBuildingObjectsWithCtorAndPrivateSetters_ShouldSetPrivateSettersByDefault() + { + var dto = Builder.CreateListOfSize(1) + .TheFirst(1) + .Set(x => x.SetByCtorWithPublicSetter, "1") + .Set(x => x.SetByCtorWithPrivateSetter, "2") + .Set(x => x.NotSetByCtorWithPrivateSetter, "3") + .Set(x => x.NotSetByCtorWithPublicSetter, "4") + .BuildList() + [0]; + + dto.SetByCtorWithPublicSetter.ShouldBe("1"); + dto.SetByCtorWithPrivateSetter.ShouldBe("2"); + dto.NotSetByCtorWithPrivateSetter.ShouldBe("3"); + dto.NotSetByCtorWithPublicSetter.ShouldBe("4"); + } + + [Fact] + public void GivenBuilderListWithFactoryOverride_WhenBuildingObjects_ShouldRespectOverriddenFactory() + { + var dto = Builder.CreateListOfSize(1, new CallConstructorFactory()) + .TheFirst(1) + .Set(x => x.SetByCtorWithPublicSetter, "1") + .Set(x => x.SetByCtorWithPrivateSetter, "2") + .Set(x => x.NotSetByCtorWithPrivateSetter, "3") + .Set(x => x.NotSetByCtorWithPublicSetter, "4") + .BuildList() + [0]; + + dto.SetByCtorWithPublicSetter.ShouldBe("1"); + dto.SetByCtorWithPrivateSetter.ShouldBe("2"); + dto.NotSetByCtorWithPrivateSetter.ShouldNotBe("3"); + dto.NotSetByCtorWithPublicSetter.ShouldNotBe("4"); + } } } \ No newline at end of file diff --git a/TestStack.Dossier.Tests/Builder_CreateNewTests.cs b/TestStack.Dossier.Tests/Builder_CreateNewTests.cs index 9daf39f..4495601 100644 --- a/TestStack.Dossier.Tests/Builder_CreateNewTests.cs +++ b/TestStack.Dossier.Tests/Builder_CreateNewTests.cs @@ -1,5 +1,6 @@ using System; using Shouldly; +using TestStack.Dossier.Factories; using TestStack.Dossier.Tests.Stubs.Entities; using TestStack.Dossier.Tests.Stubs.Examples; using TestStack.Dossier.Tests.Stubs.ViewModels; @@ -70,5 +71,20 @@ public void GivenBuilder_WhenBuildingObjectWithCtorAndPrivateSetters_ShouldSetPr dto.NotSetByCtorWithPrivateSetter.ShouldBe("3"); dto.NotSetByCtorWithPublicSetter.ShouldBe("4"); } + + [Fact] + public void GivenBuilderWithFactoryOverride_WhenBuildingObject_ShouldRespectOverriddenFactory() + { + MixedAccessibilityDto dto = Builder.CreateNew(new CallConstructorFactory()) + .Set(x => x.SetByCtorWithPublicSetter, "1") + .Set(x => x.SetByCtorWithPrivateSetter, "2") + .Set(x => x.NotSetByCtorWithPrivateSetter, "3") + .Set(x => x.NotSetByCtorWithPublicSetter, "4"); + + dto.SetByCtorWithPublicSetter.ShouldBe("1"); + dto.SetByCtorWithPrivateSetter.ShouldBe("2"); + dto.NotSetByCtorWithPrivateSetter.ShouldNotBe("3"); + dto.NotSetByCtorWithPublicSetter.ShouldNotBe("4"); + } } } \ No newline at end of file diff --git a/TestStack.Dossier.Tests/Builders/AutoConstructorCustomerBuilder.cs b/TestStack.Dossier.Tests/Builders/AutoConstructorCustomerBuilder.cs index 15d37ba..43da77f 100644 --- a/TestStack.Dossier.Tests/Builders/AutoConstructorCustomerBuilder.cs +++ b/TestStack.Dossier.Tests/Builders/AutoConstructorCustomerBuilder.cs @@ -22,7 +22,7 @@ public AutoConstructorCustomerBuilder WhoJoinedIn(int year) protected override Customer BuildObject() { - return BuildUsing(); + return BuildUsing(); } } } diff --git a/TestStack.Dossier.Tests/Factories/ConstructorFactoryTests.cs b/TestStack.Dossier.Tests/Factories/CallConstructorFactoryTests.cs similarity index 88% rename from TestStack.Dossier.Tests/Factories/ConstructorFactoryTests.cs rename to TestStack.Dossier.Tests/Factories/CallConstructorFactoryTests.cs index 79ef3eb..2b08ebf 100644 --- a/TestStack.Dossier.Tests/Factories/ConstructorFactoryTests.cs +++ b/TestStack.Dossier.Tests/Factories/CallConstructorFactoryTests.cs @@ -6,12 +6,12 @@ namespace TestStack.Dossier.Tests.Factories { - public class ConstructorFactoryTests + public class CallConstructorFactoryTests { [Fact] public void GivenConstructorFactory_WhenBuilding_ThenOnlyConstructorPropertiesSet() { - MixedAccessibilityDto dto = Builder.CreateNew(new ConstructorFactory()); + MixedAccessibilityDto dto = Builder.CreateNew(new CallConstructorFactory()); // ctor properties dto.SetByCtorWithPrivateSetter.ShouldNotBe(null); diff --git a/TestStack.Dossier.Tests/TestStack.Dossier.Tests.csproj b/TestStack.Dossier.Tests/TestStack.Dossier.Tests.csproj index c058b00..5977ee8 100644 --- a/TestStack.Dossier.Tests/TestStack.Dossier.Tests.csproj +++ b/TestStack.Dossier.Tests/TestStack.Dossier.Tests.csproj @@ -61,7 +61,7 @@ - + diff --git a/TestStack.Dossier/Factories/ConstructorFactory.cs b/TestStack.Dossier/Factories/CallConstructorFactory.cs similarity index 78% rename from TestStack.Dossier/Factories/ConstructorFactory.cs rename to TestStack.Dossier/Factories/CallConstructorFactory.cs index fda1efe..b4a7232 100644 --- a/TestStack.Dossier/Factories/ConstructorFactory.cs +++ b/TestStack.Dossier/Factories/CallConstructorFactory.cs @@ -4,9 +4,11 @@ namespace TestStack.Dossier.Factories { /// - /// Builds the object using the constructor with the most arguments. + /// Builds the object using the constructor with the most arguments using values stored in the builder that match + /// the constructor parameter name case insensitively. + /// If there is no value specified in the builder for an argument then the builder will supply an anonymous value. /// - public class ConstructorFactory : IFactory + public class CallConstructorFactory : IFactory { /// public virtual TObject BuildObject(TestDataBuilder builder) diff --git a/TestStack.Dossier/Factories/PublicPropertySettersFactory.cs b/TestStack.Dossier/Factories/PublicPropertySettersFactory.cs index 5c2496c..1362ab5 100644 --- a/TestStack.Dossier/Factories/PublicPropertySettersFactory.cs +++ b/TestStack.Dossier/Factories/PublicPropertySettersFactory.cs @@ -5,7 +5,7 @@ namespace TestStack.Dossier.Factories /// /// Creates an instance of an object by setting all public properties but not private properties. /// - public class PublicPropertySettersFactory : ConstructorFactory + public class PublicPropertySettersFactory : CallConstructorFactory { /// public override TObject BuildObject(TestDataBuilder builder) diff --git a/TestStack.Dossier/TestStack.Dossier.csproj b/TestStack.Dossier/TestStack.Dossier.csproj index 3900525..569a193 100644 --- a/TestStack.Dossier/TestStack.Dossier.csproj +++ b/TestStack.Dossier/TestStack.Dossier.csproj @@ -81,7 +81,7 @@ - + From c788cb36946e2a03a9b507d46f5d6f3229f76879 Mon Sep 17 00:00:00 2001 From: Rob Moore Date: Thu, 14 May 2015 18:34:06 +0200 Subject: [PATCH 03/86] Making it explicit that the AutoFixtureFactory does not use values from the builder --- .../Factories/AutoFixtureFactoryTests.cs | 21 ++++++++++++++----- .../Factories/AutoFixtureFactory.cs | 2 +- 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/TestStack.Dossier.Tests/Factories/AutoFixtureFactoryTests.cs b/TestStack.Dossier.Tests/Factories/AutoFixtureFactoryTests.cs index 3f519e1..0d7448a 100644 --- a/TestStack.Dossier.Tests/Factories/AutoFixtureFactoryTests.cs +++ b/TestStack.Dossier.Tests/Factories/AutoFixtureFactoryTests.cs @@ -13,15 +13,26 @@ public void GivenAutoFixtureFactory_WhenBuilding_ThenOnlyConstructorAndPublicPro { MixedAccessibilityDto dto = Builder.CreateNew(new AutoFixtureFactory()); - // ctor properties dto.SetByCtorWithPrivateSetter.ShouldNotBe(null); dto.SetByCtorWithPublicSetter.ShouldNotBe(null); - - // public properties + dto.NotSetByCtorWithPrivateSetter.ShouldBe(null); dto.NotSetByCtorWithPublicSetter.ShouldNotBe(null); + } - // private properties - dto.NotSetByCtorWithPrivateSetter.ShouldBe(null); + [Fact] + public void GivenAutoFixtureFactoryAgainstBuilderWithModifications_WhenBuilding_ThenNoCustomisationsAreUsed() + { + MixedAccessibilityDto dto = Builder + .CreateNew(new AutoFixtureFactory()) + .Set(x => x.SetByCtorWithPrivateSetter, "1") + .Set(x => x.SetByCtorWithPublicSetter, "2") + .Set(x => x.NotSetByCtorWithPrivateSetter, "3") + .Set(x => x.NotSetByCtorWithPublicSetter, "4"); + + dto.SetByCtorWithPrivateSetter.ShouldNotBe("1"); + dto.SetByCtorWithPublicSetter.ShouldNotBe("2"); + dto.NotSetByCtorWithPrivateSetter.ShouldNotBe("3"); + dto.NotSetByCtorWithPublicSetter.ShouldNotBe("4"); } } } diff --git a/TestStack.Dossier/Factories/AutoFixtureFactory.cs b/TestStack.Dossier/Factories/AutoFixtureFactory.cs index 831c65b..8c8b4ec 100644 --- a/TestStack.Dossier/Factories/AutoFixtureFactory.cs +++ b/TestStack.Dossier/Factories/AutoFixtureFactory.cs @@ -3,7 +3,7 @@ namespace TestStack.Dossier.Factories { /// - /// Creates an instance of an object with AutoFixture. + /// Creates an instance of an object with AutoFixture - any values set in your builder will NOT be used to construct the object. /// public class AutoFixtureFactory : IFactory { From f26d418c3fe8863e2038b919a4c95311c5bdd800 Mon Sep 17 00:00:00 2001 From: Rob Moore Date: Thu, 14 May 2015 18:35:38 +0200 Subject: [PATCH 04/86] Moved example builders and objects to TestHelpers so the root namespace of the tests isn't cluttered with test and non-test namespaces / files --- TestStack.Dossier.Tests/AsProxyTests.cs | 2 +- TestStack.Dossier.Tests/BuildListTests.cs | 4 ++-- TestStack.Dossier.Tests/BuildTests.cs | 4 ++-- .../Builder_CreateListTests.cs | 4 ++-- .../Builder_CreateNewTests.cs | 5 ++--- .../Factories/AllPropertiesFactoryTests.cs | 2 +- .../Factories/AutoFixtureFactoryTests.cs | 2 +- .../Factories/CallConstructorFactoryTests.cs | 2 +- .../PublicPropertySettersFactoryTests.cs | 2 +- TestStack.Dossier.Tests/GetAnonymousTests.cs | 2 +- TestStack.Dossier.Tests/GetOrDefaultTests.cs | 2 +- TestStack.Dossier.Tests/GetSetTests.cs | 2 +- TestStack.Dossier.Tests/ProxyBuilderTests.cs | 2 +- .../Stubs/ViewModels/Grade.cs | 7 ------- .../AutoConstructorCustomerBuilder.cs | 4 ++-- .../Builders/BasicCustomerBuilder.cs | 4 ++-- .../Builders/CustomerBuilder.cs | 4 ++-- .../Builders/ProxyAlteringCustomerBuilder.cs | 4 ++-- .../Objects}/Entities/Company.cs | 2 +- .../Objects}/Entities/Customer.cs | 2 +- .../Objects}/Entities/CustomerClass.cs | 2 +- .../Examples/MixedAccessibilityDto.cs | 4 +--- .../TestHelpers/Objects/ViewModels/Grade.cs | 7 +++++++ .../Objects}/ViewModels/StudentViewModel.cs | 2 +- .../TestStack.Dossier.Tests.csproj | 20 +++++++++---------- 25 files changed, 47 insertions(+), 50 deletions(-) delete mode 100644 TestStack.Dossier.Tests/Stubs/ViewModels/Grade.cs rename TestStack.Dossier.Tests/{ => TestHelpers}/Builders/AutoConstructorCustomerBuilder.cs (86%) rename TestStack.Dossier.Tests/{ => TestHelpers}/Builders/BasicCustomerBuilder.cs (81%) rename TestStack.Dossier.Tests/{ => TestHelpers}/Builders/CustomerBuilder.cs (87%) rename TestStack.Dossier.Tests/{ => TestHelpers}/Builders/ProxyAlteringCustomerBuilder.cs (84%) rename TestStack.Dossier.Tests/{Stubs => TestHelpers/Objects}/Entities/Company.cs (83%) rename TestStack.Dossier.Tests/{Stubs => TestHelpers/Objects}/Entities/Customer.cs (95%) rename TestStack.Dossier.Tests/{Stubs => TestHelpers/Objects}/Entities/CustomerClass.cs (65%) rename TestStack.Dossier.Tests/{Stubs => TestHelpers/Objects}/Examples/MixedAccessibilityDto.cs (92%) create mode 100644 TestStack.Dossier.Tests/TestHelpers/Objects/ViewModels/Grade.cs rename TestStack.Dossier.Tests/{Stubs => TestHelpers/Objects}/ViewModels/StudentViewModel.cs (93%) diff --git a/TestStack.Dossier.Tests/AsProxyTests.cs b/TestStack.Dossier.Tests/AsProxyTests.cs index ddf8036..4711568 100644 --- a/TestStack.Dossier.Tests/AsProxyTests.cs +++ b/TestStack.Dossier.Tests/AsProxyTests.cs @@ -1,7 +1,7 @@ using System; using NSubstitute; using Shouldly; -using TestStack.Dossier.Tests.Builders; +using TestStack.Dossier.Tests.TestHelpers.Builders; using Xunit; namespace TestStack.Dossier.Tests diff --git a/TestStack.Dossier.Tests/BuildListTests.cs b/TestStack.Dossier.Tests/BuildListTests.cs index e2651b2..5e0e15b 100644 --- a/TestStack.Dossier.Tests/BuildListTests.cs +++ b/TestStack.Dossier.Tests/BuildListTests.cs @@ -3,8 +3,8 @@ using Shouldly; using TestStack.Dossier.DataSources.Generators; using TestStack.Dossier.Lists; -using TestStack.Dossier.Tests.Builders; -using TestStack.Dossier.Tests.Stubs.Entities; +using TestStack.Dossier.Tests.TestHelpers.Builders; +using TestStack.Dossier.Tests.TestHelpers.Objects.Entities; using Xunit; namespace TestStack.Dossier.Tests diff --git a/TestStack.Dossier.Tests/BuildTests.cs b/TestStack.Dossier.Tests/BuildTests.cs index f6088aa..9c6d1d4 100644 --- a/TestStack.Dossier.Tests/BuildTests.cs +++ b/TestStack.Dossier.Tests/BuildTests.cs @@ -1,6 +1,6 @@ using Shouldly; -using TestStack.Dossier.Tests.Builders; -using TestStack.Dossier.Tests.Stubs.Entities; +using TestStack.Dossier.Tests.TestHelpers.Builders; +using TestStack.Dossier.Tests.TestHelpers.Objects.Entities; using Xunit; namespace TestStack.Dossier.Tests diff --git a/TestStack.Dossier.Tests/Builder_CreateListTests.cs b/TestStack.Dossier.Tests/Builder_CreateListTests.cs index b160da5..5ad8c51 100644 --- a/TestStack.Dossier.Tests/Builder_CreateListTests.cs +++ b/TestStack.Dossier.Tests/Builder_CreateListTests.cs @@ -5,8 +5,8 @@ using TestStack.Dossier.DataSources.Generators; using TestStack.Dossier.Factories; using TestStack.Dossier.Lists; -using TestStack.Dossier.Tests.Stubs.Examples; -using TestStack.Dossier.Tests.Stubs.ViewModels; +using TestStack.Dossier.Tests.TestHelpers.Objects.Examples; +using TestStack.Dossier.Tests.TestHelpers.Objects.ViewModels; using Xunit; namespace TestStack.Dossier.Tests diff --git a/TestStack.Dossier.Tests/Builder_CreateNewTests.cs b/TestStack.Dossier.Tests/Builder_CreateNewTests.cs index 4495601..24a3b4f 100644 --- a/TestStack.Dossier.Tests/Builder_CreateNewTests.cs +++ b/TestStack.Dossier.Tests/Builder_CreateNewTests.cs @@ -1,9 +1,8 @@ using System; using Shouldly; using TestStack.Dossier.Factories; -using TestStack.Dossier.Tests.Stubs.Entities; -using TestStack.Dossier.Tests.Stubs.Examples; -using TestStack.Dossier.Tests.Stubs.ViewModels; +using TestStack.Dossier.Tests.TestHelpers.Objects.Examples; +using TestStack.Dossier.Tests.TestHelpers.Objects.ViewModels; using Xunit; namespace TestStack.Dossier.Tests diff --git a/TestStack.Dossier.Tests/Factories/AllPropertiesFactoryTests.cs b/TestStack.Dossier.Tests/Factories/AllPropertiesFactoryTests.cs index 5e3daab..322154e 100644 --- a/TestStack.Dossier.Tests/Factories/AllPropertiesFactoryTests.cs +++ b/TestStack.Dossier.Tests/Factories/AllPropertiesFactoryTests.cs @@ -1,7 +1,7 @@ using System; using Shouldly; using TestStack.Dossier.Factories; -using TestStack.Dossier.Tests.Stubs.Examples; +using TestStack.Dossier.Tests.TestHelpers.Objects.Examples; using Xunit; namespace TestStack.Dossier.Tests.Factories diff --git a/TestStack.Dossier.Tests/Factories/AutoFixtureFactoryTests.cs b/TestStack.Dossier.Tests/Factories/AutoFixtureFactoryTests.cs index 0d7448a..c6c15e5 100644 --- a/TestStack.Dossier.Tests/Factories/AutoFixtureFactoryTests.cs +++ b/TestStack.Dossier.Tests/Factories/AutoFixtureFactoryTests.cs @@ -1,7 +1,7 @@ using System; using Shouldly; using TestStack.Dossier.Factories; -using TestStack.Dossier.Tests.Stubs.Examples; +using TestStack.Dossier.Tests.TestHelpers.Objects.Examples; using Xunit; namespace TestStack.Dossier.Tests.Factories diff --git a/TestStack.Dossier.Tests/Factories/CallConstructorFactoryTests.cs b/TestStack.Dossier.Tests/Factories/CallConstructorFactoryTests.cs index 2b08ebf..0bf0f4e 100644 --- a/TestStack.Dossier.Tests/Factories/CallConstructorFactoryTests.cs +++ b/TestStack.Dossier.Tests/Factories/CallConstructorFactoryTests.cs @@ -1,7 +1,7 @@ using System; using Shouldly; using TestStack.Dossier.Factories; -using TestStack.Dossier.Tests.Stubs.Examples; +using TestStack.Dossier.Tests.TestHelpers.Objects.Examples; using Xunit; namespace TestStack.Dossier.Tests.Factories diff --git a/TestStack.Dossier.Tests/Factories/PublicPropertySettersFactoryTests.cs b/TestStack.Dossier.Tests/Factories/PublicPropertySettersFactoryTests.cs index ff024fe..5598a64 100644 --- a/TestStack.Dossier.Tests/Factories/PublicPropertySettersFactoryTests.cs +++ b/TestStack.Dossier.Tests/Factories/PublicPropertySettersFactoryTests.cs @@ -1,6 +1,6 @@ using Shouldly; using TestStack.Dossier.Factories; -using TestStack.Dossier.Tests.Stubs.Examples; +using TestStack.Dossier.Tests.TestHelpers.Objects.Examples; using Xunit; namespace TestStack.Dossier.Tests.Factories diff --git a/TestStack.Dossier.Tests/GetAnonymousTests.cs b/TestStack.Dossier.Tests/GetAnonymousTests.cs index c415c73..b5a0ddf 100644 --- a/TestStack.Dossier.Tests/GetAnonymousTests.cs +++ b/TestStack.Dossier.Tests/GetAnonymousTests.cs @@ -2,8 +2,8 @@ using Shouldly; using TestStack.Dossier.DataSources.Person; using TestStack.Dossier.Lists; -using TestStack.Dossier.Tests.Builders; using TestStack.Dossier.Tests.TestHelpers; +using TestStack.Dossier.Tests.TestHelpers.Builders; using Xunit; namespace TestStack.Dossier.Tests diff --git a/TestStack.Dossier.Tests/GetOrDefaultTests.cs b/TestStack.Dossier.Tests/GetOrDefaultTests.cs index 71713a1..5bfbd6b 100644 --- a/TestStack.Dossier.Tests/GetOrDefaultTests.cs +++ b/TestStack.Dossier.Tests/GetOrDefaultTests.cs @@ -1,5 +1,5 @@ using Shouldly; -using TestStack.Dossier.Tests.Builders; +using TestStack.Dossier.Tests.TestHelpers.Builders; using Xunit; namespace TestStack.Dossier.Tests diff --git a/TestStack.Dossier.Tests/GetSetTests.cs b/TestStack.Dossier.Tests/GetSetTests.cs index 4addf96..2362f91 100644 --- a/TestStack.Dossier.Tests/GetSetTests.cs +++ b/TestStack.Dossier.Tests/GetSetTests.cs @@ -1,6 +1,6 @@ using System; using Shouldly; -using TestStack.Dossier.Tests.Builders; +using TestStack.Dossier.Tests.TestHelpers.Builders; using Xunit; namespace TestStack.Dossier.Tests diff --git a/TestStack.Dossier.Tests/ProxyBuilderTests.cs b/TestStack.Dossier.Tests/ProxyBuilderTests.cs index ae9aef8..e62b2a5 100644 --- a/TestStack.Dossier.Tests/ProxyBuilderTests.cs +++ b/TestStack.Dossier.Tests/ProxyBuilderTests.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; using NSubstitute; using Shouldly; -using TestStack.Dossier.Tests.Stubs.Entities; +using TestStack.Dossier.Tests.TestHelpers.Objects.Entities; using Xunit; namespace TestStack.Dossier.Tests diff --git a/TestStack.Dossier.Tests/Stubs/ViewModels/Grade.cs b/TestStack.Dossier.Tests/Stubs/ViewModels/Grade.cs deleted file mode 100644 index 8598bb2..0000000 --- a/TestStack.Dossier.Tests/Stubs/ViewModels/Grade.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace TestStack.Dossier.Tests.Stubs.ViewModels -{ - public enum Grade - { - A, B, C, D, F - } -} \ No newline at end of file diff --git a/TestStack.Dossier.Tests/Builders/AutoConstructorCustomerBuilder.cs b/TestStack.Dossier.Tests/TestHelpers/Builders/AutoConstructorCustomerBuilder.cs similarity index 86% rename from TestStack.Dossier.Tests/Builders/AutoConstructorCustomerBuilder.cs rename to TestStack.Dossier.Tests/TestHelpers/Builders/AutoConstructorCustomerBuilder.cs index 43da77f..b413c49 100644 --- a/TestStack.Dossier.Tests/Builders/AutoConstructorCustomerBuilder.cs +++ b/TestStack.Dossier.Tests/TestHelpers/Builders/AutoConstructorCustomerBuilder.cs @@ -1,7 +1,7 @@ using TestStack.Dossier.Factories; -using TestStack.Dossier.Tests.Stubs.Entities; +using TestStack.Dossier.Tests.TestHelpers.Objects.Entities; -namespace TestStack.Dossier.Tests.Builders +namespace TestStack.Dossier.Tests.TestHelpers.Builders { class AutoConstructorCustomerBuilder : TestDataBuilder { diff --git a/TestStack.Dossier.Tests/Builders/BasicCustomerBuilder.cs b/TestStack.Dossier.Tests/TestHelpers/Builders/BasicCustomerBuilder.cs similarity index 81% rename from TestStack.Dossier.Tests/Builders/BasicCustomerBuilder.cs rename to TestStack.Dossier.Tests/TestHelpers/Builders/BasicCustomerBuilder.cs index 4e3e80d..20e7e0f 100644 --- a/TestStack.Dossier.Tests/Builders/BasicCustomerBuilder.cs +++ b/TestStack.Dossier.Tests/TestHelpers/Builders/BasicCustomerBuilder.cs @@ -1,8 +1,8 @@ using System; using System.Linq.Expressions; -using TestStack.Dossier.Tests.Stubs.Entities; +using TestStack.Dossier.Tests.TestHelpers.Objects.Entities; -namespace TestStack.Dossier.Tests.Builders +namespace TestStack.Dossier.Tests.TestHelpers.Builders { public class BasicCustomerBuilder : TestDataBuilder { diff --git a/TestStack.Dossier.Tests/Builders/CustomerBuilder.cs b/TestStack.Dossier.Tests/TestHelpers/Builders/CustomerBuilder.cs similarity index 87% rename from TestStack.Dossier.Tests/Builders/CustomerBuilder.cs rename to TestStack.Dossier.Tests/TestHelpers/Builders/CustomerBuilder.cs index 319a57c..1da6a0e 100644 --- a/TestStack.Dossier.Tests/Builders/CustomerBuilder.cs +++ b/TestStack.Dossier.Tests/TestHelpers/Builders/CustomerBuilder.cs @@ -1,6 +1,6 @@ -using TestStack.Dossier.Tests.Stubs.Entities; +using TestStack.Dossier.Tests.TestHelpers.Objects.Entities; -namespace TestStack.Dossier.Tests.Builders +namespace TestStack.Dossier.Tests.TestHelpers.Builders { public class CustomerBuilder : TestDataBuilder { diff --git a/TestStack.Dossier.Tests/Builders/ProxyAlteringCustomerBuilder.cs b/TestStack.Dossier.Tests/TestHelpers/Builders/ProxyAlteringCustomerBuilder.cs similarity index 84% rename from TestStack.Dossier.Tests/Builders/ProxyAlteringCustomerBuilder.cs rename to TestStack.Dossier.Tests/TestHelpers/Builders/ProxyAlteringCustomerBuilder.cs index 2419fdf..97a156e 100644 --- a/TestStack.Dossier.Tests/Builders/ProxyAlteringCustomerBuilder.cs +++ b/TestStack.Dossier.Tests/TestHelpers/Builders/ProxyAlteringCustomerBuilder.cs @@ -1,8 +1,8 @@ using System; using NSubstitute; -using TestStack.Dossier.Tests.Stubs.Entities; +using TestStack.Dossier.Tests.TestHelpers.Objects.Entities; -namespace TestStack.Dossier.Tests.Builders +namespace TestStack.Dossier.Tests.TestHelpers.Builders { class ProxyAlteringCustomerBuilder : TestDataBuilder { diff --git a/TestStack.Dossier.Tests/Stubs/Entities/Company.cs b/TestStack.Dossier.Tests/TestHelpers/Objects/Entities/Company.cs similarity index 83% rename from TestStack.Dossier.Tests/Stubs/Entities/Company.cs rename to TestStack.Dossier.Tests/TestHelpers/Objects/Entities/Company.cs index 2635100..df96a43 100644 --- a/TestStack.Dossier.Tests/Stubs/Entities/Company.cs +++ b/TestStack.Dossier.Tests/TestHelpers/Objects/Entities/Company.cs @@ -1,4 +1,4 @@ -namespace TestStack.Dossier.Tests.Stubs.Entities +namespace TestStack.Dossier.Tests.TestHelpers.Objects.Entities { public class Company { diff --git a/TestStack.Dossier.Tests/Stubs/Entities/Customer.cs b/TestStack.Dossier.Tests/TestHelpers/Objects/Entities/Customer.cs similarity index 95% rename from TestStack.Dossier.Tests/Stubs/Entities/Customer.cs rename to TestStack.Dossier.Tests/TestHelpers/Objects/Entities/Customer.cs index 0e71270..3c943ea 100644 --- a/TestStack.Dossier.Tests/Stubs/Entities/Customer.cs +++ b/TestStack.Dossier.Tests/TestHelpers/Objects/Entities/Customer.cs @@ -1,6 +1,6 @@ using System; -namespace TestStack.Dossier.Tests.Stubs.Entities +namespace TestStack.Dossier.Tests.TestHelpers.Objects.Entities { public class Customer { diff --git a/TestStack.Dossier.Tests/Stubs/Entities/CustomerClass.cs b/TestStack.Dossier.Tests/TestHelpers/Objects/Entities/CustomerClass.cs similarity index 65% rename from TestStack.Dossier.Tests/Stubs/Entities/CustomerClass.cs rename to TestStack.Dossier.Tests/TestHelpers/Objects/Entities/CustomerClass.cs index dd79d7b..aa3a080 100644 --- a/TestStack.Dossier.Tests/Stubs/Entities/CustomerClass.cs +++ b/TestStack.Dossier.Tests/TestHelpers/Objects/Entities/CustomerClass.cs @@ -1,4 +1,4 @@ -namespace TestStack.Dossier.Tests.Stubs.Entities +namespace TestStack.Dossier.Tests.TestHelpers.Objects.Entities { public enum CustomerClass { diff --git a/TestStack.Dossier.Tests/Stubs/Examples/MixedAccessibilityDto.cs b/TestStack.Dossier.Tests/TestHelpers/Objects/Examples/MixedAccessibilityDto.cs similarity index 92% rename from TestStack.Dossier.Tests/Stubs/Examples/MixedAccessibilityDto.cs rename to TestStack.Dossier.Tests/TestHelpers/Objects/Examples/MixedAccessibilityDto.cs index e6a1782..fc1e8e4 100644 --- a/TestStack.Dossier.Tests/Stubs/Examples/MixedAccessibilityDto.cs +++ b/TestStack.Dossier.Tests/TestHelpers/Objects/Examples/MixedAccessibilityDto.cs @@ -1,6 +1,4 @@ -using System; - -namespace TestStack.Dossier.Tests.Stubs.Examples +namespace TestStack.Dossier.Tests.TestHelpers.Objects.Examples { public class MixedAccessibilityDto { diff --git a/TestStack.Dossier.Tests/TestHelpers/Objects/ViewModels/Grade.cs b/TestStack.Dossier.Tests/TestHelpers/Objects/ViewModels/Grade.cs new file mode 100644 index 0000000..2594136 --- /dev/null +++ b/TestStack.Dossier.Tests/TestHelpers/Objects/ViewModels/Grade.cs @@ -0,0 +1,7 @@ +namespace TestStack.Dossier.Tests.TestHelpers.Objects.ViewModels +{ + public enum Grade + { + A, B, C, D, F + } +} \ No newline at end of file diff --git a/TestStack.Dossier.Tests/Stubs/ViewModels/StudentViewModel.cs b/TestStack.Dossier.Tests/TestHelpers/Objects/ViewModels/StudentViewModel.cs similarity index 93% rename from TestStack.Dossier.Tests/Stubs/ViewModels/StudentViewModel.cs rename to TestStack.Dossier.Tests/TestHelpers/Objects/ViewModels/StudentViewModel.cs index 674a844..9ba1f94 100644 --- a/TestStack.Dossier.Tests/Stubs/ViewModels/StudentViewModel.cs +++ b/TestStack.Dossier.Tests/TestHelpers/Objects/ViewModels/StudentViewModel.cs @@ -1,7 +1,7 @@ using System; using System.ComponentModel.DataAnnotations; -namespace TestStack.Dossier.Tests.Stubs.ViewModels +namespace TestStack.Dossier.Tests.TestHelpers.Objects.ViewModels { public class StudentViewModel { diff --git a/TestStack.Dossier.Tests/TestStack.Dossier.Tests.csproj b/TestStack.Dossier.Tests/TestStack.Dossier.Tests.csproj index 5977ee8..4b10acb 100644 --- a/TestStack.Dossier.Tests/TestStack.Dossier.Tests.csproj +++ b/TestStack.Dossier.Tests/TestStack.Dossier.Tests.csproj @@ -57,15 +57,15 @@ - + - - - + + + @@ -81,18 +81,18 @@ - - - + + + - - - + + + From 68810c97c6c4c982d3e3482a0f9520fb0a2e8012 Mon Sep 17 00:00:00 2001 From: Rob Moore Date: Thu, 14 May 2015 18:40:52 +0200 Subject: [PATCH 05/86] Adding a ctor-set readonly property to the MixedAccessibilityDto --- .../Factories/AllPropertiesFactoryTests.cs | 8 ++------ .../Factories/AutoFixtureFactoryTests.cs | 3 +++ .../Factories/CallConstructorFactoryTests.cs | 8 ++------ .../PublicPropertySettersFactoryTests.cs | 16 ++++++---------- .../Objects/Examples/MixedAccessibilityDto.cs | 9 ++++++--- 5 files changed, 19 insertions(+), 25 deletions(-) diff --git a/TestStack.Dossier.Tests/Factories/AllPropertiesFactoryTests.cs b/TestStack.Dossier.Tests/Factories/AllPropertiesFactoryTests.cs index 322154e..940c4e2 100644 --- a/TestStack.Dossier.Tests/Factories/AllPropertiesFactoryTests.cs +++ b/TestStack.Dossier.Tests/Factories/AllPropertiesFactoryTests.cs @@ -13,15 +13,11 @@ public void GivenAllPropertiesFactory_WhenBuilding_ThenAllPropertiesSet() { MixedAccessibilityDto dto = Builder.CreateNew(new AllPropertiesFactory()); - // ctor properties + dto.SetByCtorNoPropertySetter.ShouldNotBe(null); dto.SetByCtorWithPrivateSetter.ShouldNotBe(null); dto.SetByCtorWithPublicSetter.ShouldNotBe(null); - - // public properties - dto.NotSetByCtorWithPublicSetter.ShouldNotBe(null); - - // private properties dto.NotSetByCtorWithPrivateSetter.ShouldNotBe(null); + dto.NotSetByCtorWithPublicSetter.ShouldNotBe(null); } } } diff --git a/TestStack.Dossier.Tests/Factories/AutoFixtureFactoryTests.cs b/TestStack.Dossier.Tests/Factories/AutoFixtureFactoryTests.cs index c6c15e5..d018ff5 100644 --- a/TestStack.Dossier.Tests/Factories/AutoFixtureFactoryTests.cs +++ b/TestStack.Dossier.Tests/Factories/AutoFixtureFactoryTests.cs @@ -13,6 +13,7 @@ public void GivenAutoFixtureFactory_WhenBuilding_ThenOnlyConstructorAndPublicPro { MixedAccessibilityDto dto = Builder.CreateNew(new AutoFixtureFactory()); + dto.SetByCtorNoPropertySetter.ShouldNotBe(null); dto.SetByCtorWithPrivateSetter.ShouldNotBe(null); dto.SetByCtorWithPublicSetter.ShouldNotBe(null); dto.NotSetByCtorWithPrivateSetter.ShouldBe(null); @@ -24,11 +25,13 @@ public void GivenAutoFixtureFactoryAgainstBuilderWithModifications_WhenBuilding_ { MixedAccessibilityDto dto = Builder .CreateNew(new AutoFixtureFactory()) + .Set(x => x.SetByCtorNoPropertySetter, "0") .Set(x => x.SetByCtorWithPrivateSetter, "1") .Set(x => x.SetByCtorWithPublicSetter, "2") .Set(x => x.NotSetByCtorWithPrivateSetter, "3") .Set(x => x.NotSetByCtorWithPublicSetter, "4"); + dto.SetByCtorNoPropertySetter.ShouldNotBe("0"); dto.SetByCtorWithPrivateSetter.ShouldNotBe("1"); dto.SetByCtorWithPublicSetter.ShouldNotBe("2"); dto.NotSetByCtorWithPrivateSetter.ShouldNotBe("3"); diff --git a/TestStack.Dossier.Tests/Factories/CallConstructorFactoryTests.cs b/TestStack.Dossier.Tests/Factories/CallConstructorFactoryTests.cs index 0bf0f4e..97ae9a6 100644 --- a/TestStack.Dossier.Tests/Factories/CallConstructorFactoryTests.cs +++ b/TestStack.Dossier.Tests/Factories/CallConstructorFactoryTests.cs @@ -13,15 +13,11 @@ public void GivenConstructorFactory_WhenBuilding_ThenOnlyConstructorPropertiesSe { MixedAccessibilityDto dto = Builder.CreateNew(new CallConstructorFactory()); - // ctor properties + dto.SetByCtorNoPropertySetter.ShouldNotBe(null); dto.SetByCtorWithPrivateSetter.ShouldNotBe(null); dto.SetByCtorWithPublicSetter.ShouldNotBe(null); - - // public properties - dto.NotSetByCtorWithPublicSetter.ShouldBe(null); - - // private properties dto.NotSetByCtorWithPrivateSetter.ShouldBe(null); + dto.NotSetByCtorWithPublicSetter.ShouldBe(null); } } } diff --git a/TestStack.Dossier.Tests/Factories/PublicPropertySettersFactoryTests.cs b/TestStack.Dossier.Tests/Factories/PublicPropertySettersFactoryTests.cs index 5598a64..794b0e4 100644 --- a/TestStack.Dossier.Tests/Factories/PublicPropertySettersFactoryTests.cs +++ b/TestStack.Dossier.Tests/Factories/PublicPropertySettersFactoryTests.cs @@ -10,17 +10,13 @@ public class PublicPropertySettersFactoryTests [Fact] public void GivenPublicPropertiesFactory_WhenBuilding_ThenOnlyConstructorAndPublicPropertiesSet() { - MixedAccessibilityDto instructor = Builder.CreateNew(new PublicPropertySettersFactory()); + MixedAccessibilityDto dto = Builder.CreateNew(new PublicPropertySettersFactory()); - // ctor properties - instructor.SetByCtorWithPrivateSetter.ShouldNotBe(null); - instructor.SetByCtorWithPublicSetter.ShouldNotBe(null); - - // public properties - instructor.NotSetByCtorWithPublicSetter.ShouldNotBe(null); - - // private properties - instructor.NotSetByCtorWithPrivateSetter.ShouldBe(null); + dto.SetByCtorNoPropertySetter.ShouldNotBe(null); + dto.SetByCtorWithPrivateSetter.ShouldNotBe(null); + dto.SetByCtorWithPublicSetter.ShouldNotBe(null); + dto.NotSetByCtorWithPublicSetter.ShouldNotBe(null); + dto.NotSetByCtorWithPrivateSetter.ShouldBe(null); } } } diff --git a/TestStack.Dossier.Tests/TestHelpers/Objects/Examples/MixedAccessibilityDto.cs b/TestStack.Dossier.Tests/TestHelpers/Objects/Examples/MixedAccessibilityDto.cs index fc1e8e4..99cb17a 100644 --- a/TestStack.Dossier.Tests/TestHelpers/Objects/Examples/MixedAccessibilityDto.cs +++ b/TestStack.Dossier.Tests/TestHelpers/Objects/Examples/MixedAccessibilityDto.cs @@ -2,10 +2,13 @@ { public class MixedAccessibilityDto { - public MixedAccessibilityDto(string setByCtorWithPrivateSetter, string setByCtorWithPublicSetter) + private readonly string _setByCtorNoPropertySetter; + + public MixedAccessibilityDto(string setByCtorWithPrivateSetter, string setByCtorWithPublicSetter, string setByCtorNoPropertySetter) { SetByCtorWithPrivateSetter = setByCtorWithPrivateSetter; SetByCtorWithPublicSetter = setByCtorWithPublicSetter; + _setByCtorNoPropertySetter = setByCtorNoPropertySetter; } public string SetByCtorWithPrivateSetter { get; private set; } @@ -15,9 +18,9 @@ public MixedAccessibilityDto(string setByCtorWithPrivateSetter, string setByCtor public string NotSetByCtorWithPrivateSetter { get; private set; } public string NotSetByCtorWithPublicSetter { get; set; } - public string CalculatedProperty + public string SetByCtorNoPropertySetter { - get { return SetByCtorWithPrivateSetter + " " + SetByCtorWithPublicSetter; } + get { return _setByCtorNoPropertySetter; } } } } \ No newline at end of file From 9266739c9b38c109d146a042e12109309bd71171 Mon Sep 17 00:00:00 2001 From: Rob Moore Date: Thu, 14 May 2015 18:51:55 +0200 Subject: [PATCH 06/86] Added tests to ensure the correct behaviour for the factories with respect to using builder values Changed the AllPropertiesFactory to call the constructor using builder values rather than using AutoFixture --- .../Factories/AllPropertiesFactoryTests.cs | 18 +++++++++++++++ .../Factories/AutoFixtureFactoryTests.cs | 3 +-- .../Factories/CallConstructorFactoryTests.cs | 23 ++++++++++++++++--- .../PublicPropertySettersFactoryTests.cs | 20 +++++++++++++++- .../Factories/AllPropertiesFactory.cs | 13 ++++++----- .../Factories/PublicPropertySettersFactory.cs | 5 +++- 6 files changed, 69 insertions(+), 13 deletions(-) diff --git a/TestStack.Dossier.Tests/Factories/AllPropertiesFactoryTests.cs b/TestStack.Dossier.Tests/Factories/AllPropertiesFactoryTests.cs index 940c4e2..cbd8956 100644 --- a/TestStack.Dossier.Tests/Factories/AllPropertiesFactoryTests.cs +++ b/TestStack.Dossier.Tests/Factories/AllPropertiesFactoryTests.cs @@ -19,5 +19,23 @@ public void GivenAllPropertiesFactory_WhenBuilding_ThenAllPropertiesSet() dto.NotSetByCtorWithPrivateSetter.ShouldNotBe(null); dto.NotSetByCtorWithPublicSetter.ShouldNotBe(null); } + + [Fact] + public void GivenAllPropertiesFactoryAgainstBuilderWithModifications_WhenBuilding_ThenCustomisationsAreUsed() + { + MixedAccessibilityDto dto = Builder + .CreateNew(new AllPropertiesFactory()) + .Set(x => x.SetByCtorNoPropertySetter, "0") + .Set(x => x.SetByCtorWithPrivateSetter, "1") + .Set(x => x.SetByCtorWithPublicSetter, "2") + .Set(x => x.NotSetByCtorWithPrivateSetter, "3") + .Set(x => x.NotSetByCtorWithPublicSetter, "4"); + + dto.SetByCtorNoPropertySetter.ShouldBe("0"); + dto.SetByCtorWithPrivateSetter.ShouldBe("1"); + dto.SetByCtorWithPublicSetter.ShouldBe("2"); + dto.NotSetByCtorWithPrivateSetter.ShouldBe("3"); + dto.NotSetByCtorWithPublicSetter.ShouldBe("4"); + } } } diff --git a/TestStack.Dossier.Tests/Factories/AutoFixtureFactoryTests.cs b/TestStack.Dossier.Tests/Factories/AutoFixtureFactoryTests.cs index d018ff5..899135b 100644 --- a/TestStack.Dossier.Tests/Factories/AutoFixtureFactoryTests.cs +++ b/TestStack.Dossier.Tests/Factories/AutoFixtureFactoryTests.cs @@ -1,5 +1,4 @@ -using System; -using Shouldly; +using Shouldly; using TestStack.Dossier.Factories; using TestStack.Dossier.Tests.TestHelpers.Objects.Examples; using Xunit; diff --git a/TestStack.Dossier.Tests/Factories/CallConstructorFactoryTests.cs b/TestStack.Dossier.Tests/Factories/CallConstructorFactoryTests.cs index 97ae9a6..61a9d01 100644 --- a/TestStack.Dossier.Tests/Factories/CallConstructorFactoryTests.cs +++ b/TestStack.Dossier.Tests/Factories/CallConstructorFactoryTests.cs @@ -1,5 +1,4 @@ -using System; -using Shouldly; +using Shouldly; using TestStack.Dossier.Factories; using TestStack.Dossier.Tests.TestHelpers.Objects.Examples; using Xunit; @@ -9,7 +8,7 @@ namespace TestStack.Dossier.Tests.Factories public class CallConstructorFactoryTests { [Fact] - public void GivenConstructorFactory_WhenBuilding_ThenOnlyConstructorPropertiesSet() + public void GivenCallConstructorFactory_WhenBuilding_ThenOnlyConstructorPropertiesSet() { MixedAccessibilityDto dto = Builder.CreateNew(new CallConstructorFactory()); @@ -19,5 +18,23 @@ public void GivenConstructorFactory_WhenBuilding_ThenOnlyConstructorPropertiesSe dto.NotSetByCtorWithPrivateSetter.ShouldBe(null); dto.NotSetByCtorWithPublicSetter.ShouldBe(null); } + + [Fact] + public void GivenCallConstructorFactoryAgainstBuilderWithModifications_WhenBuilding_ThenCustomisationsAreUsed() + { + MixedAccessibilityDto dto = Builder + .CreateNew(new CallConstructorFactory()) + .Set(x => x.SetByCtorNoPropertySetter, "0") + .Set(x => x.SetByCtorWithPrivateSetter, "1") + .Set(x => x.SetByCtorWithPublicSetter, "2") + .Set(x => x.NotSetByCtorWithPrivateSetter, "3") + .Set(x => x.NotSetByCtorWithPublicSetter, "4"); + + dto.SetByCtorNoPropertySetter.ShouldBe("0"); + dto.SetByCtorWithPrivateSetter.ShouldBe("1"); + dto.SetByCtorWithPublicSetter.ShouldBe("2"); + dto.NotSetByCtorWithPrivateSetter.ShouldBe(null); + dto.NotSetByCtorWithPublicSetter.ShouldBe(null); + } } } diff --git a/TestStack.Dossier.Tests/Factories/PublicPropertySettersFactoryTests.cs b/TestStack.Dossier.Tests/Factories/PublicPropertySettersFactoryTests.cs index 794b0e4..3dbe57c 100644 --- a/TestStack.Dossier.Tests/Factories/PublicPropertySettersFactoryTests.cs +++ b/TestStack.Dossier.Tests/Factories/PublicPropertySettersFactoryTests.cs @@ -8,15 +8,33 @@ namespace TestStack.Dossier.Tests.Factories public class PublicPropertySettersFactoryTests { [Fact] - public void GivenPublicPropertiesFactory_WhenBuilding_ThenOnlyConstructorAndPublicPropertiesSet() + public void GivenPublicPropertySettersFactory_WhenBuilding_ThenOnlyConstructorAndPublicPropertiesSet() { MixedAccessibilityDto dto = Builder.CreateNew(new PublicPropertySettersFactory()); dto.SetByCtorNoPropertySetter.ShouldNotBe(null); dto.SetByCtorWithPrivateSetter.ShouldNotBe(null); dto.SetByCtorWithPublicSetter.ShouldNotBe(null); + dto.NotSetByCtorWithPrivateSetter.ShouldBe(null); dto.NotSetByCtorWithPublicSetter.ShouldNotBe(null); + } + + [Fact] + public void GivenPublicPropertySettersFactoryAgainstBuilderWithModifications_WhenBuilding_ThenCustomisationsAreUsed() + { + MixedAccessibilityDto dto = Builder + .CreateNew(new PublicPropertySettersFactory()) + .Set(x => x.SetByCtorNoPropertySetter, "0") + .Set(x => x.SetByCtorWithPrivateSetter, "1") + .Set(x => x.SetByCtorWithPublicSetter, "2") + .Set(x => x.NotSetByCtorWithPrivateSetter, "3") + .Set(x => x.NotSetByCtorWithPublicSetter, "4"); + + dto.SetByCtorNoPropertySetter.ShouldBe("0"); + dto.SetByCtorWithPrivateSetter.ShouldBe("1"); + dto.SetByCtorWithPublicSetter.ShouldBe("2"); dto.NotSetByCtorWithPrivateSetter.ShouldBe(null); + dto.NotSetByCtorWithPublicSetter.ShouldBe("4"); } } } diff --git a/TestStack.Dossier/Factories/AllPropertiesFactory.cs b/TestStack.Dossier/Factories/AllPropertiesFactory.cs index 34bbc6d..1f105b3 100644 --- a/TestStack.Dossier/Factories/AllPropertiesFactory.cs +++ b/TestStack.Dossier/Factories/AllPropertiesFactory.cs @@ -3,16 +3,17 @@ namespace TestStack.Dossier.Factories { /// - /// Creates an instance of an object by setting all public and private properties. + /// Builds the object using the constructor with the most arguments using values stored in the builder that match + /// the constructor parameter name case insensitively and then sets all public and private property setters with + /// values from the builder. + /// If there is no value specified in the builder for a ctor argument / property then the builder will supply an anonymous value. /// - public class AllPropertiesFactory : IFactory + public class AllPropertiesFactory : CallConstructorFactory { /// - public TObject BuildObject(TestDataBuilder builder) - where TObject : class - where TBuilder : TestDataBuilder, new() + public override TObject BuildObject(TestDataBuilder builder) { - var model = builder.Any.Fixture.Create(); + var model = base.BuildObject(builder); var properties = Reflector.GetSettablePropertiesFor(); foreach (var property in properties) diff --git a/TestStack.Dossier/Factories/PublicPropertySettersFactory.cs b/TestStack.Dossier/Factories/PublicPropertySettersFactory.cs index 1362ab5..aa015a9 100644 --- a/TestStack.Dossier/Factories/PublicPropertySettersFactory.cs +++ b/TestStack.Dossier/Factories/PublicPropertySettersFactory.cs @@ -3,7 +3,10 @@ namespace TestStack.Dossier.Factories { /// - /// Creates an instance of an object by setting all public properties but not private properties. + /// Builds the object using the constructor with the most arguments using values stored in the builder that match + /// the constructor parameter name case insensitively and then sets all public property setters with values from + /// the builder. + /// If there is no value specified in the builder for a ctor argument / property then the builder will supply an anonymous value. /// public class PublicPropertySettersFactory : CallConstructorFactory { From a28a6be0adbef1fdf7e3244ee8d9323e58be1743 Mon Sep 17 00:00:00 2001 From: Rob Moore Date: Thu, 14 May 2015 18:54:12 +0200 Subject: [PATCH 07/86] Removing redundant method --- .../TestHelpers/Builders/BasicCustomerBuilder.cs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/TestStack.Dossier.Tests/TestHelpers/Builders/BasicCustomerBuilder.cs b/TestStack.Dossier.Tests/TestHelpers/Builders/BasicCustomerBuilder.cs index 20e7e0f..6a94c4b 100644 --- a/TestStack.Dossier.Tests/TestHelpers/Builders/BasicCustomerBuilder.cs +++ b/TestStack.Dossier.Tests/TestHelpers/Builders/BasicCustomerBuilder.cs @@ -10,10 +10,5 @@ protected override Customer BuildObject() { return new Customer("customer1", "First Name", "Last Name", 2013, CustomerClass.Normal); } - - public virtual new BasicCustomerBuilder Set(Expression> property, TValue value) - { - return base.Set(property, value); - } } } From e0d928f32e75d5a337e6bcd937a0fe8e173ebd74 Mon Sep 17 00:00:00 2001 From: Rob Moore Date: Thu, 14 May 2015 19:06:54 +0200 Subject: [PATCH 08/86] Removed the redundant method in AnonymousValueFixture and bumped to v3.0 due to the breaking change --- BREAKING_CHANGES.md | 39 +++++++++++++++++-- NextVersion.txt | 2 +- .../Builders/BasicCustomerBuilder.cs | 4 +- TestStack.Dossier.sln | 3 +- TestStack.Dossier/AnonymousValueFixture.cs | 4 +- TestStack.Dossier/IAnonymousValueSupplier.cs | 10 ----- .../Suppliers/DefaultEmailValueSupplier.cs | 6 --- .../DefaultFirstNameValueSupplier.cs | 6 --- .../Suppliers/DefaultLastNameValueSupplier.cs | 6 --- .../Suppliers/DefaultStringValueSupplier.cs | 6 --- .../Suppliers/DefaultValueSupplier.cs | 6 --- .../DefaultValueTypeValueSupplier.cs | 9 +---- 12 files changed, 43 insertions(+), 58 deletions(-) diff --git a/BREAKING_CHANGES.md b/BREAKING_CHANGES.md index 832cee6..7ac50d6 100644 --- a/BREAKING_CHANGES.md +++ b/BREAKING_CHANGES.md @@ -1,7 +1,40 @@ Breaking Changes ================ -Breaking change from NTestDataBuilder -> TestStack.Dossier 1.0 +Version 3.0 +----------- + +The signature of `IAnonymousValueSupplier` has changed from: + +```c# +public interface IAnonymousValueSupplier +{ + bool CanSupplyValue(Type type, string propertyName); + TValue GenerateAnonymousValue(AnonymousValueFixture any, string propertyName); +} +``` + +To: + +```c# +public interface IAnonymousValueSupplier +{ + bool CanSupplyValue(Type type, string propertyName); + object GenerateAnonymousValue(AnonymousValueFixture any, Type type, string propertyName); +} +``` + +Note: the `GenerateAnonymousValue` method is no longer generic. + +### Reason + +In order to implement the `BuildUsing` method that allows you to build an object by convention in one line rather than having to call the constructor yourself we needed to have a non-generic version of the method. This change actually ended up making the anonymous value suppliers slightly easier to implement (no longer any need for type casting). + +### Fix + +If you have any custom anonymous value suppliers change the signature of your `GenerateAnonymousValue` method so it's no logner generic. + +Breaking change from NTestDataBuilder -> TestStack.Dossier 2.0 -------------------------------------------------------------- Namespace has changed from NTestDataBuilder to TestStack.Dossier. @@ -14,7 +47,7 @@ The project has been renamed. Do a global find and replace of `using NTestDataBuilder` with `using TestStack.Dossier`. -Breaking change from NTestDataBuilder -> TestStack.Dossier 1.0 +Breaking change from NTestDataBuilder -> TestStack.Dossier 2.0 -------------------------------------------------------------- When you don't `Set` a default value for a property that you later `Get` in your builder it will now generate an anonymous value for that property rather than throwing an exception. @@ -29,7 +62,7 @@ The old behaviour of throwing an exception if a value hasn't been specified is n If you want to fix a static value for a property then by all means you can still use `Set` calls in your builder constructor. If you aren't happy with the default anonymous value that is generated for a property you can use the `Any` property to generate a value from a different equivalence class in combination with a `Set` call in your builder constructor. -Breaking change from NTestDataBuilder -> TestStack.Dossier 1.0 +Breaking change from NTestDataBuilder -> TestStack.Dossier 2.0 -------------------------------------------------------------- The way that lists are generated no longer uses NBuilder - the new syntax is backwards compatible with NBuilder except that the namespace you need to include is different. You can also refactor your list generation to be a lot more terse, but that is optional. Any `BuildList` extension methods you created will now need to be deleted since they are no longer needed. You also need to ensure that all of the methods you call are marked virtual so the list generation can proxy those method calls. diff --git a/NextVersion.txt b/NextVersion.txt index 50aea0e..56fea8a 100644 --- a/NextVersion.txt +++ b/NextVersion.txt @@ -1 +1 @@ -2.1.0 \ No newline at end of file +3.0.0 \ No newline at end of file diff --git a/TestStack.Dossier.Tests/TestHelpers/Builders/BasicCustomerBuilder.cs b/TestStack.Dossier.Tests/TestHelpers/Builders/BasicCustomerBuilder.cs index 6a94c4b..cc3e534 100644 --- a/TestStack.Dossier.Tests/TestHelpers/Builders/BasicCustomerBuilder.cs +++ b/TestStack.Dossier.Tests/TestHelpers/Builders/BasicCustomerBuilder.cs @@ -1,6 +1,4 @@ -using System; -using System.Linq.Expressions; -using TestStack.Dossier.Tests.TestHelpers.Objects.Entities; +using TestStack.Dossier.Tests.TestHelpers.Objects.Entities; namespace TestStack.Dossier.Tests.TestHelpers.Builders { diff --git a/TestStack.Dossier.sln b/TestStack.Dossier.sln index e535bbe..954293b 100644 --- a/TestStack.Dossier.sln +++ b/TestStack.Dossier.sln @@ -1,13 +1,14 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 2013 -VisualStudioVersion = 12.0.31101.0 +VisualStudioVersion = 12.0.30723.0 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{BC8508D1-6FCB-46B2-9C14-F41F6AD76B09}" ProjectSection(SolutionItems) = preProject BREAKING_CHANGES.md = BREAKING_CHANGES.md LICENSE = LICENSE logo.png = logo.png + NextVersion.txt = NextVersion.txt README.md = README.md EndProjectSection EndProject diff --git a/TestStack.Dossier/AnonymousValueFixture.cs b/TestStack.Dossier/AnonymousValueFixture.cs index 1b9eff1..3558fd6 100644 --- a/TestStack.Dossier/AnonymousValueFixture.cs +++ b/TestStack.Dossier/AnonymousValueFixture.cs @@ -88,7 +88,7 @@ public T Get(Expression> property) .Concat(DefaultValueSuppliers) .First(s => s.CanSupplyValue(typeof(T), propertyName)); - return valueSupplier.GenerateAnonymousValue(this, propertyName); + return (T) valueSupplier.GenerateAnonymousValue(this, typeof(T), propertyName); } /// @@ -102,7 +102,7 @@ public object Get(Type type, string propertyName) var valueSupplier = LocalValueSuppliers .Concat(GlobalValueSuppliers) .Concat(DefaultValueSuppliers) - .First(s => s.CanSupplyValue(type,propertyName)); + .First(s => s.CanSupplyValue(type, propertyName)); return valueSupplier.GenerateAnonymousValue(this, type, propertyName); } diff --git a/TestStack.Dossier/IAnonymousValueSupplier.cs b/TestStack.Dossier/IAnonymousValueSupplier.cs index 9eda5af..85fe113 100644 --- a/TestStack.Dossier/IAnonymousValueSupplier.cs +++ b/TestStack.Dossier/IAnonymousValueSupplier.cs @@ -15,16 +15,6 @@ public interface IAnonymousValueSupplier /// Whether or not this supplier can supply an anonymous value bool CanSupplyValue(Type type, string propertyName); - /// - /// Return an anonymous value for the given property and fixture. - /// - /// The type that the property is enclosed in - /// The type of the target property - the required anonymous value is of this type - /// Anonymous value fixture - /// The name of the property to return an anonymous value for - /// The anonymous value - TValue GenerateAnonymousValue(AnonymousValueFixture any, string propertyName); - /// /// Return an anonymous value for the given property and fixture. /// diff --git a/TestStack.Dossier/Suppliers/DefaultEmailValueSupplier.cs b/TestStack.Dossier/Suppliers/DefaultEmailValueSupplier.cs index 754faba..5db3f94 100644 --- a/TestStack.Dossier/Suppliers/DefaultEmailValueSupplier.cs +++ b/TestStack.Dossier/Suppliers/DefaultEmailValueSupplier.cs @@ -14,12 +14,6 @@ public bool CanSupplyValue(Type type, string propertyName) return type == typeof(string) && propertyName.ToLower().Contains("email"); } - /// - public TValue GenerateAnonymousValue(AnonymousValueFixture any, string propertyName) - { - return (TValue) (object) any.EmailAddress(); - } - /// public object GenerateAnonymousValue(AnonymousValueFixture any, Type type, string propertyName) { diff --git a/TestStack.Dossier/Suppliers/DefaultFirstNameValueSupplier.cs b/TestStack.Dossier/Suppliers/DefaultFirstNameValueSupplier.cs index bbd2e59..57edf91 100644 --- a/TestStack.Dossier/Suppliers/DefaultFirstNameValueSupplier.cs +++ b/TestStack.Dossier/Suppliers/DefaultFirstNameValueSupplier.cs @@ -14,12 +14,6 @@ public bool CanSupplyValue(Type type, string propertyName) return type == typeof(string) && propertyName.ToLower() == "firstname"; } - /// - public TValue GenerateAnonymousValue(AnonymousValueFixture any, string propertyName) - { - return (TValue) (object) any.FirstName(); - } - /// public object GenerateAnonymousValue(AnonymousValueFixture any, Type type, string propertyName) { diff --git a/TestStack.Dossier/Suppliers/DefaultLastNameValueSupplier.cs b/TestStack.Dossier/Suppliers/DefaultLastNameValueSupplier.cs index e0fc9c7..a5f3fc0 100644 --- a/TestStack.Dossier/Suppliers/DefaultLastNameValueSupplier.cs +++ b/TestStack.Dossier/Suppliers/DefaultLastNameValueSupplier.cs @@ -15,12 +15,6 @@ public bool CanSupplyValue(Type type, string propertyName) (propertyName.ToLower() == "lastname" || propertyName.ToLower() == "surname"); } - /// - public TValue GenerateAnonymousValue(AnonymousValueFixture any, string propertyName) - { - return (TValue)(object)any.LastName(); - } - /// public object GenerateAnonymousValue(AnonymousValueFixture any, Type type, string propertyName) { diff --git a/TestStack.Dossier/Suppliers/DefaultStringValueSupplier.cs b/TestStack.Dossier/Suppliers/DefaultStringValueSupplier.cs index ed5b40f..0402e00 100644 --- a/TestStack.Dossier/Suppliers/DefaultStringValueSupplier.cs +++ b/TestStack.Dossier/Suppliers/DefaultStringValueSupplier.cs @@ -14,12 +14,6 @@ public bool CanSupplyValue(Type type, string propertyName) return type == typeof(string); } - /// - public TValue GenerateAnonymousValue(AnonymousValueFixture any, string propertyName) - { - return (TValue) (object) any.StringStartingWith(propertyName); - } - /// public object GenerateAnonymousValue(AnonymousValueFixture any, Type type, string propertyName) { diff --git a/TestStack.Dossier/Suppliers/DefaultValueSupplier.cs b/TestStack.Dossier/Suppliers/DefaultValueSupplier.cs index 6bd6099..fe3f0d9 100644 --- a/TestStack.Dossier/Suppliers/DefaultValueSupplier.cs +++ b/TestStack.Dossier/Suppliers/DefaultValueSupplier.cs @@ -13,12 +13,6 @@ public bool CanSupplyValue(Type type, string propertyName) return true; } - /// - public TValue GenerateAnonymousValue(AnonymousValueFixture any, string propertyName) - { - return default(TValue); - } - /// public object GenerateAnonymousValue(AnonymousValueFixture any, Type type, string propertyName) { diff --git a/TestStack.Dossier/Suppliers/DefaultValueTypeValueSupplier.cs b/TestStack.Dossier/Suppliers/DefaultValueTypeValueSupplier.cs index bf1cd68..1e0ec24 100644 --- a/TestStack.Dossier/Suppliers/DefaultValueTypeValueSupplier.cs +++ b/TestStack.Dossier/Suppliers/DefaultValueTypeValueSupplier.cs @@ -16,17 +16,10 @@ public bool CanSupplyValue(Type type, string propertyName) return type.IsValueType; } - /// - public TValue GenerateAnonymousValue(AnonymousValueFixture any, string propertyName) - { - return any.Fixture.Create(); - } - - /// How to create weakly-typed CreateAnonymous with AutoFixture - /// http://autofixture.codeplex.com/workitem/4229 /// public object GenerateAnonymousValue(AnonymousValueFixture any, Type type, string propertyName) { + // http://autofixture.codeplex.com/workitem/4229 var context = new SpecimenContext(any.Fixture); var specimen = context.Resolve(type); return specimen; From 6f3053f17bd9b7a6fdc55652a8888c979c4a6284 Mon Sep 17 00:00:00 2001 From: Rob Moore Date: Thu, 14 May 2015 19:33:51 +0200 Subject: [PATCH 09/86] Documentation update --- README.md | 272 +++++++++++------- .../Builder_CreateNewTests.cs | 16 +- 2 files changed, 175 insertions(+), 113 deletions(-) diff --git a/README.md b/README.md index ff2645c..54cfd7e 100644 --- a/README.md +++ b/README.md @@ -12,76 +12,79 @@ Prior to v2.0 this library was known as NTestDataBuilder. 1. `Install-Package TestStack.Dossier` -2. Create a builder class for one of your objects, e.g. if you have a customer: - - // Customer.cs - - public class Customer - { - protected Customer() {} - - public Customer(string firstName, string lastName, int yearJoined) - { - if (string.IsNullOrEmpty(firstName)) - throw new ArgumentNullException("firstName"); - if (string.IsNullOrEmpty(lastName)) - throw new ArgumentNullException("lastName"); - - FirstName = firstName; - LastName = lastName; - YearJoined = yearJoined; - } - - public virtual int CustomerForHowManyYears(DateTime since) - { - if (since.Year < YearJoined) - throw new ArgumentException("Date must be on year or after year that customer joined.", "since"); - return since.Year - YearJoined; - } - - public virtual string FirstName { get; private set; } - public virtual string LastName { get; private set; } - public virtual int YearJoined { get; private set; } - } - - // CustomerBuilder.cs - - public class CustomerBuilder : TestDataBuilder - { - public CustomerBuilder() - { - // Can set up defaults here - any that you don't set will have an anonymous value generated by default. - WhoJoinedIn(2013); - } - - public CustomerBuilder WithFirstName(string firstName) - { - return Set(x => x.FirstName, firstName); - } - - public CustomerBuilder WithLastName(string lastName) - { - return Set(x => x.LastName, lastName); - } - - public CustomerBuilder WhoJoinedIn(int yearJoined) - { - return Set(x => x.YearJoined, yearJoined); - } - - protected override Customer BuildObject() - { - return new Customer( - Get(x => x.FirstName), - Get(x => x.LastName), - Get(x => x.YearJoined) - ); - } - } +2. Create a builder class for one of your domain objects, e.g. if you have a customer: + + // Customer.cs + + public class Customer + { + protected Customer() {} + + public Customer(string firstName, string lastName, int yearJoined) + { + if (string.IsNullOrEmpty(firstName)) + throw new ArgumentNullException("firstName"); + if (string.IsNullOrEmpty(lastName)) + throw new ArgumentNullException("lastName"); + + FirstName = firstName; + LastName = lastName; + YearJoined = yearJoined; + } + + public virtual int CustomerForHowManyYears(DateTime since) + { + if (since.Year < YearJoined) + throw new ArgumentException("Date must be on year or after year that customer joined.", "since"); + return since.Year - YearJoined; + } + + public virtual string FirstName { get; private set; } + public virtual string LastName { get; private set; } + public virtual int YearJoined { get; private set; } + } + + // CustomerBuilder.cs + + public class CustomerBuilder : TestDataBuilder + { + public CustomerBuilder() + { + // Can set up defaults here - any that you don't set or subsequently override will have an anonymous value generated by default. + WhoJoinedIn(2013); + } + + // Note: the methods are virtual - this is important if you want to build lists (as per below) + public virtual CustomerBuilder WithFirstName(string firstName) + { + return Set(x => x.FirstName, firstName); + } + + public virtual CustomerBuilder WithLastName(string lastName) + { + return Set(x => x.LastName, lastName); + } + + public virtual CustomerBuilder WhoJoinedIn(int yearJoined) + { + return Set(x => x.YearJoined, yearJoined); + } + + protected override Customer BuildObject() + { + return new Customer( + Get(x => x.FirstName), + Get(x => x.LastName), + Get(x => x.YearJoined) + ); + // or + return BuildUsing(); + } + } 3. Use the builder in a test, e.g. - var customer = new CustomerBuilder().WithFirstName("Robert").Build(); + var customer = new CustomerBuilder().WithFirstName("Robert").Build(); 4. Consider using the Object Mother pattern in combination with the builders, see [my blog post](http://robdmoore.id.au/blog/2013/05/26/test-data-generation-the-right-way-object-mother-test-data-builders-nsubstitute-nbuilder/) for a description of how I use this library. @@ -92,75 +95,134 @@ This library allows you to build a list of entities fluently and tersely. Here i ```c# var customers = CustomerBuilder.CreateListOfSize(5) - .TheFirst(1).WithFirstName("First") - .TheNext(1).WithLastName("Next Last") - .TheLast(1).WithLastName("Last Last") - .ThePrevious(2).With(b => b.WithLastName("last" + (++i).ToString())) - .All().WhoJoinedIn(1999) - .BuildList(); + .TheFirst(1).WithFirstName("First") + .TheNext(1).WithLastName("Next Last") + .TheLast(1).WithLastName("Last Last") + .ThePrevious(2).With(b => b.WithLastName("last" + (++i).ToString())) + .All().WhoJoinedIn(1999) + .BuildList(); ``` This would create the following (represented as json): ```json [ - { - "FirstName":"First", - "LastName":"LastNameff51d5e5-9ce4-4710-830e-9042cfd48a8b", - "YearJoined":1999 - }, - { - "FirstName":"FirstName7b08da9c-8c13-47f7-abe9-09b73b935e1f", - "LastName":"Next Last", - "YearJoined":1999 - }, - { - "FirstName":"FirstName836d4c54-b227-4c1b-b684-de4cd940c251", - "LastName":"last1", - "YearJoined":1999 - }, - { - "FirstName":"FirstName5f53e895-921e-4130-8ed8-610b017f3b9b", - "LastName":"last2", - "YearJoined":1999 - }, - { - "FirstName":"FirstName9cf6b05f-38aa-47c1-9fd7-e3c1009cf3e4", - "LastName":"Last Last", - "YearJoined":1999 - } + { + "FirstName":"First", + "LastName":"LastNameff51d5e5-9ce4-4710-830e-9042cfd48a8b", + "YearJoined":1999 + }, + { + "FirstName":"FirstName7b08da9c-8c13-47f7-abe9-09b73b935e1f", + "LastName":"Next Last", + "YearJoined":1999 + }, + { + "FirstName":"FirstName836d4c54-b227-4c1b-b684-de4cd940c251", + "LastName":"last1", + "YearJoined":1999 + }, + { + "FirstName":"FirstName5f53e895-921e-4130-8ed8-610b017f3b9b", + "LastName":"last2", + "YearJoined":1999 + }, + { + "FirstName":"FirstName9cf6b05f-38aa-47c1-9fd7-e3c1009cf3e4", + "LastName":"Last Last", + "YearJoined":1999 + } ] ``` + ### Castle Dynamic Proxy Generator Exception error If you use the list builder functionality and get the following error: -> Castle.DynamicProxy.Generators.GeneratorExceptionCan not create proxy for type because it is not accessible. Make it public, or internal and mark your assembly with [assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")] attribute, because assembly is not strong-named. +> Castle.DynamicProxy.Generators.GeneratorException: Can not create proxy for type because it is not accessible. Make it public, or internal and mark your assembly with [assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")] attribute, because assembly is not strong-named. Then you either need to: * Make your builder class public * Add the following to your `AssemblyInfo.cs` file: `[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")]` +### Non-virtual method Invalid Operation Exception + +If you use the list builder functionality and get the following error: + +> System.InvalidOperationException: Tried to build a list with a builder who has non-virtual method. Please make on type virtual. + +Then you need to mark all the public methods on your builder as virtual. This is because we are using Castle Dynamic Proxy to generate lists and it can't intercept non-virtual methods. + Create Entities Implicitly -------------------------- -In the previous examples, you have seen how to create entities *explicitly*, by calling the `Build()` and `BuildList()` methods. For the ultimate in terseness, you can omit these methods, and Dossier will *implicitly* call them for you. The one caveat is that you must explicitly declare the variable type rather than using the `var` keyword. +In the previous examples, you have seen how to create entities *explicitly*, by calling the `Build()` and `BuildList()` methods. For the ultimate in terseness, you can omit these methods, and Dossier will *implicitly* call them for you. The one caveat is that you must explicitly declare the variable type rather than using the `var` keyword (unless you are passing into a method with the desired type). So, to create a single entity: - Customer customer = new CustomerBuilder(); + Customer customer = new CustomerBuilder(); - Customer customer = new CustomerBuilder() + Customer customer = new CustomerBuilder() .WithFirstName("Matt") .WithLastName("Kocaj") .WhoJoinedIn(2010); Or to create a list of entities: - List entities = BasicCustomerBuilder.CreateListOfSize(5); + List entities = CustomerBuilder.CreateListOfSize(5); List data = CustomerBuilder.CreateListOfSize(3) - .All().With(b => b.WithFirstName(generator.Generate().ToString())); + .TheFirst(1).WithFirstName("John"); + +Create object without requiring custom builder class +---------------------------------------------------- + +If you are building domain entities or other important classes having a custom builder class with intention-revealing method (e.g. WithFirstName) provides terseness (avoiding lambda expressions) and allows the builder class to start forming documentation about the usage of that object. + +Sometimes though, you just want to build a class without that ceremony. Typically, we find that this applies for view models and DTOs. + +In that instance you can use the generic Builder implementation as shown below: + +```c# +StudentViewModel vm = Builder.CreateNew() + .Set(x => x.FirstName, "Pi") + .Set(x => x.LastName, "Lanningham") + .Set(x => x.EnrollmentDate, new DateTime(2000, 1, 1)); + +var studentViewModels = Builder.CreateListOfSize(5) + .TheFirst(1).Set(x => x.FirstName, "First") + .TheNext(1).Set(x => x.LastName, "Next Last") + .TheLast(1).Set(x => x.LastName, "Last Last") + .ThePrevious(2).With(b => b.Set(x => x.LastName, "last" + (++i).ToString())) + .All().Set(x => x.EnrollmentDate, _enrollmentDate) + .BuildList(); +``` + +The syntax is modelled closely against what NBuilder provides and the behaviour of the class should be very similar. + +### Customising the construction of the object + +By default the longest constructor of the class you specify will be called and then all properties (with public and private setters) will be set with values you specified (or anonymous values if none were specified). + +Sometimes you might not want this behaviour, in which case you can specify a custom construction factory (see build objects without calling constructor section for explanation of factories) as shown below: + +```c# +var dto = Builder.CreateNew(new CallConstructorFactory()).Build(); + +var dtos = MixedAccessibilityDto dto = Builder.CreateListOfSize(5, new CallConstructorFactory()).BuildList(); +``` + +Build objects without calling constructor +----------------------------------------- + +When you extend the `TestDataBuilder` as part of creating a custom builder you will be forced to override the abstract `BuildObject` method. You have full flexibility to call the constructor of your class directly as shown above, but you can also invoke some convention-based factories to speed up the creation of your builder (also shown above) using the `BuildUsing` method. + +The `BuildUsing` method takes an instance of `IFactory`, of which you can create your own factory implementation that takes into account your own conventions or you can use one of the built-in ones: + +* `AllPropertiesFactory` - Calls the longest constructor with builder values (or anonymous values if none set) based on case-insensitive match of constructor parameter names against property names and then calls the setter on all properties (public or private) with builder values (or anonymous values if none set) +* `PublicPropertySettersFactory` - Calls the longest constructor with builder values (or anonymous values if none set) based on case-insensitive match of constructor parameter names against property names and then calls the setter on all properties with public setters with builder values (or anonymous values if none set) +* `CallConstructorFactory` - Calls the longest constructor with builder values (or anonymous values if none set) based on case-insensitive match of constructor parameter names against property names +* `AutoFixtureFactory` - Asks AutoFixture to create an anonymous instance of the class (note: does **not** use any builder values or anonymous values from Dossier) Anonymous Values and Equivalence Classes ---------------------------------------- @@ -220,4 +282,4 @@ If you have a suggestion for the library that can incorporate this value-add wit Contributions / Questions ------------------------- -If you would like to contribute to this project then feel free to communicate with me via Twitter @robdmoore or alternatively submit a pull request / issue. +If you would like to contribute to this project then feel free to communicate with Rob via Twitter (@robdmoore) or alternatively submit a pull request / issue. diff --git a/TestStack.Dossier.Tests/Builder_CreateNewTests.cs b/TestStack.Dossier.Tests/Builder_CreateNewTests.cs index 24a3b4f..3581856 100644 --- a/TestStack.Dossier.Tests/Builder_CreateNewTests.cs +++ b/TestStack.Dossier.Tests/Builder_CreateNewTests.cs @@ -36,24 +36,24 @@ public void GivenBuilderWithModifications_WhenCallingBuildExplicitly_ShouldOverr .Set(x => x.LastName, "Lanningham") .Set(x => x.EnrollmentDate, new DateTime(2000, 1, 1)); - var customer = builder.Build(); + var vm = builder.Build(); - customer.FirstName.ShouldBe("Pi"); - customer.LastName.ShouldBe("Lanningham"); - customer.EnrollmentDate.ShouldBe(new DateTime(2000, 1, 1)); + vm.FirstName.ShouldBe("Pi"); + vm.LastName.ShouldBe("Lanningham"); + vm.EnrollmentDate.ShouldBe(new DateTime(2000, 1, 1)); } [Fact] public void GivenBuilderWithModifications_WhenCallingBuildImplicitly_ShouldOverrideValues() { - StudentViewModel customer = Builder.CreateNew() + StudentViewModel vm = Builder.CreateNew() .Set(x => x.FirstName, "Pi") .Set(x => x.LastName, "Lanningham") .Set(x => x.EnrollmentDate, new DateTime(2000, 1, 1)); - customer.FirstName.ShouldBe("Pi"); - customer.LastName.ShouldBe("Lanningham"); - customer.EnrollmentDate.ShouldBe(new DateTime(2000, 1, 1)); + vm.FirstName.ShouldBe("Pi"); + vm.LastName.ShouldBe("Lanningham"); + vm.EnrollmentDate.ShouldBe(new DateTime(2000, 1, 1)); } [Fact] From 775f87b1a33682389711fab4f9117ffc13a8c212 Mon Sep 17 00:00:00 2001 From: Rob Moore Date: Thu, 14 May 2015 20:10:47 +0200 Subject: [PATCH 10/86] Added ability to set child builders when using Builder --- README.md | 1 + .../Builder_SetUsingBuilderTests.cs | 116 ++++++++++++++++++ .../Builders/AddressViewModelBuilder.cs | 18 +++ .../Objects/ViewModels/AddressViewModel.cs | 8 ++ .../Objects/ViewModels/StudentViewModel.cs | 2 + .../TestStack.Dossier.Tests.csproj | 3 + TestStack.Dossier/Builder.cs | 40 +++++- TestStack.Dossier/TestDataBuilder.cs | 8 +- 8 files changed, 189 insertions(+), 7 deletions(-) create mode 100644 TestStack.Dossier.Tests/Builder_SetUsingBuilderTests.cs create mode 100644 TestStack.Dossier.Tests/TestHelpers/Builders/AddressViewModelBuilder.cs create mode 100644 TestStack.Dossier.Tests/TestHelpers/Objects/ViewModels/AddressViewModel.cs diff --git a/README.md b/README.md index 54cfd7e..8c6c7ae 100644 --- a/README.md +++ b/README.md @@ -60,6 +60,7 @@ Prior to v2.0 this library was known as NTestDataBuilder. return Set(x => x.FirstName, firstName); } + // Note: we typically only start with the methods that are strictly needed so the builders are quick to write and aren't bloated' public virtual CustomerBuilder WithLastName(string lastName) { return Set(x => x.LastName, lastName); diff --git a/TestStack.Dossier.Tests/Builder_SetUsingBuilderTests.cs b/TestStack.Dossier.Tests/Builder_SetUsingBuilderTests.cs new file mode 100644 index 0000000..ff548b7 --- /dev/null +++ b/TestStack.Dossier.Tests/Builder_SetUsingBuilderTests.cs @@ -0,0 +1,116 @@ +using Shouldly; +using TestStack.Dossier.Lists; +using TestStack.Dossier.Tests.TestHelpers.Builders; +using TestStack.Dossier.Tests.TestHelpers.Objects.ViewModels; +using Xunit; + +namespace TestStack.Dossier.Tests +{ + // ReSharper disable once InconsistentNaming + public class Builder_SetUsingBuilderTests + { + [Fact] + public void GivenBuilderWithObjectPropertyNotSet_WhenBuildingTheObject_ThenThePropertyWillBeNull() + { + var vm = Builder.CreateNew().Build(); + + vm.Address.ShouldBe(null); + } + + [Fact] + public void GivenBuilderWithObjectPropertyNotSet_WhenBuildingAListOfObjects_ThenThePropertyWillBeNull() + { + var vm = Builder.CreateListOfSize(1).BuildList()[0]; + + vm.Address.ShouldBe(null); + } + + [Fact] + public void GivenBuilderWithObjectPropertySetViaBuilder_WhenBuildingTheObject_ThenThePropertyWillBeSet() + { + var vm = Builder.CreateNew() + .SetUsingBuilder(x => x.Address) + .Build(); + + vm.Address.ShouldNotBe(null); + } + + [Fact] + public void GivenBuilderWithObjectPropertySetViaBuilder_WhenBuildingAListOfObjects_ThenThePropertyWillBeSet() + { + var vm = Builder.CreateListOfSize(1) + .TheFirst(1) + .SetUsingBuilder(x => x.Address) + .BuildList()[0]; + + vm.Address.ShouldNotBe(null); + } + + [Fact] + public void GivenBuilderWithObjectPropertySetViaBuilderAndCustomisation_WhenBuildingTheObject_ThenThePropertyWillBeSetIncludingTheCustomisation() + { + var vm = Builder.CreateNew() + .SetUsingBuilder(x => x.Address, b => b.Set(x => x.Street, "A street")) + .Build(); + + vm.Address.ShouldNotBe(null); + vm.Address.Street.ShouldBe("A street"); + } + + [Fact] + public void GivenBuilderWithObjectPropertySetViaBuilderAndCustomisation_WhenBuildingAListOfObjects_ThenThePropertyWillBeSetIncludingTheCustomisation() + { + var vm = Builder.CreateListOfSize(1) + .All() + .SetUsingBuilder(x => x.Address, b => b.Set(x => x.Street, "A street")) + .BuildList()[0]; + + vm.Address.ShouldNotBe(null); + vm.Address.Street.ShouldBe("A street"); + } + + [Fact] + public void GivenBuilderWithObjectPropertySetViaCustomBuilder_WhenBuildingTheObject_ThenThePropertyWillBeSet() + { + var vm = Builder.CreateNew() + .SetUsingBuilder(x => x.Address) + .Build(); + + vm.Address.ShouldNotBe(null); + } + + [Fact] + public void GivenBuilderWithObjectPropertySetViaCustomBuilder_WhenBuildingAListOfObjects_ThenThePropertyWillBeSet() + { + var vm = Builder.CreateListOfSize(1) + .All() + .SetUsingBuilder(x => x.Address) + .BuildList()[0]; + + vm.Address.ShouldNotBe(null); + } + + [Fact] + public void GivenBuilderWithObjectPropertySetViaCustomBuilderAndCustomisation_WhenBuildingTheObject_ThenThePropertyWillBeSetIncludingTheCustomisation() + { + var vm = Builder.CreateNew() + .SetUsingBuilder(x => x.Address, b => b.WithStreet("A street")) + .Build(); + + vm.Address.ShouldNotBe(null); + vm.Address.Street.ShouldBe("A street"); + } + + [Fact] + public void GivenBuilderWithObjectPropertySetViaCustomBuilderAndCustomisation_WhenBuildingAListOfObjects_ThenThePropertyWillBeSetIncludingTheCustomisation() + { + var vm = Builder.CreateListOfSize(1) + .All() + .SetUsingBuilder(x => x.Address, b => b.WithStreet("A street")) + .BuildList()[0]; + + vm.Address.ShouldNotBe(null); + vm.Address.Street.ShouldBe("A street"); + } + } +} diff --git a/TestStack.Dossier.Tests/TestHelpers/Builders/AddressViewModelBuilder.cs b/TestStack.Dossier.Tests/TestHelpers/Builders/AddressViewModelBuilder.cs new file mode 100644 index 0000000..512b120 --- /dev/null +++ b/TestStack.Dossier.Tests/TestHelpers/Builders/AddressViewModelBuilder.cs @@ -0,0 +1,18 @@ +using TestStack.Dossier.Factories; +using TestStack.Dossier.Tests.TestHelpers.Objects.ViewModels; + +namespace TestStack.Dossier.Tests.TestHelpers.Builders +{ + public class AddressViewModelBuilder : TestDataBuilder + { + public virtual AddressViewModelBuilder WithStreet(string street) + { + return Set(x => x.Street, street); + } + + protected override AddressViewModel BuildObject() + { + return BuildUsing(); + } + } +} diff --git a/TestStack.Dossier.Tests/TestHelpers/Objects/ViewModels/AddressViewModel.cs b/TestStack.Dossier.Tests/TestHelpers/Objects/ViewModels/AddressViewModel.cs new file mode 100644 index 0000000..7a24c75 --- /dev/null +++ b/TestStack.Dossier.Tests/TestHelpers/Objects/ViewModels/AddressViewModel.cs @@ -0,0 +1,8 @@ +namespace TestStack.Dossier.Tests.TestHelpers.Objects.ViewModels +{ + public class AddressViewModel + { + public string Street { get; set; } + public string Suburb { get; set; } + } +} \ No newline at end of file diff --git a/TestStack.Dossier.Tests/TestHelpers/Objects/ViewModels/StudentViewModel.cs b/TestStack.Dossier.Tests/TestHelpers/Objects/ViewModels/StudentViewModel.cs index 9ba1f94..63e6017 100644 --- a/TestStack.Dossier.Tests/TestHelpers/Objects/ViewModels/StudentViewModel.cs +++ b/TestStack.Dossier.Tests/TestHelpers/Objects/ViewModels/StudentViewModel.cs @@ -31,5 +31,7 @@ public string FullName public DateTime EnrollmentDate { get; set; } public Grade Grade { get; set; } + + public AddressViewModel Address { get; set; } } } diff --git a/TestStack.Dossier.Tests/TestStack.Dossier.Tests.csproj b/TestStack.Dossier.Tests/TestStack.Dossier.Tests.csproj index 4b10acb..380dd50 100644 --- a/TestStack.Dossier.Tests/TestStack.Dossier.Tests.csproj +++ b/TestStack.Dossier.Tests/TestStack.Dossier.Tests.csproj @@ -57,6 +57,8 @@ + + @@ -90,6 +92,7 @@ + diff --git a/TestStack.Dossier/Builder.cs b/TestStack.Dossier/Builder.cs index 6e46826..e4dc321 100644 --- a/TestStack.Dossier/Builder.cs +++ b/TestStack.Dossier/Builder.cs @@ -1,12 +1,14 @@ -using Ploeh.AutoFixture.Kernel; +using System; +using System.Linq.Expressions; +using Ploeh.AutoFixture.Kernel; using TestStack.Dossier.Factories; using TestStack.Dossier.Lists; namespace TestStack.Dossier { /// - /// A generic Test Data Builder implementation for building objects on the fly. - /// By default + /// A generic Test Data Builder implementation for building objects on the fly + /// without needing to create a custom builder. /// /// The type of object this class generates. public class Builder : TestDataBuilder> @@ -63,5 +65,37 @@ protected override T BuildObject() { return Factory.BuildObject(this); } + + /// + /// Set a property value using a custom builder. + /// + /// The type of the property being set + /// The type of the custom builder to build the property value using + /// The property to set + /// An optional modifier to customise the builder + /// The builder so that other method calls can be chained + public virtual Builder SetUsingBuilder( + Expression> property, + Func modifier = null) + where TPropertyType : class + where TPropertyBuilder : TestDataBuilder, new() + { + return Set(property, GetChildBuilder(modifier)); + } + + /// + /// Set a property value using a . + /// + /// The type of the property being set + /// The property to set + /// An optional modifier to customise the builder + /// The builder so that other method calls can be chained + public virtual Builder SetUsingBuilder( + Expression> property, + Func, Builder> modifier = null) + where TPropertyType : class + { + return Set(property, GetChildBuilder>(modifier)); + } } } diff --git a/TestStack.Dossier/TestDataBuilder.cs b/TestStack.Dossier/TestDataBuilder.cs index 3eff09f..608d272 100644 --- a/TestStack.Dossier/TestDataBuilder.cs +++ b/TestStack.Dossier/TestDataBuilder.cs @@ -77,10 +77,10 @@ public static implicit operator List(TestDataBuilder protected abstract TObject BuildObject(); /// - /// + /// Builds the object from this builder using an . /// - /// - /// + /// The factory to use to build the object + /// The built object protected TObject BuildUsing() where TFactory : IFactory, new() { @@ -110,7 +110,7 @@ protected virtual void AlterProxy(TObject proxy) {} /// /// The type of the property /// A lambda expression specifying the property to record a value for - /// The value to record + /// The builder so that other method calls can be chained public virtual TBuilder Set(Expression> property, TValue value) { _properties[Reflector.GetPropertyNameFor(property)] = value; From 48acf15036557d2ad51e9c7df0bb320c1d71f10a Mon Sep 17 00:00:00 2001 From: Rob Moore Date: Thu, 14 May 2015 20:22:03 +0200 Subject: [PATCH 11/86] Added documentation for sharing anonymous value fixtures across builders --- README.md | 33 ++++++++++++++++++++ TestStack.Dossier.Tests/ChildBuilderTests.cs | 4 +-- 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 8c6c7ae..4a9da88 100644 --- a/README.md +++ b/README.md @@ -225,6 +225,39 @@ The `BuildUsing` method takes an instance of `IFactory`, of which you can create * `CallConstructorFactory` - Calls the longest constructor with builder values (or anonymous values if none set) based on case-insensitive match of constructor parameter names against property names * `AutoFixtureFactory` - Asks AutoFixture to create an anonymous instance of the class (note: does **not** use any builder values or anonymous values from Dossier) +Propogating the anonymous value fixture across builders +------------------------------------------------------- + +Within a particular instance of `AnonymousValueFixture`, which is created for every builder, any generators that return a sequence of values (e.g. unique values) will be maintained. If you want to ensure that the same anonymous value fixture is used across multiple related builders then: + +* Using `CreateListOfSize` will automatically propagate the anonymous value fixture across builders +* Call the `GetChildBuilder(Func modifier = null)` method from within your custom builder, e.g.: + + public MyCustomBuilder WithSomeValue(Func modifier = null) + { + return Set(x => x.SomeValue, GetChildBuilder(modifier)); + } +* If using `Builder` then call the `SetUsingBuilder` method, e.g.: + + // Uses Builder + Builder.CreateNew() + .SetUsingBuilder(x => x.Address) + .Build() + // Uses Builder, includes customisation + Builder.CreateNew() + .SetUsingBuilder(x => x.Address, b => b.Set(y => y.Street, "A street")) + .Build() + // Uses AddressBuilder + Builder.CreateNew() + .SetUsingBuilder(x => x.Address) + .Build() + // Uses AddressBuilder, includes customisation + Builder.CreateNew() + .SetUsingBuilder(x => x.Address, b => b.Set(y => y.Street, "A street")) + .Build() + +There is currently no way to share an anonymous value fixture across unrelated builder instances. If this is something you need please raise an issue so we can discuss your requirement. + Anonymous Values and Equivalence Classes ---------------------------------------- diff --git a/TestStack.Dossier.Tests/ChildBuilderTests.cs b/TestStack.Dossier.Tests/ChildBuilderTests.cs index 3c447bd..7891162 100644 --- a/TestStack.Dossier.Tests/ChildBuilderTests.cs +++ b/TestStack.Dossier.Tests/ChildBuilderTests.cs @@ -68,12 +68,12 @@ public class ParentBuilder : TestDataBuilder { public ParentBuilder() { - Set(x => x.Child, new ChildBuilder().Build()); + Set(x => x.Child, new ChildBuilder()); } public ParentBuilder WithChildBuilder(Func modifier = null) { - return Set(x => x.Child, GetChildBuilder(modifier).Build()); + return Set(x => x.Child, GetChildBuilder(modifier)); } protected override ParentObject BuildObject() From 3d924d219f4a0a3f2985e9ed563fc63af671b88b Mon Sep 17 00:00:00 2001 From: Michael Whelan Date: Fri, 15 May 2015 16:36:11 +0100 Subject: [PATCH 12/86] Set default Factory to PublicPropertySettersFactory --- TestStack.Dossier/TestDataBuilder.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TestStack.Dossier/TestDataBuilder.cs b/TestStack.Dossier/TestDataBuilder.cs index 8c35cf4..50e1167 100644 --- a/TestStack.Dossier/TestDataBuilder.cs +++ b/TestStack.Dossier/TestDataBuilder.cs @@ -76,7 +76,7 @@ public static implicit operator List(TestDataBuilder /// The built object protected virtual TObject BuildObject() { - return BuildUsing(); + return BuildUsing(); } /// From 882323224a8d8a14cadb0bf80cb8a158d3ae8bde Mon Sep 17 00:00:00 2001 From: Michael Whelan Date: Fri, 15 May 2015 17:37:06 +0100 Subject: [PATCH 13/86] Updated the readme --- README.md | 142 ++++++++++++++++++++++++++---------------------------- 1 file changed, 67 insertions(+), 75 deletions(-) diff --git a/README.md b/README.md index 4a9da88..70a146c 100644 --- a/README.md +++ b/README.md @@ -85,16 +85,16 @@ Prior to v2.0 this library was known as NTestDataBuilder. 3. Use the builder in a test, e.g. - var customer = new CustomerBuilder().WithFirstName("Robert").Build(); + var customer = new CustomerBuilder() + .WithFirstName("Robert") + .Build(); 4. Consider using the Object Mother pattern in combination with the builders, see [my blog post](http://robdmoore.id.au/blog/2013/05/26/test-data-generation-the-right-way-object-mother-test-data-builders-nsubstitute-nbuilder/) for a description of how I use this library. -How can I create a list of entities using my builders? ------------------------------------------------------- +## How can I create a list of entities using my builders? This library allows you to build a list of entities fluently and tersely. Here is an example: -```c# var customers = CustomerBuilder.CreateListOfSize(5) .TheFirst(1).WithFirstName("First") .TheNext(1).WithLastName("Next Last") @@ -102,39 +102,36 @@ This library allows you to build a list of entities fluently and tersely. Here i .ThePrevious(2).With(b => b.WithLastName("last" + (++i).ToString())) .All().WhoJoinedIn(1999) .BuildList(); -``` This would create the following (represented as json): -```json -[ - { - "FirstName":"First", - "LastName":"LastNameff51d5e5-9ce4-4710-830e-9042cfd48a8b", - "YearJoined":1999 - }, - { - "FirstName":"FirstName7b08da9c-8c13-47f7-abe9-09b73b935e1f", - "LastName":"Next Last", - "YearJoined":1999 - }, - { - "FirstName":"FirstName836d4c54-b227-4c1b-b684-de4cd940c251", - "LastName":"last1", - "YearJoined":1999 - }, - { - "FirstName":"FirstName5f53e895-921e-4130-8ed8-610b017f3b9b", - "LastName":"last2", - "YearJoined":1999 - }, - { - "FirstName":"FirstName9cf6b05f-38aa-47c1-9fd7-e3c1009cf3e4", - "LastName":"Last Last", - "YearJoined":1999 - } -] -``` + [ + { + "FirstName":"First", + "LastName":"LastNameff51d5e5-9ce4-4710-830e-9042cfd48a8b", + "YearJoined":1999 + }, + { + "FirstName":"FirstName7b08da9c-8c13-47f7-abe9-09b73b935e1f", + "LastName":"Next Last", + "YearJoined":1999 + }, + { + "FirstName":"FirstName836d4c54-b227-4c1b-b684-de4cd940c251", + "LastName":"last1", + "YearJoined":1999 + }, + { + "FirstName":"FirstName5f53e895-921e-4130-8ed8-610b017f3b9b", + "LastName":"last2", + "YearJoined":1999 + }, + { + "FirstName":"FirstName9cf6b05f-38aa-47c1-9fd7-e3c1009cf3e4", + "LastName":"Last Last", + "YearJoined":1999 + } + ] ### Castle Dynamic Proxy Generator Exception error @@ -155,8 +152,8 @@ If you use the list builder functionality and get the following error: Then you need to mark all the public methods on your builder as virtual. This is because we are using Castle Dynamic Proxy to generate lists and it can't intercept non-virtual methods. -Create Entities Implicitly --------------------------- +## Create Entities Implicitly + In the previous examples, you have seen how to create entities *explicitly*, by calling the `Build()` and `BuildList()` methods. For the ultimate in terseness, you can omit these methods, and Dossier will *implicitly* call them for you. The one caveat is that you must explicitly declare the variable type rather than using the `var` keyword (unless you are passing into a method with the desired type). So, to create a single entity: @@ -175,46 +172,48 @@ Or to create a list of entities: List data = CustomerBuilder.CreateListOfSize(3) .TheFirst(1).WithFirstName("John"); -Create object without requiring custom builder class ----------------------------------------------------- +## Create object without requiring custom builder class -If you are building domain entities or other important classes having a custom builder class with intention-revealing method (e.g. WithFirstName) provides terseness (avoiding lambda expressions) and allows the builder class to start forming documentation about the usage of that object. +If you are building domain entities, or other important classes, having a custom builder class with intention-revealing method (e.g. WithFirstName) provides terseness (avoiding lambda expressions) and allows the builder class to start forming documentation about the usage of that object. Sometimes though, you just want to build a class without that ceremony. Typically, we find that this applies for view models and DTOs. -In that instance you can use the generic Builder implementation as shown below: +In that instance you can use the generic `Builder` implementation as shown below: + + StudentViewModel vm = Builder.CreateNew() + .Set(x => x.FirstName, "Pi") + .Set(x => x.LastName, "Lanningham") + .Set(x => x.EnrollmentDate, new DateTime(2000, 1, 1)); + + var studentViewModels = Builder.CreateListOfSize(5) + .TheFirst(1).Set(x => x.FirstName, "First") + .TheNext(1).Set(x => x.LastName, "Next Last") + .TheLast(1).Set(x => x.LastName, "Last Last") + .ThePrevious(2).With(b => b.Set(x => x.LastName, "last" + (++i).ToString())) + .All().Set(x => x.EnrollmentDate, _enrollmentDate) + .BuildList(); -```c# -StudentViewModel vm = Builder.CreateNew() - .Set(x => x.FirstName, "Pi") - .Set(x => x.LastName, "Lanningham") - .Set(x => x.EnrollmentDate, new DateTime(2000, 1, 1)); +The syntax is modelled closely against what NBuilder provides and the behaviour of the class should be very similar. -var studentViewModels = Builder.CreateListOfSize(5) - .TheFirst(1).Set(x => x.FirstName, "First") - .TheNext(1).Set(x => x.LastName, "Next Last") - .TheLast(1).Set(x => x.LastName, "Last Last") - .ThePrevious(2).With(b => b.Set(x => x.LastName, "last" + (++i).ToString())) - .All().Set(x => x.EnrollmentDate, _enrollmentDate) - .BuildList(); -``` +Note, that in the first example above, it was not necessary to call the `Build` method at the end of the method chain. This is because the `vm` variable has been defined as `StudentViewModel` and the C# compiler is able to infer the type and the object is set *implicitly*. -The syntax is modelled closely against what NBuilder provides and the behaviour of the class should be very similar. +In the second example, the `var` keyword is used to define `studentViewModels`, and so it is necessary to *explicitly* call `BuildList` to set the variable. ### Customising the construction of the object -By default the longest constructor of the class you specify will be called and then all properties (with public and private setters) will be set with values you specified (or anonymous values if none were specified). - -Sometimes you might not want this behaviour, in which case you can specify a custom construction factory (see build objects without calling constructor section for explanation of factories) as shown below: +By default, the longest constructor of the class you specify will be called and then all properties (with public and private setters) will be set with values you specified (or anonymous values if none were specified). -```c# -var dto = Builder.CreateNew(new CallConstructorFactory()).Build(); +Sometimes you might not want this behaviour, in which case you can specify a custom construction factory (see *Build objects without calling constructor* section for explanation of factories) as shown below: -var dtos = MixedAccessibilityDto dto = Builder.CreateListOfSize(5, new CallConstructorFactory()).BuildList(); -``` + var dto = Builder + .CreateNew(new CallConstructorFactory()) + .Build(); + + var dtos = MixedAccessibilityDto dto = Builder + .CreateListOfSize(5, new CallConstructorFactory()) + .BuildList(); -Build objects without calling constructor ------------------------------------------ +## Build objects without calling constructor When you extend the `TestDataBuilder` as part of creating a custom builder you will be forced to override the abstract `BuildObject` method. You have full flexibility to call the constructor of your class directly as shown above, but you can also invoke some convention-based factories to speed up the creation of your builder (also shown above) using the `BuildUsing` method. @@ -225,8 +224,7 @@ The `BuildUsing` method takes an instance of `IFactory`, of which you can create * `CallConstructorFactory` - Calls the longest constructor with builder values (or anonymous values if none set) based on case-insensitive match of constructor parameter names against property names * `AutoFixtureFactory` - Asks AutoFixture to create an anonymous instance of the class (note: does **not** use any builder values or anonymous values from Dossier) -Propogating the anonymous value fixture across builders -------------------------------------------------------- +## Propagating the anonymous value fixture across builders Within a particular instance of `AnonymousValueFixture`, which is created for every builder, any generators that return a sequence of values (e.g. unique values) will be maintained. If you want to ensure that the same anonymous value fixture is used across multiple related builders then: @@ -258,13 +256,11 @@ Within a particular instance of `AnonymousValueFixture`, which is created for ev There is currently no way to share an anonymous value fixture across unrelated builder instances. If this is something you need please raise an issue so we can discuss your requirement. -Anonymous Values and Equivalence Classes ----------------------------------------- +## Anonymous Values and Equivalence Classes todo: Coming soon! -How can I create proxy objects? -------------------------------- +## How can I create proxy objects? This library integrates with [NSubstitute](http://nsubstitute.github.io/) for generating proxy objects, this means you can call the `AsProxy` method on your builder to request that the result from calling `Build` will be an NSubstitute proxy with the public properties set to return the values you have specified via your builder, e.g. @@ -275,7 +271,6 @@ This library integrates with [NSubstitute](http://nsubstitute.github.io/) for ge If you need to alter the proxy before calling `Build` to add complex behaviours that can't be expressed by the default public properties returns values then you can override the `AlterProxy` method in your builder, e.g. -```c# class CustomerBuilder : TestDataBuilder { // ... @@ -300,12 +295,10 @@ If you need to alter the proxy before calling `Build` to add complex behaviours var customer = new CustomerBuilder().AsProxy().HasBeenMemberForYears(10); var years = customer.CustomerForHowManyYears(DateTime.Now); // 10 -``` *Remember that when using proxy objects of real classes that you need to mark properties and methods as virtual and have a protected empty constructor.* -Why does TestStack.Dossier have NSubstitute and AutoFixture as dependencies? ------------------------------------------------------------------------- +## Why does TestStack.Dossier have NSubstitute and AutoFixture as dependencies? TestStack.Dossier is an opinionated framework and as such prescribes how to build your fixture data, including how to build lists, anonymous data and mock objects. Because of this we have decided to bundle it with the best of breed libraries for this purpose: AutoFixture and NSubstitute. @@ -313,7 +306,6 @@ This allows for this library to provide a rich value-add on top of the basics of If you have a suggestion for the library that can incorporate this value-add without bundling these libraries feel free to submit a pull request. -Contributions / Questions -------------------------- +## Contributions / Questions If you would like to contribute to this project then feel free to communicate with Rob via Twitter (@robdmoore) or alternatively submit a pull request / issue. From 1c8fe7b2f9c42c7772204c5e93edf5d92af81bf1 Mon Sep 17 00:00:00 2001 From: Rob Moore Date: Sun, 17 May 2015 15:48:28 +0800 Subject: [PATCH 14/86] Fixing incorrect breaking change documentation --- BREAKING_CHANGES.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/BREAKING_CHANGES.md b/BREAKING_CHANGES.md index 7ac50d6..3d68b99 100644 --- a/BREAKING_CHANGES.md +++ b/BREAKING_CHANGES.md @@ -24,15 +24,15 @@ public interface IAnonymousValueSupplier } ``` -Note: the `GenerateAnonymousValue` method is no longer generic. +Note: the `CanSupplyValue` method and the `GenerateAnonymousValue` method are no longer generic. ### Reason -In order to implement the `BuildUsing` method that allows you to build an object by convention in one line rather than having to call the constructor yourself we needed to have a non-generic version of the method. This change actually ended up making the anonymous value suppliers slightly easier to implement (no longer any need for type casting). +In order to implement the `BuildUsing` method that allows you to build an object by convention in one line rather than having to call the constructor yourself we needed to have a non-generic version of the methods. This change actually ended up making the anonymous value suppliers slightly easier to implement (no longer any need for type casting). ### Fix -If you have any custom anonymous value suppliers change the signature of your `GenerateAnonymousValue` method so it's no logner generic. +If you have any custom anonymous value suppliers change the signature of your `CanSupplyValue` and `GenerateAnonymousValue` methods so they are no longer generic. Breaking change from NTestDataBuilder -> TestStack.Dossier 2.0 -------------------------------------------------------------- From bf636b8adba7e68c213c3e13fa6c50e12a9b0e9a Mon Sep 17 00:00:00 2001 From: Pi Lanningham Date: Mon, 18 May 2015 12:20:11 -0400 Subject: [PATCH 15/86] Adds a Set overload which takes a lambda factory method - The specific use case for this is that we wanted to be able to use equivalence classes. However, if you just use them naively, it would generate a single value and use it for all of the instances it created. - The lambda overload not only enables this case, but gives some power to constructing incrementing counters and the like. For example, using a Queue to generate an ordered set of names, or other such use cases. --- TestStack.Dossier.Tests/BuildTests.cs | 29 +++++++++++++++++++++- TestStack.Dossier/TestDataBuilder.cs | 35 +++++++++++++++++++-------- 2 files changed, 53 insertions(+), 11 deletions(-) diff --git a/TestStack.Dossier.Tests/BuildTests.cs b/TestStack.Dossier.Tests/BuildTests.cs index 9c6d1d4..010376a 100644 --- a/TestStack.Dossier.Tests/BuildTests.cs +++ b/TestStack.Dossier.Tests/BuildTests.cs @@ -1,4 +1,5 @@ -using Shouldly; +using System.Collections.Generic; +using Shouldly; using TestStack.Dossier.Tests.TestHelpers.Builders; using TestStack.Dossier.Tests.TestHelpers.Objects.Entities; using Xunit; @@ -47,6 +48,32 @@ public void GivenBuilder_WhenCallingSetExplicitly_ShouldOverrideValues() customer.YearJoined.ShouldBe(2014); } + [Fact] + public void GivenBuilder_WhenCallingSetWithLambda_ShouldInvokeEachTime() + { + int counter = 2014; + var builder = new CustomerBuilder() + .Set(x => x.FirstName, "Pi") + .Set(x => x.LastName, "Lanningham") + .Set(x => x.YearJoined, () => counter++); + + var customerA = builder.Build(); + var customerB = builder.Build(); + + customerA.YearJoined.ShouldBe(2014); + customerB.YearJoined.ShouldBe(2015); + + List customerList = CustomerBuilder.CreateListOfSize(10) + .All() + .Set(x => x.YearJoined, () => counter++); + int newCounter = 2016; + foreach (var c in customerList) + { + c.YearJoined.ShouldBe(newCounter++); + } + + } + [Fact] public void GivenBasicBuilder_WhenCallingBuildImplicitly_ThenReturnAnObject() { diff --git a/TestStack.Dossier/TestDataBuilder.cs b/TestStack.Dossier/TestDataBuilder.cs index 50e1167..c3fb0d3 100644 --- a/TestStack.Dossier/TestDataBuilder.cs +++ b/TestStack.Dossier/TestDataBuilder.cs @@ -16,6 +16,7 @@ public abstract class TestDataBuilder where TBuilder : TestDataBuilder, new() { private readonly Dictionary _properties = new Dictionary(StringComparer.InvariantCultureIgnoreCase); + private readonly Dictionary> _propFactories = new Dictionary>(); private ProxyBuilder _proxyBuilder; /// @@ -107,19 +108,32 @@ public TBuilder AsProxy() /// /// The proxy object protected virtual void AlterProxy(TObject proxy) {} - + /// /// Records the given value for the given property from {TObject} and returns the builder to allow chaining. /// /// The type of the property /// A lambda expression specifying the property to record a value for - /// The builder so that other method calls can be chained + /// The value to set the property to + /// The builder so that other method calls can be chained public virtual TBuilder Set(Expression> property, TValue value) { _properties[Reflector.GetPropertyNameFor(property)] = value; return this as TBuilder; } + /// + /// Records a given value provider for the given property from {TObject} and returns the builder to allow chaining. + /// + /// The type of the property + /// A lambda expression specifying the property to record a value for + /// A method which produces instances of {TValue} for the property. + public virtual TBuilder Set(Expression> property, Func factory) + { + _propFactories[Reflector.GetPropertyNameFor(property)] = () => factory() as object; + return this as TBuilder; + } + /// /// Gets the recorded value for the given property from {TObject} or an anonymous /// value if there isn't one specified. @@ -129,10 +143,7 @@ public virtual TBuilder Set(Expression> property, /// The recorded value of the property or an anonymous value for it public TValue Get(Expression> property) { - if (!Has(property)) - return Any.Get(property); - - return (TValue)_properties[Reflector.GetPropertyNameFor(property)]; + return (TValue)Get(typeof (TValue), Reflector.GetPropertyNameFor(property)); } /// @@ -144,9 +155,13 @@ public TValue Get(Expression> property) /// public object Get(Type type, string propertyName) { - if (!Has(propertyName)) - return Any.Get(type, propertyName); - return _properties[propertyName]; + object value; + if (_properties.TryGetValue(propertyName, out value)) return value; + + Func factory; + if (_propFactories.TryGetValue(propertyName, out factory)) return factory(); + + return Any.Get(type, propertyName); } /// @@ -193,7 +208,7 @@ protected bool Has(Expression> property) /// Whether or not there is a recorded value for the property protected bool Has(string propertyName) { - return _properties.ContainsKey(propertyName); + return _properties.ContainsKey(propertyName) || _propFactories.ContainsKey(propertyName); } /// From 6eaee0bb2549e098408ab69c333210dd000d5970 Mon Sep 17 00:00:00 2001 From: Pi Lanningham Date: Wed, 20 May 2015 19:50:27 -0400 Subject: [PATCH 16/86] Fixes up the set lambda, the function pattern now underlies other methods - It's a lot cleaner to use the factory lambdas as just constant functions for the other Set method. --- TestStack.Dossier.Tests/ProxyBuilderTests.cs | 25 ++++++++++---------- TestStack.Dossier/ProxyBuilder.cs | 9 +++---- TestStack.Dossier/TestDataBuilder.cs | 14 ++++------- 3 files changed, 23 insertions(+), 25 deletions(-) diff --git a/TestStack.Dossier.Tests/ProxyBuilderTests.cs b/TestStack.Dossier.Tests/ProxyBuilderTests.cs index e62b2a5..c6c662b 100644 --- a/TestStack.Dossier.Tests/ProxyBuilderTests.cs +++ b/TestStack.Dossier.Tests/ProxyBuilderTests.cs @@ -12,7 +12,7 @@ class ProxyBuilderTests [Fact] public void GivenClassToProxyWithNoProperties_WhenBuildingProxy_ReturnAClassWithNoReturnsValuesSet() { - var proxyBuilder = new ProxyBuilder(new Dictionary()); + var proxyBuilder = new ProxyBuilder(new Dictionary>()); var proxy = proxyBuilder.Build(); @@ -24,7 +24,7 @@ public void GivenClassToProxyWithNoProperties_WhenBuildingProxy_ReturnAClassWith [Fact] public void GivenClassToProxyWithNoProperties_WhenBuildingProxy_ReturnAnNSubstituteProxyOfThatClass() { - var proxyBuilder = new ProxyBuilder(new Dictionary()); + var proxyBuilder = new ProxyBuilder(new Dictionary>()); var proxy = proxyBuilder.Build(); @@ -32,13 +32,14 @@ public void GivenClassToProxyWithNoProperties_WhenBuildingProxy_ReturnAnNSubstit } [Fact] - public void GivenClassToProxyWithSinglePropertyValue_WhenBuildingProxy_ReturnAClassWithReturnValueSet() + public void GivenClassToProxyWithSinglePropertyValue_WhenBuildingProxy_ReturnAClassWithReturnValueSetFromFunction() { - var proxyBuilder = new ProxyBuilder(new Dictionary {{"FirstName", "FirstName"}}); + int nonce = new Random().Next(0, 100); + var proxyBuilder = new ProxyBuilder(new Dictionary> {{"FirstName", () => "FirstName" + nonce}}); var proxy = proxyBuilder.Build(); - proxy.FirstName.ShouldBe("FirstName"); + proxy.FirstName.ShouldBe("FirstName" + nonce); proxy.LastName.ShouldBe(string.Empty); proxy.YearJoined.ShouldBe(0); } @@ -46,11 +47,11 @@ public void GivenClassToProxyWithSinglePropertyValue_WhenBuildingProxy_ReturnACl [Fact] public void GivenClassToProxyWithMultiplePropertyValues_WhenBuildingProxy_ReturnAClassWithReturnValueSet() { - var proxyBuilder = new ProxyBuilder(new Dictionary + var proxyBuilder = new ProxyBuilder(new Dictionary> { - { "FirstName", "FirstName" }, - { "LastName", "LastName" }, - { "YearJoined", 1 }, + { "FirstName", () => "FirstName" }, + { "LastName", () => "LastName" }, + { "YearJoined", () => 1 }, } ); @@ -64,10 +65,10 @@ public void GivenClassToProxyWithMultiplePropertyValues_WhenBuildingProxy_Return [Fact] public void GivenClassWithSomeVirtualProperties_WhenBuildingProxy_ThenOnlyVirtualMembersAreProxied() { - var proxyBuilder = new ProxyBuilder(new Dictionary() + var proxyBuilder = new ProxyBuilder(new Dictionary>() { - {"Name", "Vandelay Industries"}, - {"EmployeeCount", 100} + {"Name", () => "Vandelay Industries"}, + {"EmployeeCount", () => 100} }); var proxy = proxyBuilder.Build(); diff --git a/TestStack.Dossier/ProxyBuilder.cs b/TestStack.Dossier/ProxyBuilder.cs index 5a7ff05..0efd431 100644 --- a/TestStack.Dossier/ProxyBuilder.cs +++ b/TestStack.Dossier/ProxyBuilder.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Linq; using System.Reflection; using NSubstitute; @@ -11,13 +12,13 @@ namespace TestStack.Dossier /// The type being proxied public class ProxyBuilder where T : class { - private readonly Dictionary _properties; + private readonly Dictionary> _properties; /// /// Create a proxy builder to proxy the given property values for the type {T}. /// /// - public ProxyBuilder(Dictionary properties) + public ProxyBuilder(Dictionary> properties) { _properties = properties; } @@ -33,7 +34,7 @@ public T Build() foreach (var property in properties.Where(property => _properties.ContainsKey(property.Name))) { if (property.GetGetMethod().IsVirtual) - property.GetValue(proxy, null).Returns(_properties[property.Name]); + property.GetValue(proxy, null).Returns(_properties[property.Name]()); } return proxy; diff --git a/TestStack.Dossier/TestDataBuilder.cs b/TestStack.Dossier/TestDataBuilder.cs index c3fb0d3..a571dd3 100644 --- a/TestStack.Dossier/TestDataBuilder.cs +++ b/TestStack.Dossier/TestDataBuilder.cs @@ -15,8 +15,7 @@ public abstract class TestDataBuilder where TObject : class where TBuilder : TestDataBuilder, new() { - private readonly Dictionary _properties = new Dictionary(StringComparer.InvariantCultureIgnoreCase); - private readonly Dictionary> _propFactories = new Dictionary>(); + private readonly Dictionary> _properties = new Dictionary>(); private ProxyBuilder _proxyBuilder; /// @@ -118,7 +117,7 @@ protected virtual void AlterProxy(TObject proxy) {} /// The builder so that other method calls can be chained public virtual TBuilder Set(Expression> property, TValue value) { - _properties[Reflector.GetPropertyNameFor(property)] = value; + _properties[Reflector.GetPropertyNameFor(property)] = () => value; return this as TBuilder; } @@ -130,7 +129,7 @@ public virtual TBuilder Set(Expression> property, /// A method which produces instances of {TValue} for the property. public virtual TBuilder Set(Expression> property, Func factory) { - _propFactories[Reflector.GetPropertyNameFor(property)] = () => factory() as object; + _properties[Reflector.GetPropertyNameFor(property)] = () => factory() as object; return this as TBuilder; } @@ -155,11 +154,8 @@ public TValue Get(Expression> property) /// public object Get(Type type, string propertyName) { - object value; - if (_properties.TryGetValue(propertyName, out value)) return value; - Func factory; - if (_propFactories.TryGetValue(propertyName, out factory)) return factory(); + if (_properties.TryGetValue(propertyName, out factory)) return factory(); return Any.Get(type, propertyName); } @@ -208,7 +204,7 @@ protected bool Has(Expression> property) /// Whether or not there is a recorded value for the property protected bool Has(string propertyName) { - return _properties.ContainsKey(propertyName) || _propFactories.ContainsKey(propertyName); + return _properties.ContainsKey(propertyName); } /// From 0d13e75a0d6cacdabe7fe06ae52b23aa9d57dfbe Mon Sep 17 00:00:00 2001 From: Pi Lanningham Date: Wed, 20 May 2015 19:52:04 -0400 Subject: [PATCH 17/86] Fixes a doc comment --- TestStack.Dossier/TestDataBuilder.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/TestStack.Dossier/TestDataBuilder.cs b/TestStack.Dossier/TestDataBuilder.cs index a571dd3..97b9697 100644 --- a/TestStack.Dossier/TestDataBuilder.cs +++ b/TestStack.Dossier/TestDataBuilder.cs @@ -127,6 +127,7 @@ public virtual TBuilder Set(Expression> property, /// The type of the property /// A lambda expression specifying the property to record a value for /// A method which produces instances of {TValue} for the property. + /// The builder so that other method calls can be chained public virtual TBuilder Set(Expression> property, Func factory) { _properties[Reflector.GetPropertyNameFor(property)] = () => factory() as object; From 3b4bc6303c2aad116af9b7ab1a6115e60ad2a461 Mon Sep 17 00:00:00 2001 From: Pi Lanningham Date: Thu, 21 May 2015 00:47:17 -0400 Subject: [PATCH 18/86] Added the start of a contributor guidelines file - This will help new contributors get started, and keep them from stepping on anyone's stylistic toes. - Expand as you see fit! --- CONTRIBUTOR_GUIDELINES.md | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 CONTRIBUTOR_GUIDELINES.md diff --git a/CONTRIBUTOR_GUIDELINES.md b/CONTRIBUTOR_GUIDELINES.md new file mode 100644 index 0000000..214b5b0 --- /dev/null +++ b/CONTRIBUTOR_GUIDELINES.md @@ -0,0 +1,11 @@ +Contributor Guidelines +====================== + +Hi! Thank you for your interest in contributing to this open source library! +We ask that you follow the following style guidelines when submitting pull +requests, to keep the code consistent and maintainable. + + - Do not put an if clause and it's statement on the same line: separate them + with a new-line and indent accordingly. + +(This file will be expanded as more guidelines are established by the maintainer) \ No newline at end of file From 1d1d47d577c5412f8ddc66291a8cb0cc8fbd9c81 Mon Sep 17 00:00:00 2001 From: Pi Lanningham Date: Thu, 21 May 2015 00:47:38 -0400 Subject: [PATCH 19/86] Fixes a stylistic issue with ifs and statements on the same line --- TestStack.Dossier/TestDataBuilder.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/TestStack.Dossier/TestDataBuilder.cs b/TestStack.Dossier/TestDataBuilder.cs index 97b9697..24edb91 100644 --- a/TestStack.Dossier/TestDataBuilder.cs +++ b/TestStack.Dossier/TestDataBuilder.cs @@ -156,7 +156,8 @@ public TValue Get(Expression> property) public object Get(Type type, string propertyName) { Func factory; - if (_properties.TryGetValue(propertyName, out factory)) return factory(); + if (_properties.TryGetValue(propertyName, out factory)) + return factory(); return Any.Get(type, propertyName); } From f5b5e95f1b639411b9f348db13ee14785ec6029f Mon Sep 17 00:00:00 2001 From: Rob Moore Date: Sun, 24 May 2015 21:51:27 +0800 Subject: [PATCH 20/86] Bumping minor for the new feature --- NextVersion.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NextVersion.txt b/NextVersion.txt index 56fea8a..a0cd9f0 100644 --- a/NextVersion.txt +++ b/NextVersion.txt @@ -1 +1 @@ -3.0.0 \ No newline at end of file +3.1.0 \ No newline at end of file From 6e1f2aac3cda47c6e0b77e9af54794c98a79b9df Mon Sep 17 00:00:00 2001 From: Rob Moore Date: Sun, 24 May 2015 22:00:25 +0800 Subject: [PATCH 21/86] Moved new tests to a more appropriate place with a more appropriate type (you typically wouldn't use Set for a domain object builder) --- TestStack.Dossier.Tests/BuildTests.cs | 26 ------------------- .../Builder_CreateListTests.cs | 17 ++++++++++-- .../Builder_CreateNewTests.cs | 25 +++++++++++++++--- 3 files changed, 36 insertions(+), 32 deletions(-) diff --git a/TestStack.Dossier.Tests/BuildTests.cs b/TestStack.Dossier.Tests/BuildTests.cs index 010376a..8067a7a 100644 --- a/TestStack.Dossier.Tests/BuildTests.cs +++ b/TestStack.Dossier.Tests/BuildTests.cs @@ -48,32 +48,6 @@ public void GivenBuilder_WhenCallingSetExplicitly_ShouldOverrideValues() customer.YearJoined.ShouldBe(2014); } - [Fact] - public void GivenBuilder_WhenCallingSetWithLambda_ShouldInvokeEachTime() - { - int counter = 2014; - var builder = new CustomerBuilder() - .Set(x => x.FirstName, "Pi") - .Set(x => x.LastName, "Lanningham") - .Set(x => x.YearJoined, () => counter++); - - var customerA = builder.Build(); - var customerB = builder.Build(); - - customerA.YearJoined.ShouldBe(2014); - customerB.YearJoined.ShouldBe(2015); - - List customerList = CustomerBuilder.CreateListOfSize(10) - .All() - .Set(x => x.YearJoined, () => counter++); - int newCounter = 2016; - foreach (var c in customerList) - { - c.YearJoined.ShouldBe(newCounter++); - } - - } - [Fact] public void GivenBasicBuilder_WhenCallingBuildImplicitly_ThenReturnAnObject() { diff --git a/TestStack.Dossier.Tests/Builder_CreateListTests.cs b/TestStack.Dossier.Tests/Builder_CreateListTests.cs index 5ad8c51..62be8bc 100644 --- a/TestStack.Dossier.Tests/Builder_CreateListTests.cs +++ b/TestStack.Dossier.Tests/Builder_CreateListTests.cs @@ -170,7 +170,7 @@ public void WhenBuildingObjectsImplicitly_ThenTheAnonymousValueFixtureIsSharedAc studentViewModels.Select(x => x.Grade).ShouldBeUnique(); } - public void WhenBuildingObjectsWithCtorAndPrivateSetters_ShouldSetPrivateSettersByDefault() + public void WhenBuildingObjectsWithCtorAndPrivateSetters_ThenSetPrivateSettersByDefault() { var dto = Builder.CreateListOfSize(1) .TheFirst(1) @@ -188,7 +188,7 @@ public void WhenBuildingObjectsWithCtorAndPrivateSetters_ShouldSetPrivateSetters } [Fact] - public void GivenBuilderListWithFactoryOverride_WhenBuildingObjects_ShouldRespectOverriddenFactory() + public void GivenBuilderListWithFactoryOverride_WhenBuildingObjects_ThenRespectOverriddenFactory() { var dto = Builder.CreateListOfSize(1, new CallConstructorFactory()) .TheFirst(1) @@ -204,5 +204,18 @@ public void GivenBuilderListWithFactoryOverride_WhenBuildingObjects_ShouldRespec dto.NotSetByCtorWithPrivateSetter.ShouldNotBe("3"); dto.NotSetByCtorWithPublicSetter.ShouldNotBe("4"); } + + [Fact] + public void GivenBuilder_WhenCallingSetWithLambda_ThenInvokeEachTime() + { + var grade = Grade.A; + var customers = Builder.CreateListOfSize(10) + .All().Set(x => x.Grade, () => grade++) + .BuildList(); + + var gradeAssertion = Grade.A; + foreach (var c in customers) + c.Grade.ShouldBe(gradeAssertion++); + } } } \ No newline at end of file diff --git a/TestStack.Dossier.Tests/Builder_CreateNewTests.cs b/TestStack.Dossier.Tests/Builder_CreateNewTests.cs index 3581856..de36834 100644 --- a/TestStack.Dossier.Tests/Builder_CreateNewTests.cs +++ b/TestStack.Dossier.Tests/Builder_CreateNewTests.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using Shouldly; using TestStack.Dossier.Factories; using TestStack.Dossier.Tests.TestHelpers.Objects.Examples; @@ -29,7 +30,7 @@ public void GivenBuilder_WhenCallingBuildImplicitly_ThenReturnAnObject() } [Fact] - public void GivenBuilderWithModifications_WhenCallingBuildExplicitly_ShouldOverrideValues() + public void GivenBuilderWithModifications_WhenCallingBuildExplicitly_ThenOverrideValues() { var builder = Builder.CreateNew() .Set(x => x.FirstName, "Pi") @@ -44,7 +45,7 @@ public void GivenBuilderWithModifications_WhenCallingBuildExplicitly_ShouldOverr } [Fact] - public void GivenBuilderWithModifications_WhenCallingBuildImplicitly_ShouldOverrideValues() + public void GivenBuilderWithModifications_WhenCallingBuildImplicitly_ThenOverrideValues() { StudentViewModel vm = Builder.CreateNew() .Set(x => x.FirstName, "Pi") @@ -57,7 +58,7 @@ public void GivenBuilderWithModifications_WhenCallingBuildImplicitly_ShouldOverr } [Fact] - public void GivenBuilder_WhenBuildingObjectWithCtorAndPrivateSetters_ShouldSetPrivateSettersByDefault() + public void GivenBuilder_WhenBuildingObjectWithCtorAndPrivateSetters_ThenSetPrivateSettersByDefault() { MixedAccessibilityDto dto = Builder.CreateNew() .Set(x => x.SetByCtorWithPublicSetter, "1") @@ -72,7 +73,7 @@ public void GivenBuilder_WhenBuildingObjectWithCtorAndPrivateSetters_ShouldSetPr } [Fact] - public void GivenBuilderWithFactoryOverride_WhenBuildingObject_ShouldRespectOverriddenFactory() + public void GivenBuilderWithFactoryOverride_WhenBuildingObject_ThenRespectOverriddenFactory() { MixedAccessibilityDto dto = Builder.CreateNew(new CallConstructorFactory()) .Set(x => x.SetByCtorWithPublicSetter, "1") @@ -85,5 +86,21 @@ public void GivenBuilderWithFactoryOverride_WhenBuildingObject_ShouldRespectOver dto.NotSetByCtorWithPrivateSetter.ShouldNotBe("3"); dto.NotSetByCtorWithPublicSetter.ShouldNotBe("4"); } + + [Fact] + public void GivenBuilder_WhenCallingSetWithLambda_ThenInvokeEachTime() + { + var grade = Grade.A; + var builder = Builder.CreateNew() + .Set(x => x.FirstName, "Pi") + .Set(x => x.LastName, "Lanningham") + .Set(x => x.Grade, () => grade++); + + var customerA = builder.Build(); + var customerB = builder.Build(); + + customerA.Grade.ShouldBe(Grade.A); + customerB.Grade.ShouldBe(Grade.B); + } } } \ No newline at end of file From 075913f325f768d21bed415aa3965fbc261b56f6 Mon Sep 17 00:00:00 2001 From: Rob Moore Date: Sun, 24 May 2015 22:15:20 +0800 Subject: [PATCH 22/86] Updated contributor and readme documentation --- CONTRIBUTING.md | 15 +++ CONTRIBUTOR_GUIDELINES.md | 11 -- README.md | 204 +++++--------------------------------- 3 files changed, 39 insertions(+), 191 deletions(-) create mode 100644 CONTRIBUTING.md delete mode 100644 CONTRIBUTOR_GUIDELINES.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..506dae4 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,15 @@ +Contributor Guidelines +====================== + +Hi! Thank you for your interest in contributing to this open source library! + +We welcome issues and pull requests. If you are starting on something major +please raise an issue first so we can discuss it with you, make sure it fits +in with the direction of the project and provide appropriate assistance :) + +We ask that you follow the following style guidelines when submitting pull +requests, to keep the code consistent and maintainable. + + - In general - follow the default ReSharper suggestions + - Do not put a single line if clause on the same line as the if statement it + belongs to; separate them with a new-line and an indent diff --git a/CONTRIBUTOR_GUIDELINES.md b/CONTRIBUTOR_GUIDELINES.md deleted file mode 100644 index 214b5b0..0000000 --- a/CONTRIBUTOR_GUIDELINES.md +++ /dev/null @@ -1,11 +0,0 @@ -Contributor Guidelines -====================== - -Hi! Thank you for your interest in contributing to this open source library! -We ask that you follow the following style guidelines when submitting pull -requests, to keep the code consistent and maintainable. - - - Do not put an if clause and it's statement on the same line: separate them - with a new-line and indent accordingly. - -(This file will be expanded as more guidelines are established by the maintainer) \ No newline at end of file diff --git a/README.md b/README.md index 70a146c..e778095 100644 --- a/README.md +++ b/README.md @@ -8,11 +8,16 @@ TestStack.Dossier is integrated with NSubstitute for proxy/mock/substitute objec Prior to v2.0 this library was known as NTestDataBuilder. -## How do I get started? +## Getting started - building a single object 1. `Install-Package TestStack.Dossier` -2. Create a builder class for one of your domain objects, e.g. if you have a customer: +2. Are you building a DTO, view model, or other class you don't want to write a custom + test data builder class for? If so then check out our [generic test data builder implementation](http://dossier.teststack.net/v1.0/docs/create-object-without-requiring-custom-builder-cla) + +3. If you want to build a custom builder class, e.g. for a domain object, so you can use the builder + as documentation and also to make the experience of building that class in your tests more rich + then you need to extend the TestDataBuilder class like in the following code example: // Customer.cs @@ -46,11 +51,14 @@ Prior to v2.0 this library was known as NTestDataBuilder. // CustomerBuilder.cs + // Yep - you have to provide the custom builder type in as a generic type argument + // it's a bit weird, but necessary for the fluent chaining to work from the base class public class CustomerBuilder : TestDataBuilder { public CustomerBuilder() { - // Can set up defaults here - any that you don't set or subsequently override will have an anonymous value generated by default. + // Can set up defaults here - any that you don't set or subsequently override + // will have an anonymous value generated by default WhoJoinedIn(2013); } @@ -60,7 +68,8 @@ Prior to v2.0 this library was known as NTestDataBuilder. return Set(x => x.FirstName, firstName); } - // Note: we typically only start with the methods that are strictly needed so the builders are quick to write and aren't bloated' + // Note: we typically only start with the methods that are strictly needed so the + // builders are quick to write and aren't bloated' public virtual CustomerBuilder WithLastName(string lastName) { return Set(x => x.LastName, lastName); @@ -71,27 +80,28 @@ Prior to v2.0 this library was known as NTestDataBuilder. return Set(x => x.YearJoined, yearJoined); } + // This method is optional, by default it uses `BuildUsing()` protected override Customer BuildObject() { + return BuildUsing(); + // or, if you need more control / can't use the auto-construction assumptions return new Customer( Get(x => x.FirstName), Get(x => x.LastName), Get(x => x.YearJoined) ); - // or - return BuildUsing(); } } -3. Use the builder in a test, e.g. +4. Use the builder in a test, e.g. var customer = new CustomerBuilder() .WithFirstName("Robert") .Build(); -4. Consider using the Object Mother pattern in combination with the builders, see [my blog post](http://robdmoore.id.au/blog/2013/05/26/test-data-generation-the-right-way-object-mother-test-data-builders-nsubstitute-nbuilder/) for a description of how I use this library. +5. Consider using the Object Mother pattern in combination with the builders, see [my blog post](http://robdmoore.id.au/blog/2013/05/26/test-data-generation-the-right-way-object-mother-test-data-builders-nsubstitute-nbuilder/) for a description of how I use this library. -## How can I create a list of entities using my builders? +## Getting started - building a list of objects This library allows you to build a list of entities fluently and tersely. Here is an example: @@ -103,7 +113,7 @@ This library allows you to build a list of entities fluently and tersely. Here i .All().WhoJoinedIn(1999) .BuildList(); -This would create the following (represented as json): +This would create the following (represented as json) - note the anonymous values that are generated: [ { @@ -133,179 +143,13 @@ This would create the following (represented as json): } ] -### Castle Dynamic Proxy Generator Exception error - -If you use the list builder functionality and get the following error: - -> Castle.DynamicProxy.Generators.GeneratorException: Can not create proxy for type because it is not accessible. Make it public, or internal and mark your assembly with [assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")] attribute, because assembly is not strong-named. - -Then you either need to: - -* Make your builder class public -* Add the following to your `AssemblyInfo.cs` file: `[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")]` - -### Non-virtual method Invalid Operation Exception - -If you use the list builder functionality and get the following error: - -> System.InvalidOperationException: Tried to build a list with a builder who has non-virtual method. Please make on type virtual. - -Then you need to mark all the public methods on your builder as virtual. This is because we are using Castle Dynamic Proxy to generate lists and it can't intercept non-virtual methods. - -## Create Entities Implicitly - -In the previous examples, you have seen how to create entities *explicitly*, by calling the `Build()` and `BuildList()` methods. For the ultimate in terseness, you can omit these methods, and Dossier will *implicitly* call them for you. The one caveat is that you must explicitly declare the variable type rather than using the `var` keyword (unless you are passing into a method with the desired type). - -So, to create a single entity: - - Customer customer = new CustomerBuilder(); - - Customer customer = new CustomerBuilder() - .WithFirstName("Matt") - .WithLastName("Kocaj") - .WhoJoinedIn(2010); - -Or to create a list of entities: - - List entities = CustomerBuilder.CreateListOfSize(5); - - List data = CustomerBuilder.CreateListOfSize(3) - .TheFirst(1).WithFirstName("John"); - -## Create object without requiring custom builder class - -If you are building domain entities, or other important classes, having a custom builder class with intention-revealing method (e.g. WithFirstName) provides terseness (avoiding lambda expressions) and allows the builder class to start forming documentation about the usage of that object. - -Sometimes though, you just want to build a class without that ceremony. Typically, we find that this applies for view models and DTOs. - -In that instance you can use the generic `Builder` implementation as shown below: - - StudentViewModel vm = Builder.CreateNew() - .Set(x => x.FirstName, "Pi") - .Set(x => x.LastName, "Lanningham") - .Set(x => x.EnrollmentDate, new DateTime(2000, 1, 1)); - - var studentViewModels = Builder.CreateListOfSize(5) - .TheFirst(1).Set(x => x.FirstName, "First") - .TheNext(1).Set(x => x.LastName, "Next Last") - .TheLast(1).Set(x => x.LastName, "Last Last") - .ThePrevious(2).With(b => b.Set(x => x.LastName, "last" + (++i).ToString())) - .All().Set(x => x.EnrollmentDate, _enrollmentDate) - .BuildList(); - -The syntax is modelled closely against what NBuilder provides and the behaviour of the class should be very similar. - -Note, that in the first example above, it was not necessary to call the `Build` method at the end of the method chain. This is because the `vm` variable has been defined as `StudentViewModel` and the C# compiler is able to infer the type and the object is set *implicitly*. - -In the second example, the `var` keyword is used to define `studentViewModels`, and so it is necessary to *explicitly* call `BuildList` to set the variable. - -### Customising the construction of the object - -By default, the longest constructor of the class you specify will be called and then all properties (with public and private setters) will be set with values you specified (or anonymous values if none were specified). - -Sometimes you might not want this behaviour, in which case you can specify a custom construction factory (see *Build objects without calling constructor* section for explanation of factories) as shown below: - - var dto = Builder - .CreateNew(new CallConstructorFactory()) - .Build(); - - var dtos = MixedAccessibilityDto dto = Builder - .CreateListOfSize(5, new CallConstructorFactory()) - .BuildList(); - -## Build objects without calling constructor - -When you extend the `TestDataBuilder` as part of creating a custom builder you will be forced to override the abstract `BuildObject` method. You have full flexibility to call the constructor of your class directly as shown above, but you can also invoke some convention-based factories to speed up the creation of your builder (also shown above) using the `BuildUsing` method. - -The `BuildUsing` method takes an instance of `IFactory`, of which you can create your own factory implementation that takes into account your own conventions or you can use one of the built-in ones: - -* `AllPropertiesFactory` - Calls the longest constructor with builder values (or anonymous values if none set) based on case-insensitive match of constructor parameter names against property names and then calls the setter on all properties (public or private) with builder values (or anonymous values if none set) -* `PublicPropertySettersFactory` - Calls the longest constructor with builder values (or anonymous values if none set) based on case-insensitive match of constructor parameter names against property names and then calls the setter on all properties with public setters with builder values (or anonymous values if none set) -* `CallConstructorFactory` - Calls the longest constructor with builder values (or anonymous values if none set) based on case-insensitive match of constructor parameter names against property names -* `AutoFixtureFactory` - Asks AutoFixture to create an anonymous instance of the class (note: does **not** use any builder values or anonymous values from Dossier) - -## Propagating the anonymous value fixture across builders - -Within a particular instance of `AnonymousValueFixture`, which is created for every builder, any generators that return a sequence of values (e.g. unique values) will be maintained. If you want to ensure that the same anonymous value fixture is used across multiple related builders then: - -* Using `CreateListOfSize` will automatically propagate the anonymous value fixture across builders -* Call the `GetChildBuilder(Func modifier = null)` method from within your custom builder, e.g.: - - public MyCustomBuilder WithSomeValue(Func modifier = null) - { - return Set(x => x.SomeValue, GetChildBuilder(modifier)); - } -* If using `Builder` then call the `SetUsingBuilder` method, e.g.: - - // Uses Builder - Builder.CreateNew() - .SetUsingBuilder(x => x.Address) - .Build() - // Uses Builder, includes customisation - Builder.CreateNew() - .SetUsingBuilder(x => x.Address, b => b.Set(y => y.Street, "A street")) - .Build() - // Uses AddressBuilder - Builder.CreateNew() - .SetUsingBuilder(x => x.Address) - .Build() - // Uses AddressBuilder, includes customisation - Builder.CreateNew() - .SetUsingBuilder(x => x.Address, b => b.Set(y => y.Street, "A street")) - .Build() - -There is currently no way to share an anonymous value fixture across unrelated builder instances. If this is something you need please raise an issue so we can discuss your requirement. - -## Anonymous Values and Equivalence Classes - -todo: Coming soon! - -## How can I create proxy objects? - -This library integrates with [NSubstitute](http://nsubstitute.github.io/) for generating proxy objects, this means you can call the `AsProxy` method on your builder to request that the result from calling `Build` will be an NSubstitute proxy with the public properties set to return the values you have specified via your builder, e.g. - - var customer = CustomerBuilder.WithFirstName("Rob").AsProxy().Build(); - customer.CustomerForHowManyYears(Arg.Any()).Returns(10); - var name = customer.FirstName; // "Rob" - var years = customer.CustomerForHowManyYears(DateTime.Now); // 10 - -If you need to alter the proxy before calling `Build` to add complex behaviours that can't be expressed by the default public properties returns values then you can override the `AlterProxy` method in your builder, e.g. - - class CustomerBuilder : TestDataBuilder - { - // ... - - private int _years; - - public CustomerBuilder HasBeenMemberForYears(int years) - { - _years = years; - return this; - } - - protected override void AlterProxy(Customer proxy) - { - proxy.CustomerForHowManyYears(Arg.Any()).Returns(_years); - } - - // ... - } - - // Then in your test you can use: - - var customer = new CustomerBuilder().AsProxy().HasBeenMemberForYears(10); - var years = customer.CustomerForHowManyYears(DateTime.Now); // 10 - -*Remember that when using proxy objects of real classes that you need to mark properties and methods as virtual and have a protected empty constructor.* - -## Why does TestStack.Dossier have NSubstitute and AutoFixture as dependencies? -TestStack.Dossier is an opinionated framework and as such prescribes how to build your fixture data, including how to build lists, anonymous data and mock objects. Because of this we have decided to bundle it with the best of breed libraries for this purpose: AutoFixture and NSubstitute. +The same works with the generic `Builder` implementation too. -This allows for this library to provide a rich value-add on top of the basics of tracking properties in a dictionary in the `TestDataBuilder` base class. If you want to use different libraries or want a cut down version that doesn't come with NSubstitute or AutoFixture and the extra functionality they bring then take the `TestDataBuilder.cs` file and cut out the bits you don't want - open source ftw :). +## Documentation -If you have a suggestion for the library that can incorporate this value-add without bundling these libraries feel free to submit a pull request. +More comprehensive documentation is available on our [documentation website](http://dossier.teststack.net/). ## Contributions / Questions -If you would like to contribute to this project then feel free to communicate with Rob via Twitter (@robdmoore) or alternatively submit a pull request / issue. +If you would like to contribute to this project then feel free to communicate with us via Twitter ([]@teststacknet](https://twitter.com/teststacknet)) or alternatively submit a [pull request](https://github.com/TestStack/TestStack.Dossier/compare/) / [issue](https://github.com/TestStack/TestStack.Dossier/issues/new). From df1a60054e5c3b3fd169806a4fad1b0115b4c5d4 Mon Sep 17 00:00:00 2001 From: Rob Moore Date: Sun, 24 May 2015 23:36:17 +0800 Subject: [PATCH 23/86] Further doco update --- README.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index e778095..78c9fba 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # TestStack.Dossier -TestStack.Dossier provides you with the code infrastructure to easily and quickly generate test fixture data for your automated tests in a terse, readable and maintainable way using the Test Data Builder pattern. +TestStack.Dossier provides you with the code infrastructure to easily and quickly generate test fixture data for your automated tests in a terse, readable and maintainable way using the Test Data Builder, anonymous value and equivalence class patterns. For more information please see the [blog post](http://robdmoore.id.au/blog/2013/05/26/test-data-generation-the-right-way-object-mother-test-data-builders-nsubstitute-nbuilder/) that gives the theory behind the approach this library was intended for and the [presentation and example code](https://github.com/robdmoore/TestFixtureDataGenerationPresentation) that gives a concrete example of the usage of the library (and the theory behind it). @@ -69,7 +69,7 @@ Prior to v2.0 this library was known as NTestDataBuilder. } // Note: we typically only start with the methods that are strictly needed so the - // builders are quick to write and aren't bloated' + // builders are quick to write and aren't bloated public virtual CustomerBuilder WithLastName(string lastName) { return Set(x => x.LastName, lastName); @@ -152,4 +152,6 @@ More comprehensive documentation is available on our [documentation website](htt ## Contributions / Questions -If you would like to contribute to this project then feel free to communicate with us via Twitter ([]@teststacknet](https://twitter.com/teststacknet)) or alternatively submit a [pull request](https://github.com/TestStack/TestStack.Dossier/compare/) / [issue](https://github.com/TestStack/TestStack.Dossier/issues/new). +If you would like to contribute to this project then feel free to communicate with us via Twitter ([@teststacknet](https://twitter.com/teststacknet)) or alternatively submit a [pull request](https://github.com/TestStack/TestStack.Dossier/compare/) / [issue](https://github.com/TestStack/TestStack.Dossier/issues/new). + +Feel free to check out our [up-for-grabs issues if you don't know where to start](https://github.com/TestStack/TestStack.Dossier/labels/up-for-grabs). \ No newline at end of file From a28dffd5eefebf31edc261d6118a98122b060e35 Mon Sep 17 00:00:00 2001 From: Rob Moore Date: Thu, 18 Jun 2015 22:22:04 +0800 Subject: [PATCH 24/86] Added contributing.md to the .sln --- TestStack.Dossier.sln | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/TestStack.Dossier.sln b/TestStack.Dossier.sln index 954293b..f467254 100644 --- a/TestStack.Dossier.sln +++ b/TestStack.Dossier.sln @@ -1,11 +1,12 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 2013 -VisualStudioVersion = 12.0.30723.0 +VisualStudioVersion = 12.0.31101.0 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{BC8508D1-6FCB-46B2-9C14-F41F6AD76B09}" ProjectSection(SolutionItems) = preProject BREAKING_CHANGES.md = BREAKING_CHANGES.md + CONTRIBUTING.md = CONTRIBUTING.md LICENSE = LICENSE logo.png = logo.png NextVersion.txt = NextVersion.txt From fc2660016fa8c9549ad6b08f24ab1e778834d087 Mon Sep 17 00:00:00 2001 From: Rob Moore Date: Thu, 18 Jun 2015 22:33:51 +0800 Subject: [PATCH 25/86] Added failing test for #40 --- TestStack.Dossier.Tests/BuildListTests.cs | 19 +++++++++++++++++++ .../Builders/BuilderWithDefaults.cs | 16 ++++++++++++++++ .../TestStack.Dossier.Tests.csproj | 1 + 3 files changed, 36 insertions(+) create mode 100644 TestStack.Dossier.Tests/TestHelpers/Builders/BuilderWithDefaults.cs diff --git a/TestStack.Dossier.Tests/BuildListTests.cs b/TestStack.Dossier.Tests/BuildListTests.cs index 5e0e15b..5c28a61 100644 --- a/TestStack.Dossier.Tests/BuildListTests.cs +++ b/TestStack.Dossier.Tests/BuildListTests.cs @@ -172,5 +172,24 @@ public void WhenBuildingEntitiesImplicitly_ThenTheAnonymousValueFixtureIsSharedA customers[3].CustomerClass.ShouldBe(CustomerClass.Gold); customers[4].CustomerClass.ShouldBe(CustomerClass.Platinum); } + + [Fact] + public void GivenBuilderWithSetCallsInConstructor_WhenBuildingAListOfTheBuilders_ThenDefaultValuesShouldBeRespectedUnlessOverridden() + { + const string overriddenFirstName = "FirstOverride"; + const string overriddenLastName = "LastOverride"; + + var customers = BuilderWithDefaults.CreateListOfSize(3) + .TheFirst(1).With(x => x.Set(y => y.FirstName, overriddenFirstName)) + .TheNext(1).With(x => x.Set(y => y.LastName, overriddenLastName)) + .BuildList(); + + customers[0].FirstName.ShouldBe(overriddenFirstName); + customers[0].LastName.ShouldBe(BuilderWithDefaults.DefaultLastName); + customers[1].FirstName.ShouldBe(BuilderWithDefaults.DefaultFirstName); + customers[1].LastName.ShouldBe(overriddenLastName); + customers[2].FirstName.ShouldBe(BuilderWithDefaults.DefaultFirstName); + customers[2].LastName.ShouldBe(BuilderWithDefaults.DefaultLastName); + } } } diff --git a/TestStack.Dossier.Tests/TestHelpers/Builders/BuilderWithDefaults.cs b/TestStack.Dossier.Tests/TestHelpers/Builders/BuilderWithDefaults.cs new file mode 100644 index 0000000..32f9bec --- /dev/null +++ b/TestStack.Dossier.Tests/TestHelpers/Builders/BuilderWithDefaults.cs @@ -0,0 +1,16 @@ +using TestStack.Dossier.Tests.TestHelpers.Objects.Entities; + +namespace TestStack.Dossier.Tests.TestHelpers.Builders +{ + public class BuilderWithDefaults : TestDataBuilder + { + public const string DefaultFirstName = "Joe"; + public const string DefaultLastName = "Bloggs"; + + public BuilderWithDefaults() + { + Set(x => x.FirstName, DefaultFirstName); + Set(x => x.LastName, DefaultLastName); + } + } +} diff --git a/TestStack.Dossier.Tests/TestStack.Dossier.Tests.csproj b/TestStack.Dossier.Tests/TestStack.Dossier.Tests.csproj index 380dd50..4391a4f 100644 --- a/TestStack.Dossier.Tests/TestStack.Dossier.Tests.csproj +++ b/TestStack.Dossier.Tests/TestStack.Dossier.Tests.csproj @@ -65,6 +65,7 @@ + From 3ad539e8a6023f641669e39dabc55cdd032a1d58 Mon Sep 17 00:00:00 2001 From: Ivan Lukic Date: Thu, 18 Jun 2015 13:51:16 +0200 Subject: [PATCH 26/86] fixed exception using defaults in constructors when creating lists (issue #40) --- TestStack.Dossier/Lists/ListBuilder.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TestStack.Dossier/Lists/ListBuilder.cs b/TestStack.Dossier/Lists/ListBuilder.cs index 370a800..148a36f 100644 --- a/TestStack.Dossier/Lists/ListBuilder.cs +++ b/TestStack.Dossier/Lists/ListBuilder.cs @@ -20,10 +20,10 @@ public class ListBuilder internal ListBuilder(int size) { + _list = new List(); BuilderProxy = (TBuilder) ListBuilderGenerator.Generator .CreateClassProxy(typeof (TBuilder), new ProxyGenerationOptions(new EnsureAllMethodsVirtual()), new ListBuilderInterceptor(this)); BuilderProxy.ListBuilder = this; - _list = new List(); var fixture = new AnonymousValueFixture(); for (var i = 0; i < size; i++) _list.Add(new TBuilder {Any = fixture}); From aace6e461ba06d0e1f241708dceafe928df989d7 Mon Sep 17 00:00:00 2001 From: Rob Moore Date: Thu, 18 Jun 2015 22:36:16 +0800 Subject: [PATCH 27/86] Removing redundant code --- TestStack.Dossier/Lists/ListBuilder.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/TestStack.Dossier/Lists/ListBuilder.cs b/TestStack.Dossier/Lists/ListBuilder.cs index 148a36f..595e94b 100644 --- a/TestStack.Dossier/Lists/ListBuilder.cs +++ b/TestStack.Dossier/Lists/ListBuilder.cs @@ -14,8 +14,8 @@ public class ListBuilder where TBuilder : TestDataBuilder, new() where TObject : class { - private int _start = 0; - private int _count = 0; + private int _start; + private int _count; private readonly List _list; internal ListBuilder(int size) From f6b0ad2aca3a74c57b74a49ecead731b3a15c236 Mon Sep 17 00:00:00 2001 From: Sergio Alvarez Date: Thu, 5 Nov 2015 14:27:44 +1100 Subject: [PATCH 28/86] Added support for nested properties --- TestStack.Dossier.Tests/GetSetTests.cs | 21 +++++++++++++ .../Builders/BasicCustomerBuilder.cs | 2 +- .../TestHelpers/Builders/CustomerBuilder.cs | 13 ++++++++ .../TestHelpers/Objects/Entities/Address.cs | 30 +++++++++++++++++++ .../TestHelpers/Objects/Entities/Customer.cs | 4 ++- .../TestStack.Dossier.Tests.csproj | 1 + TestStack.Dossier/PathExpressionVisitor.cs | 17 +++++++++++ TestStack.Dossier/Reflector.cs | 6 +++- TestStack.Dossier/TestStack.Dossier.csproj | 1 + 9 files changed, 92 insertions(+), 3 deletions(-) create mode 100644 TestStack.Dossier.Tests/TestHelpers/Objects/Entities/Address.cs create mode 100644 TestStack.Dossier/PathExpressionVisitor.cs diff --git a/TestStack.Dossier.Tests/GetSetTests.cs b/TestStack.Dossier.Tests/GetSetTests.cs index 2362f91..18c98e7 100644 --- a/TestStack.Dossier.Tests/GetSetTests.cs +++ b/TestStack.Dossier.Tests/GetSetTests.cs @@ -25,6 +25,27 @@ public void GivenAValueHasBeenSetAgainstAProperty_WhenRetrievingTheValueForThatP retrieved.ShouldBe(SetValue); } + [Fact] + public void GivenAValueHasBeenSetAgainstANestedProperty_WhenRetrievingTheValueForThatProperty_ThenTheSetValueIsReturned() + { + _b.Set(x => x.PostalAddress.Identifier, SetValue); + + var retrieved = _b.Get(x => x.PostalAddress.Identifier); + + retrieved.ShouldBe(SetValue); + } + + [Fact] + public void GivenAValueHasBeenSetAgainstANestedPropertyAndDifferentVaLueHasBeenSetAgainstANonNestedPropertyWithTheSameName_WhenRetrievingTheValueForThatNestedProperty_ThenTheSetValueIsReturned() + { + _b.Set(x => x.PostalAddress.Identifier, SetValue); + _b.Set(x => x.Identifier, (string)null); + + var retrieved = _b.Get(x => x.PostalAddress.Identifier); + + retrieved.ShouldBe(SetValue); + } + [Fact] public void GivenTwoValuesHaveBeenSetAgainstAProperty_WhenRetrievingTheValueForThatProperty_ThenTheLastSetValueIsReturned() { diff --git a/TestStack.Dossier.Tests/TestHelpers/Builders/BasicCustomerBuilder.cs b/TestStack.Dossier.Tests/TestHelpers/Builders/BasicCustomerBuilder.cs index cc3e534..fc9952d 100644 --- a/TestStack.Dossier.Tests/TestHelpers/Builders/BasicCustomerBuilder.cs +++ b/TestStack.Dossier.Tests/TestHelpers/Builders/BasicCustomerBuilder.cs @@ -6,7 +6,7 @@ public class BasicCustomerBuilder : TestDataBuilder x.YearJoined, yearJoined); } + public virtual CustomerBuilder WithPostalAdressIdentifier(string identifier) + { + return Set(x => x.PostalAddress.Identifier, identifier); + } + protected override Customer BuildObject() { return new Customer( @@ -26,6 +31,14 @@ protected override Customer BuildObject() Get(x => x.FirstName), Get(x => x.LastName), Get(x => x.YearJoined), + new Address( + Get(x => x.PostalAddress.Identifier), + Get(x => x.PostalAddress.StreetNo), + Get(x => x.PostalAddress.StreetName), + Get(x => x.PostalAddress.Suburb), + Get(x => x.PostalAddress.City), + Get(x => x.PostalAddress.PostCode) + ), Get(x => x.CustomerClass) ); } diff --git a/TestStack.Dossier.Tests/TestHelpers/Objects/Entities/Address.cs b/TestStack.Dossier.Tests/TestHelpers/Objects/Entities/Address.cs new file mode 100644 index 0000000..01dfc5b --- /dev/null +++ b/TestStack.Dossier.Tests/TestHelpers/Objects/Entities/Address.cs @@ -0,0 +1,30 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace TestStack.Dossier.Tests.TestHelpers.Objects.Entities +{ + public class Address + { + protected Address() { } + + public Address(string identifier, int streetNo, string streetName, string suburb, string city, string postCode) + { + Identifier = identifier; + StreetNo = streetNo; + StreetName = streetName; + Suburb = suburb; + City = city; + PostCode = postCode; + } + + public string Identifier { get; private set; } + public virtual int StreetNo { get; private set; } + public string StreetName { get; private set; } + public string Suburb { get; private set; } + public string City { get; private set; } + public string PostCode { get; private set; } + } +} diff --git a/TestStack.Dossier.Tests/TestHelpers/Objects/Entities/Customer.cs b/TestStack.Dossier.Tests/TestHelpers/Objects/Entities/Customer.cs index 3c943ea..5202e8c 100644 --- a/TestStack.Dossier.Tests/TestHelpers/Objects/Entities/Customer.cs +++ b/TestStack.Dossier.Tests/TestHelpers/Objects/Entities/Customer.cs @@ -6,7 +6,7 @@ public class Customer { protected Customer() {} - public Customer(string identifier, string firstName, string lastName, int yearJoined, CustomerClass customerClass) + public Customer(string identifier, string firstName, string lastName, int yearJoined, Address postalAddress, CustomerClass customerClass) { if (string.IsNullOrEmpty(identifier)) throw new ArgumentNullException("identifier"); @@ -19,6 +19,7 @@ public Customer(string identifier, string firstName, string lastName, int yearJo FirstName = firstName; LastName = lastName; YearJoined = yearJoined; + PostalAddress = postalAddress; CustomerClass = customerClass; } @@ -33,6 +34,7 @@ public virtual int CustomerForHowManyYears(DateTime since) public virtual string FirstName { get; private set; } public virtual string LastName { get; private set; } public virtual int YearJoined { get; private set; } + public virtual Address PostalAddress { get; private set; } public virtual CustomerClass CustomerClass { get; private set; } } } diff --git a/TestStack.Dossier.Tests/TestStack.Dossier.Tests.csproj b/TestStack.Dossier.Tests/TestStack.Dossier.Tests.csproj index 4391a4f..e8fe2ff 100644 --- a/TestStack.Dossier.Tests/TestStack.Dossier.Tests.csproj +++ b/TestStack.Dossier.Tests/TestStack.Dossier.Tests.csproj @@ -66,6 +66,7 @@ + diff --git a/TestStack.Dossier/PathExpressionVisitor.cs b/TestStack.Dossier/PathExpressionVisitor.cs new file mode 100644 index 0000000..5e7ba19 --- /dev/null +++ b/TestStack.Dossier/PathExpressionVisitor.cs @@ -0,0 +1,17 @@ +using System.Collections.Generic; +using System.Linq.Expressions; + +namespace TestStack.Dossier +{ + internal class PathExpressionVisitor : ExpressionVisitor + { + internal readonly List Path = new List(); + + protected override Expression VisitMember(MemberExpression node) + { + Path.Add(node.Member.Name); + return base.VisitMember(node); + } + } + +} diff --git a/TestStack.Dossier/Reflector.cs b/TestStack.Dossier/Reflector.cs index 80c9185..d01c98b 100644 --- a/TestStack.Dossier/Reflector.cs +++ b/TestStack.Dossier/Reflector.cs @@ -11,6 +11,7 @@ internal static class Reflector public static string GetPropertyNameFor(Expression> property) { var memExp = property.Body as MemberExpression; + if (memExp == null) throw new ArgumentException( string.Format( @@ -21,7 +22,10 @@ public static string GetPropertyNameFor(Expression() diff --git a/TestStack.Dossier/TestStack.Dossier.csproj b/TestStack.Dossier/TestStack.Dossier.csproj index 569a193..18981de 100644 --- a/TestStack.Dossier/TestStack.Dossier.csproj +++ b/TestStack.Dossier/TestStack.Dossier.csproj @@ -92,6 +92,7 @@ + From 0148af0f62939a18cba44d9c794ed9ffbebabca8 Mon Sep 17 00:00:00 2001 From: Rob Moore Date: Sun, 8 Nov 2015 11:25:26 +0800 Subject: [PATCH 29/86] Updated to latest gitversion --- GitVersionConfig.yaml | 3 +++ NextVersion.txt | 1 - 2 files changed, 3 insertions(+), 1 deletion(-) create mode 100644 GitVersionConfig.yaml delete mode 100644 NextVersion.txt diff --git a/GitVersionConfig.yaml b/GitVersionConfig.yaml new file mode 100644 index 0000000..66340a4 --- /dev/null +++ b/GitVersionConfig.yaml @@ -0,0 +1,3 @@ +mode: ContinuousDelivery +next-version: 3.1.0 +branches: {} diff --git a/NextVersion.txt b/NextVersion.txt deleted file mode 100644 index a0cd9f0..0000000 --- a/NextVersion.txt +++ /dev/null @@ -1 +0,0 @@ -3.1.0 \ No newline at end of file From 57e80886136c7282b50d1e142c88cc5b20655145 Mon Sep 17 00:00:00 2001 From: Rob Moore Date: Sun, 8 Nov 2015 12:01:16 +0800 Subject: [PATCH 30/86] Bumping minor version due to new feature --- GitVersionConfig.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GitVersionConfig.yaml b/GitVersionConfig.yaml index 66340a4..69f88ee 100644 --- a/GitVersionConfig.yaml +++ b/GitVersionConfig.yaml @@ -1,3 +1,3 @@ mode: ContinuousDelivery -next-version: 3.1.0 +next-version: 3.2.0 branches: {} From db8845e4637646a90e706693d383285f726dc2ab Mon Sep 17 00:00:00 2001 From: Dennis Roche Date: Wed, 9 Dec 2015 09:49:45 +0800 Subject: [PATCH 31/86] Added ITestDataBuilder interface --- TestStack.Dossier/ITestDataBuilder.cs | 15 +++++++++++++++ TestStack.Dossier/TestDataBuilder.cs | 2 +- TestStack.Dossier/TestStack.Dossier.csproj | 1 + 3 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 TestStack.Dossier/ITestDataBuilder.cs diff --git a/TestStack.Dossier/ITestDataBuilder.cs b/TestStack.Dossier/ITestDataBuilder.cs new file mode 100644 index 0000000..4dd8591 --- /dev/null +++ b/TestStack.Dossier/ITestDataBuilder.cs @@ -0,0 +1,15 @@ +namespace TestStack.Dossier +{ + /// + /// Base class definining infrastructure for a class that generates objects of type {TObject}. + /// + /// The type of object this class generates + public interface ITestDataBuilder where TObject : class + { + /// + /// Build the object. + /// + /// The built object + TObject Build(); + } +} diff --git a/TestStack.Dossier/TestDataBuilder.cs b/TestStack.Dossier/TestDataBuilder.cs index 24edb91..224f300 100644 --- a/TestStack.Dossier/TestDataBuilder.cs +++ b/TestStack.Dossier/TestDataBuilder.cs @@ -11,7 +11,7 @@ namespace TestStack.Dossier /// /// The type of object this class generates /// The type for this class, yes this is a recursive type definition - public abstract class TestDataBuilder + public abstract class TestDataBuilder : ITestDataBuilder where TObject : class where TBuilder : TestDataBuilder, new() { diff --git a/TestStack.Dossier/TestStack.Dossier.csproj b/TestStack.Dossier/TestStack.Dossier.csproj index 18981de..ebc247e 100644 --- a/TestStack.Dossier/TestStack.Dossier.csproj +++ b/TestStack.Dossier/TestStack.Dossier.csproj @@ -52,6 +52,7 @@ + From 9eea6a147882512ea487910261d168b82e2f0861 Mon Sep 17 00:00:00 2001 From: Michael Whelan Date: Tue, 19 Jan 2016 21:26:39 +0000 Subject: [PATCH 32/86] Added Pick functionality to builders --- .../Picking/PickingTests.cs | 48 +++++++++++++++++++ .../TestStack.Dossier.Tests.csproj | 2 + TestStack.Dossier/Picking/ItemPicker.cs | 38 +++++++++++++++ TestStack.Dossier/Picking/Pick.cs | 32 +++++++++++++ TestStack.Dossier/Picking/RandomItemPicker.cs | 20 ++++++++ .../Picking/RepeatingSequenceItemPicker.cs | 20 ++++++++ TestStack.Dossier/TestStack.Dossier.csproj | 4 ++ 7 files changed, 164 insertions(+) create mode 100644 TestStack.Dossier.Tests/Picking/PickingTests.cs create mode 100644 TestStack.Dossier/Picking/ItemPicker.cs create mode 100644 TestStack.Dossier/Picking/Pick.cs create mode 100644 TestStack.Dossier/Picking/RandomItemPicker.cs create mode 100644 TestStack.Dossier/Picking/RepeatingSequenceItemPicker.cs diff --git a/TestStack.Dossier.Tests/Picking/PickingTests.cs b/TestStack.Dossier.Tests/Picking/PickingTests.cs new file mode 100644 index 0000000..dd1e4cb --- /dev/null +++ b/TestStack.Dossier.Tests/Picking/PickingTests.cs @@ -0,0 +1,48 @@ +using System.Linq; +using Shouldly; +using TestStack.Dossier.Lists; +using TestStack.Dossier.Picking; +using TestStack.Dossier.Tests.TestHelpers.Objects.Entities; +using Xunit; + +namespace TestStack.Dossier.Tests.Picking +{ + public class PickingTests + { + [Fact] + public void RandomItemFrom_should_add_items_from_list_randomly() + { + var addresses = Builder
.CreateListOfSize(15).BuildList(); + var customers = Builder + .CreateListOfSize(15) + .All() + .Set(x => x.PostalAddress, Pick.RandomItemFrom(addresses).Next) + .BuildList(); + + var uniqueAddresses = customers.Select(x => x.PostalAddress).Distinct().Count(); + uniqueAddresses.ShouldBeGreaterThan(3); + uniqueAddresses.ShouldBeLessThan(15); + } + + [Fact] + public void RepeatingSequenceFrom_should_add_items_from_list_sequentially_and_repeat_when_list_completes() + { + var addresses = Builder
.CreateListOfSize(3).BuildList(); + var customers = Builder + .CreateListOfSize(9) + .All() + .Set(x => x.PostalAddress, Pick.RepeatingSequenceFrom(addresses).Next) + .BuildList(); + + for (int i = 0; i < 2; i++) + { + var address = customers[i].PostalAddress; + address.ShouldBeSameAs(customers[i + 3].PostalAddress); + address.ShouldBeSameAs(customers[i + 6].PostalAddress); + + address.ShouldNotBeSameAs(customers[i + 1].PostalAddress); + address.ShouldNotBeSameAs(customers[i + 2].PostalAddress); + } + } + } +} diff --git a/TestStack.Dossier.Tests/TestStack.Dossier.Tests.csproj b/TestStack.Dossier.Tests/TestStack.Dossier.Tests.csproj index e8fe2ff..617f270 100644 --- a/TestStack.Dossier.Tests/TestStack.Dossier.Tests.csproj +++ b/TestStack.Dossier.Tests/TestStack.Dossier.Tests.csproj @@ -58,6 +58,7 @@ + @@ -119,6 +120,7 @@ TestStack.Dossier + + \ No newline at end of file diff --git a/TestStack.Dossier.Tests/packages.config b/TestStack.Dossier.Tests/packages.config deleted file mode 100644 index 30cb97f..0000000 --- a/TestStack.Dossier.Tests/packages.config +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/TestStack.Dossier.sln b/TestStack.Dossier.sln index 66f61bf..6be173a 100644 --- a/TestStack.Dossier.sln +++ b/TestStack.Dossier.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 15 -VisualStudioVersion = 15.0.26014.0 +VisualStudioVersion = 15.0.26430.13 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{BC8508D1-6FCB-46B2-9C14-F41F6AD76B09}" ProjectSection(SolutionItems) = preProject @@ -13,9 +13,9 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution README.md = README.md EndProjectSection EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestStack.Dossier.Tests", "TestStack.Dossier.Tests\TestStack.Dossier.Tests.csproj", "{DC49CE57-CB3F-487D-83DC-6A4E78CB908C}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestStack.Dossier", "TestStack.Dossier\TestStack.Dossier.csproj", "{768AF10B-5E0C-46BB-B6CD-B202AF39A0EF}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestStack.Dossier", "TestStack.Dossier\TestStack.Dossier.csproj", "{01E4EE61-AB1A-4177-8B6C-D50205D167A9}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestStack.Dossier.Tests", "TestStack.Dossier.Tests\TestStack.Dossier.Tests.csproj", "{5B38B893-1018-4F0D-9999-4DA1385EB94A}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -23,14 +23,14 @@ Global Release|Any CPU = Release|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {DC49CE57-CB3F-487D-83DC-6A4E78CB908C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {DC49CE57-CB3F-487D-83DC-6A4E78CB908C}.Debug|Any CPU.Build.0 = Debug|Any CPU - {DC49CE57-CB3F-487D-83DC-6A4E78CB908C}.Release|Any CPU.ActiveCfg = Release|Any CPU - {DC49CE57-CB3F-487D-83DC-6A4E78CB908C}.Release|Any CPU.Build.0 = Release|Any CPU - {01E4EE61-AB1A-4177-8B6C-D50205D167A9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {01E4EE61-AB1A-4177-8B6C-D50205D167A9}.Debug|Any CPU.Build.0 = Debug|Any CPU - {01E4EE61-AB1A-4177-8B6C-D50205D167A9}.Release|Any CPU.ActiveCfg = Release|Any CPU - {01E4EE61-AB1A-4177-8B6C-D50205D167A9}.Release|Any CPU.Build.0 = Release|Any CPU + {768AF10B-5E0C-46BB-B6CD-B202AF39A0EF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {768AF10B-5E0C-46BB-B6CD-B202AF39A0EF}.Debug|Any CPU.Build.0 = Debug|Any CPU + {768AF10B-5E0C-46BB-B6CD-B202AF39A0EF}.Release|Any CPU.ActiveCfg = Release|Any CPU + {768AF10B-5E0C-46BB-B6CD-B202AF39A0EF}.Release|Any CPU.Build.0 = Release|Any CPU + {5B38B893-1018-4F0D-9999-4DA1385EB94A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5B38B893-1018-4F0D-9999-4DA1385EB94A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5B38B893-1018-4F0D-9999-4DA1385EB94A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5B38B893-1018-4F0D-9999-4DA1385EB94A}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/TestStack.Dossier/AssemblyInfo.cs b/TestStack.Dossier/AssemblyInfo.cs new file mode 100644 index 0000000..66feadf --- /dev/null +++ b/TestStack.Dossier/AssemblyInfo.cs @@ -0,0 +1,6 @@ +using System.Runtime.CompilerServices; + +// Handling InternalsVisibleTo in new .csproj +// https://stackoverflow.com/questions/42810705/visual-studio-2017-new-csproj-internalsvisibleto +[assembly: InternalsVisibleTo("TestStack.Dossier.Tests")] +[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")] \ No newline at end of file diff --git a/TestStack.Dossier/Properties/AssemblyInfo.cs b/TestStack.Dossier/Properties/AssemblyInfo.cs deleted file mode 100644 index 35a1828..0000000 --- a/TestStack.Dossier/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,39 +0,0 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("TestStack.Dossier")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("TestStack.Dossier")] -[assembly: AssemblyCopyright("Copyright © 2015")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -[assembly: InternalsVisibleTo("TestStack.Dossier.Tests")] -[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("24a139fb-b390-4f14-9be6-cf9fb354bb5d")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/TestStack.Dossier/TestStack.Dossier.csproj b/TestStack.Dossier/TestStack.Dossier.csproj index 6643fca..c57d46f 100644 --- a/TestStack.Dossier/TestStack.Dossier.csproj +++ b/TestStack.Dossier/TestStack.Dossier.csproj @@ -1,141 +1,76 @@ - - - + + - Debug - AnyCPU - {01E4EE61-AB1A-4177-8B6C-D50205D167A9} - Library - Properties - TestStack.Dossier - TestStack.Dossier - v4.0 - 512 - ..\ + netstandard2.0;net45;net40 - - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - bin\Debug\TestStack.Dossier.xml - 5 - - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - bin\Release\TestStack.Dossier.xml - - - - ..\packages\Castle.Core.3.3.1\lib\net40-client\Castle.Core.dll - - - False - ..\packages\NSubstitute.1.8.1.0\lib\net40\NSubstitute.dll - - - ..\packages\AutoFixture.3.20.0\lib\net40\Ploeh.AutoFixture.dll - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -172,6 +107,8 @@ + + @@ -200,14 +137,11 @@ - - - - + + + + + + + \ No newline at end of file diff --git a/TestStack.Dossier/TestStack.Dossier.nuspec b/TestStack.Dossier/TestStack.Dossier.nuspec deleted file mode 100644 index b45f643..0000000 --- a/TestStack.Dossier/TestStack.Dossier.nuspec +++ /dev/null @@ -1,45 +0,0 @@ - - - - - TestStack.Dossier - - - 1.0.0 - - - Robert Moore, Michael Whelan, TestStack - - - TestStack.Dossier provides you with the code infrastructure to easily and quickly generate test fixture data for your automated tests in a terse, readable and maintainable way using the Test Data Builder, anonymous value and equivalence class patterns. - - Formerly called NTestDataBuilder. - - - https://github.com/TestStack/TestStack.Dossier - - - https://github.com/TestStack/TestStack.Dossier/blob/master/LICENSE - - - https://raw.github.com/TestStack/TestStack.Dossier/master/logo.png - - - testing data-generation test-fixture nbuilder nsubstitute autofixture mocking equivalence-class test-data-builder anonymous-value ntestdatabuilder - - - en-US - - - - - - - - - - - - - - diff --git a/TestStack.Dossier/packages.config b/TestStack.Dossier/packages.config deleted file mode 100644 index d6889a8..0000000 --- a/TestStack.Dossier/packages.config +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file From d52c5b306016b79f2086bde8c41dc1edad93bcdd Mon Sep 17 00:00:00 2001 From: Michael Whelan Date: Sun, 17 Sep 2017 17:59:32 +0100 Subject: [PATCH 59/86] Upgraded to AutoFixture 4 and support for netstandard1.5 --- NuGet.config | 8 ++++++++ .../Dictionaries/Resources/FileDataConventions.cs | 2 +- .../TestStack.Dossier.Tests.csproj | 2 +- .../CachedFileDictionaryRepository.cs | 2 +- .../Suppliers/DefaultValueSupplier.cs | 3 ++- .../Suppliers/DefaultValueTypeValueSupplier.cs | 3 ++- TestStack.Dossier/TestStack.Dossier.csproj | 15 +++++++++++++-- 7 files changed, 28 insertions(+), 7 deletions(-) create mode 100644 NuGet.config diff --git a/NuGet.config b/NuGet.config new file mode 100644 index 0000000..7e6f194 --- /dev/null +++ b/NuGet.config @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/TestStack.Dossier.Tests/DataSources/Dictionaries/Resources/FileDataConventions.cs b/TestStack.Dossier.Tests/DataSources/Dictionaries/Resources/FileDataConventions.cs index afd5b62..651b7d5 100644 --- a/TestStack.Dossier.Tests/DataSources/Dictionaries/Resources/FileDataConventions.cs +++ b/TestStack.Dossier.Tests/DataSources/Dictionaries/Resources/FileDataConventions.cs @@ -13,7 +13,7 @@ public class FileDataConventions [Fact] public void ApplyConventions() { - var assembly = typeof(IAnonymousValueSupplier).Assembly; + var assembly = typeof(IAnonymousValueSupplier).GetTypeInfo().Assembly; var resources = assembly .GetManifestResourceNames() .Where(x => x.EndsWith(".txt")) diff --git a/TestStack.Dossier.Tests/TestStack.Dossier.Tests.csproj b/TestStack.Dossier.Tests/TestStack.Dossier.Tests.csproj index 0a92239..e3c2dd6 100644 --- a/TestStack.Dossier.Tests/TestStack.Dossier.Tests.csproj +++ b/TestStack.Dossier.Tests/TestStack.Dossier.Tests.csproj @@ -6,7 +6,7 @@ - + diff --git a/TestStack.Dossier/DataSources/Dictionaries/CachedFileDictionaryRepository.cs b/TestStack.Dossier/DataSources/Dictionaries/CachedFileDictionaryRepository.cs index 0a783d1..2bf84bd 100644 --- a/TestStack.Dossier/DataSources/Dictionaries/CachedFileDictionaryRepository.cs +++ b/TestStack.Dossier/DataSources/Dictionaries/CachedFileDictionaryRepository.cs @@ -22,7 +22,7 @@ public IList GetWordsFrom(string dictionary) else { var resourceName = string.Format("TestStack.Dossier.DataSources.Dictionaries.Resources.{0}", name); - words = GetWordsFromEmbeddedResource(GetType().Assembly, resourceName).ToList(); + words = GetWordsFromEmbeddedResource(GetType().GetTypeInfo().Assembly, resourceName).ToList(); } return words; diff --git a/TestStack.Dossier/Suppliers/DefaultValueSupplier.cs b/TestStack.Dossier/Suppliers/DefaultValueSupplier.cs index fe3f0d9..bfbea1c 100644 --- a/TestStack.Dossier/Suppliers/DefaultValueSupplier.cs +++ b/TestStack.Dossier/Suppliers/DefaultValueSupplier.cs @@ -1,4 +1,5 @@ using System; +using System.Reflection; namespace TestStack.Dossier.Suppliers { @@ -17,7 +18,7 @@ public bool CanSupplyValue(Type type, string propertyName) public object GenerateAnonymousValue(AnonymousValueFixture any, Type type, string propertyName) { // See stackoverflow: http://stackoverflow.com/questions/325426/programmatic-equivalent-of-defaulttype - if (type.IsValueType) + if (type.GetTypeInfo().IsValueType) { return Activator.CreateInstance(type); } diff --git a/TestStack.Dossier/Suppliers/DefaultValueTypeValueSupplier.cs b/TestStack.Dossier/Suppliers/DefaultValueTypeValueSupplier.cs index 1e0ec24..e6954a9 100644 --- a/TestStack.Dossier/Suppliers/DefaultValueTypeValueSupplier.cs +++ b/TestStack.Dossier/Suppliers/DefaultValueTypeValueSupplier.cs @@ -1,5 +1,6 @@ using System; using System.Linq; +using System.Reflection; using Ploeh.AutoFixture; using Ploeh.AutoFixture.Kernel; @@ -13,7 +14,7 @@ public class DefaultValueTypeValueSupplier : IAnonymousValueSupplier /// public bool CanSupplyValue(Type type, string propertyName) { - return type.IsValueType; + return type.GetTypeInfo().IsValueType; } /// diff --git a/TestStack.Dossier/TestStack.Dossier.csproj b/TestStack.Dossier/TestStack.Dossier.csproj index c57d46f..85323e6 100644 --- a/TestStack.Dossier/TestStack.Dossier.csproj +++ b/TestStack.Dossier/TestStack.Dossier.csproj @@ -1,7 +1,7 @@ - netstandard2.0;net45;net40 + netstandard1.5;net45 @@ -139,9 +139,20 @@ - + + + 4.0.0-alpha.230 + + + + + + 4.0.0-alpha.230 + + + \ No newline at end of file From b1e90f89bd4f75a728f5d13f377f2971b91c2f8b Mon Sep 17 00:00:00 2001 From: Michael Whelan Date: Sun, 17 Sep 2017 18:43:20 +0100 Subject: [PATCH 60/86] Added NuGet metadata --- TestStack.Dossier/TestStack.Dossier.csproj | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/TestStack.Dossier/TestStack.Dossier.csproj b/TestStack.Dossier/TestStack.Dossier.csproj index 85323e6..d9b6f9e 100644 --- a/TestStack.Dossier/TestStack.Dossier.csproj +++ b/TestStack.Dossier/TestStack.Dossier.csproj @@ -2,8 +2,18 @@ netstandard1.5;net45 + TestStack.Dossier + TestStack.Dossier + 3.5.0 + Robert Moore, Michael Whelan, TestStack + + TestStack.Dossier provides you with the code infrastructure to easily and quickly generate test fixture data for your automated tests in a terse, readable and maintainable way using the Test Data Builder, anonymous value and equivalence class patterns. Formerly called NTestDataBuilder. + + false + testing data-generation test-fixture nbuilder nsubstitute autofixture mocking equivalence-class test-data-builder anonymous-value ntestdatabuilder + https://github.com/TestStack/TestStack.Dossier - + From dafeb60e37a5b93827b764b4a3479dfe695c6d8d Mon Sep 17 00:00:00 2001 From: Michael Whelan Date: Thu, 2 Nov 2017 21:03:22 +0000 Subject: [PATCH 61/86] Upgraded to AutoFixture 4 --- .../TestStack.Dossier.Tests.csproj | 16 ++++++++-------- TestStack.Dossier/AnonymousValueFixture.cs | 2 +- .../EquivalenceClasses/EnumEquivalenceClasses.cs | 2 +- .../IntegerEquivalenceClasses.cs | 2 +- .../StringEquivalenceClasses.cs | 7 ++++--- .../Factories/AllPropertiesFactory.cs | 2 +- .../Factories/AutoFixtureFactory.cs | 2 +- .../Suppliers/DefaultValueTypeValueSupplier.cs | 4 ++-- TestStack.Dossier/TestStack.Dossier.csproj | 15 +++++---------- 9 files changed, 24 insertions(+), 28 deletions(-) diff --git a/TestStack.Dossier.Tests/TestStack.Dossier.Tests.csproj b/TestStack.Dossier.Tests/TestStack.Dossier.Tests.csproj index e3c2dd6..a9a044c 100644 --- a/TestStack.Dossier.Tests/TestStack.Dossier.Tests.csproj +++ b/TestStack.Dossier.Tests/TestStack.Dossier.Tests.csproj @@ -1,17 +1,17 @@ - netcoreapp2.0;net45 + netcoreapp2.0;net452 - - - - - - - + + + + + + + diff --git a/TestStack.Dossier/AnonymousValueFixture.cs b/TestStack.Dossier/AnonymousValueFixture.cs index 83a6dc2..0e641ae 100644 --- a/TestStack.Dossier/AnonymousValueFixture.cs +++ b/TestStack.Dossier/AnonymousValueFixture.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; -using Ploeh.AutoFixture; +using AutoFixture; using TestStack.Dossier.DataSources.Dictionaries; using TestStack.Dossier.Suppliers; diff --git a/TestStack.Dossier/EquivalenceClasses/EnumEquivalenceClasses.cs b/TestStack.Dossier/EquivalenceClasses/EnumEquivalenceClasses.cs index a37f287..c5c5b47 100644 --- a/TestStack.Dossier/EquivalenceClasses/EnumEquivalenceClasses.cs +++ b/TestStack.Dossier/EquivalenceClasses/EnumEquivalenceClasses.cs @@ -1,6 +1,6 @@ using System; using System.Linq; -using Ploeh.AutoFixture; +using AutoFixture; namespace TestStack.Dossier.EquivalenceClasses { diff --git a/TestStack.Dossier/EquivalenceClasses/IntegerEquivalenceClasses.cs b/TestStack.Dossier/EquivalenceClasses/IntegerEquivalenceClasses.cs index 9c60524..32c9acf 100644 --- a/TestStack.Dossier/EquivalenceClasses/IntegerEquivalenceClasses.cs +++ b/TestStack.Dossier/EquivalenceClasses/IntegerEquivalenceClasses.cs @@ -1,5 +1,5 @@ using System.Linq; -using Ploeh.AutoFixture; +using AutoFixture; namespace TestStack.Dossier.EquivalenceClasses { diff --git a/TestStack.Dossier/EquivalenceClasses/StringEquivalenceClasses.cs b/TestStack.Dossier/EquivalenceClasses/StringEquivalenceClasses.cs index f694f9e..4ad3ae9 100644 --- a/TestStack.Dossier/EquivalenceClasses/StringEquivalenceClasses.cs +++ b/TestStack.Dossier/EquivalenceClasses/StringEquivalenceClasses.cs @@ -1,6 +1,6 @@ using System.Text; -using Ploeh.AutoFixture; -using Ploeh.AutoFixture.Kernel; +using AutoFixture; +using AutoFixture.Kernel; namespace TestStack.Dossier.EquivalenceClasses { @@ -48,7 +48,8 @@ public object Resolve(object request) /// The generated string public static string StringStartingWith(this AnonymousValueFixture fixture, string prefix) { - return fixture.Fixture.Create(prefix); + //return fixture.Fixture.Create(prefix); + return string.Format("{0}{1}", prefix, fixture.Fixture.Create()); } /// diff --git a/TestStack.Dossier/Factories/AllPropertiesFactory.cs b/TestStack.Dossier/Factories/AllPropertiesFactory.cs index 1f105b3..1696811 100644 --- a/TestStack.Dossier/Factories/AllPropertiesFactory.cs +++ b/TestStack.Dossier/Factories/AllPropertiesFactory.cs @@ -1,4 +1,4 @@ -using Ploeh.AutoFixture; +using AutoFixture; namespace TestStack.Dossier.Factories { diff --git a/TestStack.Dossier/Factories/AutoFixtureFactory.cs b/TestStack.Dossier/Factories/AutoFixtureFactory.cs index 8c8b4ec..588817d 100644 --- a/TestStack.Dossier/Factories/AutoFixtureFactory.cs +++ b/TestStack.Dossier/Factories/AutoFixtureFactory.cs @@ -1,4 +1,4 @@ -using Ploeh.AutoFixture; +using AutoFixture; namespace TestStack.Dossier.Factories { diff --git a/TestStack.Dossier/Suppliers/DefaultValueTypeValueSupplier.cs b/TestStack.Dossier/Suppliers/DefaultValueTypeValueSupplier.cs index e6954a9..ae7ba85 100644 --- a/TestStack.Dossier/Suppliers/DefaultValueTypeValueSupplier.cs +++ b/TestStack.Dossier/Suppliers/DefaultValueTypeValueSupplier.cs @@ -1,8 +1,8 @@ using System; using System.Linq; using System.Reflection; -using Ploeh.AutoFixture; -using Ploeh.AutoFixture.Kernel; +using AutoFixture; +using AutoFixture.Kernel; namespace TestStack.Dossier.Suppliers { diff --git a/TestStack.Dossier/TestStack.Dossier.csproj b/TestStack.Dossier/TestStack.Dossier.csproj index d9b6f9e..08f6c62 100644 --- a/TestStack.Dossier/TestStack.Dossier.csproj +++ b/TestStack.Dossier/TestStack.Dossier.csproj @@ -1,10 +1,10 @@ - netstandard1.5;net45 + netstandard1.5;net452 TestStack.Dossier TestStack.Dossier - 3.5.0 + 4.0.0 Robert Moore, Michael Whelan, TestStack TestStack.Dossier provides you with the code infrastructure to easily and quickly generate test fixture data for your automated tests in a terse, readable and maintainable way using the Test Data Builder, anonymous value and equivalence class patterns. Formerly called NTestDataBuilder. @@ -149,8 +149,9 @@ - - + + + @@ -159,10 +160,4 @@ - - - 4.0.0-alpha.230 - - - \ No newline at end of file From 2b1054d475fdaf51da5e79e1d68251640f5aaee7 Mon Sep 17 00:00:00 2001 From: Rob Moore Date: Sun, 13 Jan 2019 14:24:54 +0800 Subject: [PATCH 62/86] Added appveyor config --- appveyor.yml | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 appveyor.yml diff --git a/appveyor.yml b/appveyor.yml new file mode 100644 index 0000000..c6f1340 --- /dev/null +++ b/appveyor.yml @@ -0,0 +1,74 @@ +version: 1.0.{build} +configuration: Release +image: +- Visual Studio 2017 +environment: + GitHubOrganisation: TestStack + GitHubToken: + secure: cBxvAtTgSlWVblTXtx8QKygh2HQeYZ9i0plMjJzCTNInGCm1XyG+nrSs18qUtC8W +init: +- ps: iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1')) +before_build: +- ps: >- + nuget restore + + choco install -y --no-progress git.install GitReleaseManager.Portable + + npm install github-release-notes -g + + GitVersion /output buildserver /updateassemblyinfo + + If (Test-Path ".\PreBuild.ps1") { + + & ".\PreBuild.ps1" + + } + +build: + parallel: true + verbosity: minimal +after_build: +- ps: >- + Get-ChildItem -Recurse *.nuspec | foreach { nuget pack $_.FullName -Properties "Configuration=Release;Platform=AnyCPU" -Symbols -Version $Env:GitVersion_NuGetVersion } + + $currentTag = git tag -l --points-at HEAD + + $HTTP_Request = [System.Net.WebRequest]::Create("https://api.github.com/repos/$env:GitHubOrganisation/$env:APPVEYOR_PROJECT_NAME/releases/tags/$Env:GitVersion_NuGetVersion") + + $HTTP_Request.UserAgent = "Powershell" + + try { + + $HTTP_Request.GetResponse() + + } catch [Net.WebException] { + + [System.Net.HttpWebResponse] $resp = [System.Net.HttpWebResponse] $_.Exception.Response + + if ($currentTag -And $resp.StatusCode -eq 404) { + + $env:SHOULD_DEPLOY = 'true' + + } + + } +test: + assemblies: + only: + - '**\*.*Tests.dll' +artifacts: +- path: '*.nupkg' +deploy: +- provider: NuGet + api_key: + secure: E55iN0yXlOk+HFXJ8SJ3XVLkJk27d1Hef98SJeg+zeHYXjMANmS+ZE1LuwNEk9Nv + on: + SHOULD_DEPLOY: true +after_deploy: +- ps: >- + gren release --token=$env:GitHubToken +notifications: +- provider: GitHubPullRequest + on_build_success: true + on_build_failure: true + on_build_status_changed: false From 994d309bea02370e03b0164edeee60ebad5d169a Mon Sep 17 00:00:00 2001 From: Rob Moore Date: Sun, 13 Jan 2019 15:02:57 +0800 Subject: [PATCH 63/86] Updated app veyor yml --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index c6f1340..c857733 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -61,7 +61,7 @@ artifacts: deploy: - provider: NuGet api_key: - secure: E55iN0yXlOk+HFXJ8SJ3XVLkJk27d1Hef98SJeg+zeHYXjMANmS+ZE1LuwNEk9Nv + secure: dTBFLJoyCv7cMYQpwIN27WSvS0tqBAX1xb48qgwuWLWuGFNOrw8rTP8mLUNu2Pqq on: SHOULD_DEPLOY: true after_deploy: From 83c7a5e6e0e8aaf48e5332c868117a92ad3a3af0 Mon Sep 17 00:00:00 2001 From: Rob Moore Date: Sun, 13 Jan 2019 15:51:52 +0800 Subject: [PATCH 64/86] Update app veyor yml --- TestStack.Dossier.sln | 4 ++++ appveyor.yml | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/TestStack.Dossier.sln b/TestStack.Dossier.sln index 66f61bf..78b68bf 100644 --- a/TestStack.Dossier.sln +++ b/TestStack.Dossier.sln @@ -5,6 +5,7 @@ VisualStudioVersion = 15.0.26014.0 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{BC8508D1-6FCB-46B2-9C14-F41F6AD76B09}" ProjectSection(SolutionItems) = preProject + appveyor.yml = appveyor.yml BREAKING_CHANGES.md = BREAKING_CHANGES.md CONTRIBUTING.md = CONTRIBUTING.md GitVersionConfig.yaml = GitVersionConfig.yaml @@ -35,4 +36,7 @@ Global GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {B1C35ECA-9807-42D4-935A-186845AF20A3} + EndGlobalSection EndGlobal diff --git a/appveyor.yml b/appveyor.yml index c857733..3d8e525 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -61,7 +61,7 @@ artifacts: deploy: - provider: NuGet api_key: - secure: dTBFLJoyCv7cMYQpwIN27WSvS0tqBAX1xb48qgwuWLWuGFNOrw8rTP8mLUNu2Pqq + secure: sci7t37NkV5yoBPRwJjCMeU05wviPFOeRGFqYo1hkGWITUTuPNa8MefokUSHUwhv on: SHOULD_DEPLOY: true after_deploy: From b70815b4f97b6c35b0776abf91d5ab42e399505e Mon Sep 17 00:00:00 2001 From: Rob Moore Date: Sun, 13 Jan 2019 17:41:52 +0800 Subject: [PATCH 65/86] Updated appveyor yaml --- appveyor.yml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 3d8e525..64e0d30 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -6,8 +6,6 @@ environment: GitHubOrganisation: TestStack GitHubToken: secure: cBxvAtTgSlWVblTXtx8QKygh2HQeYZ9i0plMjJzCTNInGCm1XyG+nrSs18qUtC8W -init: -- ps: iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1')) before_build: - ps: >- nuget restore @@ -61,7 +59,7 @@ artifacts: deploy: - provider: NuGet api_key: - secure: sci7t37NkV5yoBPRwJjCMeU05wviPFOeRGFqYo1hkGWITUTuPNa8MefokUSHUwhv + secure: VwHQFq0vD5vJNiUtsZMgUYdw2tVfXJfWh++eHC2LyEMvQzWiESWy2yBwQajzYAjo on: SHOULD_DEPLOY: true after_deploy: From 704d76f9aa981d0a908e00332b180257df912043 Mon Sep 17 00:00:00 2001 From: Rob Moore Date: Sun, 13 Jan 2019 17:54:09 +0800 Subject: [PATCH 66/86] Change to appveyor yml --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index 64e0d30..54dbffc 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -64,7 +64,7 @@ deploy: SHOULD_DEPLOY: true after_deploy: - ps: >- - gren release --token=$env:GitHubToken + gren release --token=$env:GitHubToken --username=$env:GitHubOrganisation --repo=$env:APPVEYOR_PROJECT_NAME notifications: - provider: GitHubPullRequest on_build_success: true From b791949071e3efd674e536688b322b2a3a531f5f Mon Sep 17 00:00:00 2001 From: Rob Moore Date: Sun, 13 Jan 2019 19:14:52 +0800 Subject: [PATCH 67/86] Upgraded dependencies, switched to netstandard2.0 and fixed deprecation warnings +semver: major --- NuGet.config | 4 +--- .../Builder_CreateListTests.cs | 1 + .../DataSources/DataSourceConventionTests.cs | 2 +- .../Resources/FileDataConventions.cs | 4 ++-- .../GeoEquivalenceClassesTests.cs | 10 ++++----- .../PersonEquivalenceClassesTests.cs | 22 +++++++++---------- .../TestStack.Dossier.Tests.csproj | 19 +++++++++------- TestStack.Dossier/TestStack.Dossier.csproj | 9 ++++---- 8 files changed, 36 insertions(+), 35 deletions(-) diff --git a/NuGet.config b/NuGet.config index 7e6f194..3f0e003 100644 --- a/NuGet.config +++ b/NuGet.config @@ -1,8 +1,6 @@  - - - + \ No newline at end of file diff --git a/TestStack.Dossier.Tests/Builder_CreateListTests.cs b/TestStack.Dossier.Tests/Builder_CreateListTests.cs index 62be8bc..dde56aa 100644 --- a/TestStack.Dossier.Tests/Builder_CreateListTests.cs +++ b/TestStack.Dossier.Tests/Builder_CreateListTests.cs @@ -170,6 +170,7 @@ public void WhenBuildingObjectsImplicitly_ThenTheAnonymousValueFixtureIsSharedAc studentViewModels.Select(x => x.Grade).ShouldBeUnique(); } + [Fact] public void WhenBuildingObjectsWithCtorAndPrivateSetters_ThenSetPrivateSettersByDefault() { var dto = Builder.CreateListOfSize(1) diff --git a/TestStack.Dossier.Tests/DataSources/DataSourceConventionTests.cs b/TestStack.Dossier.Tests/DataSources/DataSourceConventionTests.cs index f87ae58..8087e27 100644 --- a/TestStack.Dossier.Tests/DataSources/DataSourceConventionTests.cs +++ b/TestStack.Dossier.Tests/DataSources/DataSourceConventionTests.cs @@ -10,7 +10,7 @@ namespace TestStack.Dossier.Tests.DataSources public class DataSourceConventionTests { [Theory] - [MemberData("TestCases")] + [MemberData(nameof(TestCases))] public void DataSourceConventions(DataSource sut, int expectedCount) { var collection = sut.Data.ToList(); diff --git a/TestStack.Dossier.Tests/DataSources/Dictionaries/Resources/FileDataConventions.cs b/TestStack.Dossier.Tests/DataSources/Dictionaries/Resources/FileDataConventions.cs index 651b7d5..4cfd92c 100644 --- a/TestStack.Dossier.Tests/DataSources/Dictionaries/Resources/FileDataConventions.cs +++ b/TestStack.Dossier.Tests/DataSources/Dictionaries/Resources/FileDataConventions.cs @@ -27,7 +27,7 @@ public void ApplyConventions() } } - public void Should_not_contain_duplicates(List collection, string fileName) + private void Should_not_contain_duplicates(List collection, string fileName) { var duplicates = collection .GroupBy(x => x) @@ -43,7 +43,7 @@ public void Should_not_contain_duplicates(List collection, string fileNa } } - public void Should_not_contain_null_or_empty_values(List collection, string fileName) + private void Should_not_contain_null_or_empty_values(List collection, string fileName) { var blanks = collection.Where(string.IsNullOrEmpty).ToList(); if (blanks.Any()) diff --git a/TestStack.Dossier.Tests/EquivalenceClasses/GeoEquivalenceClassesTests.cs b/TestStack.Dossier.Tests/EquivalenceClasses/GeoEquivalenceClassesTests.cs index 1e6f4a4..40a5181 100644 --- a/TestStack.Dossier.Tests/EquivalenceClasses/GeoEquivalenceClassesTests.cs +++ b/TestStack.Dossier.Tests/EquivalenceClasses/GeoEquivalenceClassesTests.cs @@ -22,11 +22,11 @@ protected override List GetData() { return new List { - new object[] {new Words(FromDictionary.GeoContinent), GenerateTestCasesForSut(Any.Continent)}, - new object[] {new Words(FromDictionary.GeoCountry), GenerateTestCasesForSut(Any.Country)}, - new object[] {new Words(FromDictionary.GeoCountryCode), GenerateTestCasesForSut(Any.CountryCode)}, - new object[] {new Words(FromDictionary.GeoLatitude), GenerateTestCasesForSut(Any.Latitude)}, - new object[] {new Words(FromDictionary.GeoLongitude), GenerateTestCasesForSut(Any.Longitude)}, + new object[] {new Words(FromDictionary.GeoContinent), GenerateTestCasesForSut(Any.Geography.Continent)}, + new object[] {new Words(FromDictionary.GeoCountry), GenerateTestCasesForSut(Any.Geography.Country)}, + new object[] {new Words(FromDictionary.GeoCountryCode), GenerateTestCasesForSut(Any.Geography.CountryCode)}, + new object[] {new Words(FromDictionary.GeoLatitude), GenerateTestCasesForSut(Any.Geography.Latitude)}, + new object[] {new Words(FromDictionary.GeoLongitude), GenerateTestCasesForSut(Any.Geography.Longitude)}, }; } } diff --git a/TestStack.Dossier.Tests/EquivalenceClasses/PersonEquivalenceClassesTests.cs b/TestStack.Dossier.Tests/EquivalenceClasses/PersonEquivalenceClassesTests.cs index eff87a8..7f13c4a 100644 --- a/TestStack.Dossier.Tests/EquivalenceClasses/PersonEquivalenceClassesTests.cs +++ b/TestStack.Dossier.Tests/EquivalenceClasses/PersonEquivalenceClassesTests.cs @@ -25,10 +25,10 @@ public void WhenGettingUniqueEmail_ThenReturnUniqueEmailsAcrossFixtureInstances( var any2 = new AnonymousValueFixture(); PersonEquivalenceExtensions.InitializeUniqueEmailAddressSource(); - generatedValues.Add(any2.UniqueEmailAddress()); + generatedValues.Add(any2.Person.UniqueEmailAddress()); for (var i = 0; i < source.Data.Count - 1; i++) { - generatedValues.Add(Any.UniqueEmailAddress()); + generatedValues.Add(Any.Person.UniqueEmailAddress()); } generatedValues.Distinct().Count() @@ -43,17 +43,17 @@ protected override List GetData() return new List { new object[] - {new Words(FromDictionary.PersonEmailAddress), GenerateTestCasesForSut(Any.EmailAddress)}, - new object[] {new Words(FromDictionary.PersonLanguage), GenerateTestCasesForSut(Any.Language)}, + {new Words(FromDictionary.PersonEmailAddress), GenerateTestCasesForSut(Any.Person.EmailAddress)}, + new object[] {new Words(FromDictionary.PersonLanguage), GenerateTestCasesForSut(Any.Person.Language)}, new object[] - {new Words(FromDictionary.PersonNameFirstFemale), GenerateTestCasesForSut(Any.FemaleFirstName)}, - new object[] {new Words(FromDictionary.PersonNameFirst), GenerateTestCasesForSut(Any.FirstName)}, - new object[] {new Words(FromDictionary.PersonNameFull), GenerateTestCasesForSut(Any.FullName)}, - new object[] {new Words(FromDictionary.PersonNameLast), GenerateTestCasesForSut(Any.LastName)}, + {new Words(FromDictionary.PersonNameFirstFemale), GenerateTestCasesForSut(Any.Person.NameFirstFemale)}, + new object[] {new Words(FromDictionary.PersonNameFirst), GenerateTestCasesForSut(Any.Person.NameFirst)}, + new object[] {new Words(FromDictionary.PersonNameFull), GenerateTestCasesForSut(Any.Person.NameFull)}, + new object[] {new Words(FromDictionary.PersonNameLast), GenerateTestCasesForSut(Any.Person.NameLast)}, new object[] - {new Words(FromDictionary.PersonNameFirstMale), GenerateTestCasesForSut(Any.MaleFirstName)}, - new object[] {new Words(FromDictionary.PersonNameSuffix), GenerateTestCasesForSut(Any.Suffix)}, - new object[] {new Words(FromDictionary.PersonNameTitle), GenerateTestCasesForSut(Any.Title)}, + {new Words(FromDictionary.PersonNameFirstMale), GenerateTestCasesForSut(Any.Person.NameFirstMale)}, + new object[] {new Words(FromDictionary.PersonNameSuffix), GenerateTestCasesForSut(Any.Person.NameSuffix)}, + new object[] {new Words(FromDictionary.PersonNameTitle), GenerateTestCasesForSut(Any.Person.NameTitle)}, }; } } diff --git a/TestStack.Dossier.Tests/TestStack.Dossier.Tests.csproj b/TestStack.Dossier.Tests/TestStack.Dossier.Tests.csproj index a9a044c..3eabdb7 100644 --- a/TestStack.Dossier.Tests/TestStack.Dossier.Tests.csproj +++ b/TestStack.Dossier.Tests/TestStack.Dossier.Tests.csproj @@ -1,17 +1,20 @@ - + - netcoreapp2.0;net452 + netcoreapp2.0;net472 - - + + - - - - + + + + + all + runtime; build; native; contentfiles; analyzers + diff --git a/TestStack.Dossier/TestStack.Dossier.csproj b/TestStack.Dossier/TestStack.Dossier.csproj index 08f6c62..7ce6c22 100644 --- a/TestStack.Dossier/TestStack.Dossier.csproj +++ b/TestStack.Dossier/TestStack.Dossier.csproj @@ -1,10 +1,9 @@ - + - netstandard1.5;net452 + netstandard2.0 TestStack.Dossier TestStack.Dossier - 4.0.0 Robert Moore, Michael Whelan, TestStack TestStack.Dossier provides you with the code infrastructure to easily and quickly generate test fixture data for your automated tests in a terse, readable and maintainable way using the Test Data Builder, anonymous value and equivalence class patterns. Formerly called NTestDataBuilder. @@ -149,8 +148,8 @@ - - + + From 1b650474ebbf1c1d9e0ff04cdf8179d0ce842c56 Mon Sep 17 00:00:00 2001 From: Rob Moore Date: Sun, 13 Jan 2019 19:41:31 +0800 Subject: [PATCH 68/86] Updated appveyor.yml --- appveyor.yml | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 54dbffc..d4cbd39 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -8,28 +8,30 @@ environment: secure: cBxvAtTgSlWVblTXtx8QKygh2HQeYZ9i0plMjJzCTNInGCm1XyG+nrSs18qUtC8W before_build: - ps: >- - nuget restore + dotnet restore - choco install -y --no-progress git.install GitReleaseManager.Portable + dotnet tool install -g GitVersion.Tool - npm install github-release-notes -g - - GitVersion /output buildserver /updateassemblyinfo - - If (Test-Path ".\PreBuild.ps1") { - - & ".\PreBuild.ps1" - - } + dotnet gitversion /output buildserver + npm install github-release-notes -g +dotnet_csproj: + patch: true + file: '**\*.csproj' + version: '{version}' + package_version: $(GitVersion_NuGetVersion) + assembly_version: $(GitVersion_AssemblySemVer) + file_version: $(GitVersion_AssemblySemFileVer) + informational_version: (GitVersion_InformationalVersion$) build: parallel: true verbosity: minimal + publish_nuget: true after_build: - ps: >- - Get-ChildItem -Recurse *.nuspec | foreach { nuget pack $_.FullName -Properties "Configuration=Release;Platform=AnyCPU" -Symbols -Version $Env:GitVersion_NuGetVersion } + #dotnet pack $Env:APPVEYOR_PROJECT_NAME/$Env:APPVEYOR_PROJECT_NAME.csproj --configuration Release /p:Version="$Env:GitVersion_NuGetVersion" - $currentTag = git tag -l --points-at HEAD + $currentCommitIsTagged = git tag -l --points-at HEAD $HTTP_Request = [System.Net.WebRequest]::Create("https://api.github.com/repos/$env:GitHubOrganisation/$env:APPVEYOR_PROJECT_NAME/releases/tags/$Env:GitVersion_NuGetVersion") @@ -42,8 +44,9 @@ after_build: } catch [Net.WebException] { [System.Net.HttpWebResponse] $resp = [System.Net.HttpWebResponse] $_.Exception.Response + $noExistingGitHubRelease = $resp.StatusCode -eq 404 - if ($currentTag -And $resp.StatusCode -eq 404) { + if ($currentCommitIsTagged -And $noExistingGitHubRelease) { $env:SHOULD_DEPLOY = 'true' From d65228b358920d37a761dc7c6e616c57b7d4dd05 Mon Sep 17 00:00:00 2001 From: Rob Moore Date: Sun, 13 Jan 2019 19:53:27 +0800 Subject: [PATCH 69/86] Adding gitversion tool version and explicit dotnet pack --- appveyor.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index d4cbd39..3a7c79e 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -10,7 +10,7 @@ before_build: - ps: >- dotnet restore - dotnet tool install -g GitVersion.Tool + dotnet tool install -g GitVersion.Tool -version 4.0.1-beta1-58 dotnet gitversion /output buildserver @@ -26,10 +26,9 @@ dotnet_csproj: build: parallel: true verbosity: minimal - publish_nuget: true after_build: - ps: >- - #dotnet pack $Env:APPVEYOR_PROJECT_NAME/$Env:APPVEYOR_PROJECT_NAME.csproj --configuration Release /p:Version="$Env:GitVersion_NuGetVersion" + dotnet pack $Env:APPVEYOR_PROJECT_NAME/$Env:APPVEYOR_PROJECT_NAME.csproj --configuration Release /p:Version="$Env:GitVersion_NuGetVersion" $currentCommitIsTagged = git tag -l --points-at HEAD From c7c12422e8b72b2656ef3587ddfce90933df13cf Mon Sep 17 00:00:00 2001 From: Rob Moore Date: Sun, 13 Jan 2019 21:56:04 +0800 Subject: [PATCH 70/86] Updated appveyor file --- appveyor.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 3a7c79e..fbc162c 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -10,7 +10,7 @@ before_build: - ps: >- dotnet restore - dotnet tool install -g GitVersion.Tool -version 4.0.1-beta1-58 + dotnet tool install -g GitVersion.Tool --version 4.0.1-beta1-58 dotnet gitversion /output buildserver @@ -28,7 +28,7 @@ build: verbosity: minimal after_build: - ps: >- - dotnet pack $Env:APPVEYOR_PROJECT_NAME/$Env:APPVEYOR_PROJECT_NAME.csproj --configuration Release /p:Version="$Env:GitVersion_NuGetVersion" + dotnet pack $Env:APPVEYOR_PROJECT_NAME/$Env:APPVEYOR_PROJECT_NAME.csproj --configuration Release /p:Version="$Env:GitVersion_NuGetVersion" --no-build $currentCommitIsTagged = git tag -l --points-at HEAD From daa2f3550777af7fb4e247353065fe000a1f1a50 Mon Sep 17 00:00:00 2001 From: Rob Moore Date: Sun, 13 Jan 2019 22:13:58 +0800 Subject: [PATCH 71/86] Removing xunit parallelisation since it causes intermittent test breakages with tests that check GlobalValueSupplier --- TestStack.Dossier.Tests/Assembly.cs | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 TestStack.Dossier.Tests/Assembly.cs diff --git a/TestStack.Dossier.Tests/Assembly.cs b/TestStack.Dossier.Tests/Assembly.cs new file mode 100644 index 0000000..7db8497 --- /dev/null +++ b/TestStack.Dossier.Tests/Assembly.cs @@ -0,0 +1,3 @@ +using Xunit; + +[assembly: CollectionBehavior(DisableTestParallelization = true)] \ No newline at end of file From 29875ba1ee5ce56573d1e08b40b38490b7338b3b Mon Sep 17 00:00:00 2001 From: Rob Moore Date: Sun, 13 Jan 2019 22:19:16 +0800 Subject: [PATCH 72/86] Set nupkg output to be working directory so it's found for artifact publishing --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index fbc162c..86ccfc0 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -28,7 +28,7 @@ build: verbosity: minimal after_build: - ps: >- - dotnet pack $Env:APPVEYOR_PROJECT_NAME/$Env:APPVEYOR_PROJECT_NAME.csproj --configuration Release /p:Version="$Env:GitVersion_NuGetVersion" --no-build + dotnet pack $Env:APPVEYOR_PROJECT_NAME/$Env:APPVEYOR_PROJECT_NAME.csproj --configuration Release /p:Version="$Env:GitVersion_NuGetVersion" --no-build --output "$Env:APPVEYOR_BUILD_FOLDER" $currentCommitIsTagged = git tag -l --points-at HEAD From 0d96dd7ec55127c217f89e6542d4f082cddc1e9a Mon Sep 17 00:00:00 2001 From: Rob Moore Date: Sun, 13 Jan 2019 22:28:17 +0800 Subject: [PATCH 73/86] Fixing up the parameters to dotnet pack --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index 86ccfc0..4cf5862 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -28,7 +28,7 @@ build: verbosity: minimal after_build: - ps: >- - dotnet pack $Env:APPVEYOR_PROJECT_NAME/$Env:APPVEYOR_PROJECT_NAME.csproj --configuration Release /p:Version="$Env:GitVersion_NuGetVersion" --no-build --output "$Env:APPVEYOR_BUILD_FOLDER" + dotnet pack $Env:APPVEYOR_PROJECT_NAME/$Env:APPVEYOR_PROJECT_NAME.csproj --configuration Release /p:PackageVersion="$Env:GitVersion_NuGetVersion" --no-build --output "$Env:APPVEYOR_BUILD_FOLDER" --include-symbols $currentCommitIsTagged = git tag -l --points-at HEAD From d3ba7348a17580e174551559afbf69d7f9507378 Mon Sep 17 00:00:00 2001 From: Rob Moore Date: Sun, 13 Jan 2019 22:47:39 +0800 Subject: [PATCH 74/86] Another go at getting versioning correct --- appveyor.yml | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 4cf5862..cbf36f5 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -15,17 +15,8 @@ before_build: dotnet gitversion /output buildserver npm install github-release-notes -g -dotnet_csproj: - patch: true - file: '**\*.csproj' - version: '{version}' - package_version: $(GitVersion_NuGetVersion) - assembly_version: $(GitVersion_AssemblySemVer) - file_version: $(GitVersion_AssemblySemFileVer) - informational_version: (GitVersion_InformationalVersion$) -build: - parallel: true - verbosity: minimal +build_script: +- dotnet build **\*.csproj --configuration Release -p:VersionPrefix="$Env:GitVersion_NuGetVersion" --verbosity minimal --version-suffix "$Env:GitVersion_NuGetVersion" -p:FileVersion "$Env:GitVersion_AssemblySemFileVer" -p:InformationalVersion "$Env:GitVersion_InformationalVersion" after_build: - ps: >- dotnet pack $Env:APPVEYOR_PROJECT_NAME/$Env:APPVEYOR_PROJECT_NAME.csproj --configuration Release /p:PackageVersion="$Env:GitVersion_NuGetVersion" --no-build --output "$Env:APPVEYOR_BUILD_FOLDER" --include-symbols From 959f462b615199a3180ca94d99f30e2e28514073 Mon Sep 17 00:00:00 2001 From: Rob Moore Date: Sun, 13 Jan 2019 23:07:50 +0800 Subject: [PATCH 75/86] More versioning tweaks --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index cbf36f5..a357791 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -16,7 +16,7 @@ before_build: npm install github-release-notes -g build_script: -- dotnet build **\*.csproj --configuration Release -p:VersionPrefix="$Env:GitVersion_NuGetVersion" --verbosity minimal --version-suffix "$Env:GitVersion_NuGetVersion" -p:FileVersion "$Env:GitVersion_AssemblySemFileVer" -p:InformationalVersion "$Env:GitVersion_InformationalVersion" +- dotnet build **\*.csproj --configuration Release --verbosity minimal -p:VersionPrefix="$Env:GitVersion_NuGetVersion" -p:FileVersion="$Env:GitVersion_AssemblySemFileVer" -p:InformationalVersion="$Env:GitVersion_InformationalVersion" after_build: - ps: >- dotnet pack $Env:APPVEYOR_PROJECT_NAME/$Env:APPVEYOR_PROJECT_NAME.csproj --configuration Release /p:PackageVersion="$Env:GitVersion_NuGetVersion" --no-build --output "$Env:APPVEYOR_BUILD_FOLDER" --include-symbols From db6c50fede3bd58b8efc52a3bd75d55e50d2005d Mon Sep 17 00:00:00 2001 From: Rob Moore Date: Sun, 13 Jan 2019 23:23:29 +0800 Subject: [PATCH 76/86] Oops --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index a357791..372cd4d 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -16,7 +16,7 @@ before_build: npm install github-release-notes -g build_script: -- dotnet build **\*.csproj --configuration Release --verbosity minimal -p:VersionPrefix="$Env:GitVersion_NuGetVersion" -p:FileVersion="$Env:GitVersion_AssemblySemFileVer" -p:InformationalVersion="$Env:GitVersion_InformationalVersion" +- dotnet build --source "**/*.csproj" --configuration Release --verbosity minimal -p:VersionPrefix="$Env:GitVersion_NuGetVersion" -p:FileVersion="$Env:GitVersion_AssemblySemFileVer" -p:InformationalVersion="$Env:GitVersion_InformationalVersion" after_build: - ps: >- dotnet pack $Env:APPVEYOR_PROJECT_NAME/$Env:APPVEYOR_PROJECT_NAME.csproj --configuration Release /p:PackageVersion="$Env:GitVersion_NuGetVersion" --no-build --output "$Env:APPVEYOR_BUILD_FOLDER" --include-symbols From 09dff09a1c813229ad6ca557d87547e4218e9180 Mon Sep 17 00:00:00 2001 From: Rob Moore Date: Sun, 13 Jan 2019 23:37:46 +0800 Subject: [PATCH 77/86] Not in PowerShell there haha --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index 372cd4d..01b8614 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -16,7 +16,7 @@ before_build: npm install github-release-notes -g build_script: -- dotnet build --source "**/*.csproj" --configuration Release --verbosity minimal -p:VersionPrefix="$Env:GitVersion_NuGetVersion" -p:FileVersion="$Env:GitVersion_AssemblySemFileVer" -p:InformationalVersion="$Env:GitVersion_InformationalVersion" +- dotnet build --source "**/*.csproj" --configuration Release --verbosity minimal -p:VersionPrefix="$(GitVersion_NuGetVersion)" -p:FileVersion="$(GitVersion_AssemblySemFileVer)" -p:InformationalVersion="$(GitVersion_InformationalVersion)" after_build: - ps: >- dotnet pack $Env:APPVEYOR_PROJECT_NAME/$Env:APPVEYOR_PROJECT_NAME.csproj --configuration Release /p:PackageVersion="$Env:GitVersion_NuGetVersion" --no-build --output "$Env:APPVEYOR_BUILD_FOLDER" --include-symbols From 6c96e1ed93ad13c48e09ae83e18598ac1c8851c3 Mon Sep 17 00:00:00 2001 From: Rob Moore Date: Mon, 14 Jan 2019 00:01:19 +0800 Subject: [PATCH 78/86] lol --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index 01b8614..5a5ab94 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -16,7 +16,7 @@ before_build: npm install github-release-notes -g build_script: -- dotnet build --source "**/*.csproj" --configuration Release --verbosity minimal -p:VersionPrefix="$(GitVersion_NuGetVersion)" -p:FileVersion="$(GitVersion_AssemblySemFileVer)" -p:InformationalVersion="$(GitVersion_InformationalVersion)" +- ps: dotnet build --source "**/*.csproj" --configuration Release --verbosity minimal -p:VersionPrefix="$Env:GitVersion_NuGetVersion" -p:FileVersion="$Env:GitVersion_AssemblySemFileVer" -p:InformationalVersion="$Env:GitVersion_InformationalVersion" after_build: - ps: >- dotnet pack $Env:APPVEYOR_PROJECT_NAME/$Env:APPVEYOR_PROJECT_NAME.csproj --configuration Release /p:PackageVersion="$Env:GitVersion_NuGetVersion" --no-build --output "$Env:APPVEYOR_BUILD_FOLDER" --include-symbols From b4b8e07f959607eff67ca939a42547195a31dd18 Mon Sep 17 00:00:00 2001 From: Rob Moore Date: Mon, 14 Jan 2019 00:16:05 +0800 Subject: [PATCH 79/86] Re-added public api approver test (woot!) --- ...piChecked_ShouldHaveNoChanges.approved.txt | 30 ++++--------------- .../PublicApiApproverTests.cs | 16 +++++----- .../TestStack.Dossier.Tests.csproj | 1 + 3 files changed, 14 insertions(+), 33 deletions(-) diff --git a/TestStack.Dossier.Tests/PublicApiApproval/PublicApiApproverTests.GivenDossierAssembly_WhenPublicApiChecked_ShouldHaveNoChanges.approved.txt b/TestStack.Dossier.Tests/PublicApiApproval/PublicApiApproverTests.GivenDossierAssembly_WhenPublicApiChecked_ShouldHaveNoChanges.approved.txt index c1b8966..ad5a50a 100644 --- a/TestStack.Dossier.Tests/PublicApiApproval/PublicApiApproverTests.GivenDossierAssembly_WhenPublicApiChecked_ShouldHaveNoChanges.approved.txt +++ b/TestStack.Dossier.Tests/PublicApiApproval/PublicApiApproverTests.GivenDossierAssembly_WhenPublicApiChecked_ShouldHaveNoChanges.approved.txt @@ -1,12 +1,5 @@ -[assembly: System.Runtime.CompilerServices.InternalsVisibleToAttribute("DynamicProxyGenAssembly2")] -[assembly: System.Runtime.CompilerServices.InternalsVisibleToAttribute("TestStack.Dossier.Tests")] -[assembly: System.Runtime.InteropServices.ComVisibleAttribute(false)] -[assembly: System.Runtime.InteropServices.GuidAttribute("24a139fb-b390-4f14-9be6-cf9fb354bb5d")] -[assembly: System.Runtime.Versioning.TargetFrameworkAttribute(".NETFramework,Version=v4.0", FrameworkDisplayName=".NET Framework 4")] - namespace TestStack.Dossier { - public class AddressAusEquivalence { public AddressAusEquivalence(TestStack.Dossier.AnonymousValueFixture fixture) { } @@ -55,14 +48,14 @@ namespace TestStack.Dossier public TestStack.Dossier.CompanyEquivalence Company { get; } public static System.Collections.Generic.IEnumerable DefaultValueSuppliers { get; } public TestStack.Dossier.FinanceEquivalence Finance { get; } - public Ploeh.AutoFixture.Fixture Fixture { get; } + public AutoFixture.Fixture Fixture { get; } public TestStack.Dossier.GeoEquivalence Geography { get; } public static System.Collections.Generic.ICollection GlobalValueSuppliers { get; } public TestStack.Dossier.IdentifierEquivalence Identifier { get; } public TestStack.Dossier.InternetEquivalence Internet { get; } public System.Collections.Generic.ICollection LocalValueSuppliers { get; } public TestStack.Dossier.PersonEquivalence Person { get; } - public Ploeh.AutoFixture.RegularExpressionGenerator RegexGenerator { get; } + public AutoFixture.RegularExpressionGenerator RegexGenerator { get; } public T Get(System.Linq.Expressions.Expression> property) { } public object Get(System.Type type, string propertyName) { } public TestStack.Dossier.DataSources.Dictionaries.Words Words(string dictionaryName) { } @@ -200,15 +193,15 @@ namespace TestStack.Dossier protected bool Has(System.Linq.Expressions.Expression> property) { } protected bool Has(string propertyName) { } public virtual bool IsListBuilderProxy() { } + public static TObject op_Implicit(TestStack.Dossier.TestDataBuilder builder) { } + public static System.Collections.Generic.List op_Implicit(TestStack.Dossier.TestDataBuilder builder) { } public virtual TBuilder Set(System.Linq.Expressions.Expression> property, TValue value) { } public virtual TBuilder Set(System.Linq.Expressions.Expression> property, System.Func factory) { } } } namespace TestStack.Dossier.DataSources { - public abstract class DataSource : TestStack.Dossier.DataSources.IDataSource - { protected DataSource(TestStack.Dossier.DataSources.Generators.IGenerator generator) { } protected DataSource() { } @@ -218,7 +211,6 @@ namespace TestStack.Dossier.DataSources public virtual T Next() { } } public interface IDataSource - { System.Collections.Generic.IList Data { get; } TestStack.Dossier.DataSources.Generators.IGenerator Generator { get; } @@ -227,7 +219,6 @@ namespace TestStack.Dossier.DataSources } namespace TestStack.Dossier.DataSources.Dictionaries { - [System.ObsoleteAttribute("FileDictionarySource is deprecated, please use Words(FromDictionary) instead.")] public abstract class FileDictionarySource : TestStack.Dossier.DataSources.DataSource { @@ -310,7 +301,6 @@ namespace TestStack.Dossier.DataSources.Dictionaries } namespace TestStack.Dossier.DataSources.Generators { - public interface IGenerator { int ListSize { get; set; } @@ -337,7 +327,6 @@ namespace TestStack.Dossier.DataSources.Generators } namespace TestStack.Dossier.DataSources.Geography { - [System.ObsoleteAttribute("GeoContinentSource is deprecated, please use Words(FromDictionary.GeoContinent) i" + "nstead.")] public class GeoContinentSource : TestStack.Dossier.DataSources.Dictionaries.FileDictionarySource @@ -371,7 +360,6 @@ namespace TestStack.Dossier.DataSources.Geography } namespace TestStack.Dossier.DataSources.Person { - [System.ObsoleteAttribute("PersonEmailAddressSource is deprecated, please use Words(FromDictionary.PersonEma" + "ilAddress) instead.")] public class PersonEmailAddressSource : TestStack.Dossier.DataSources.Dictionaries.FileDictionarySource @@ -430,7 +418,6 @@ namespace TestStack.Dossier.DataSources.Person } namespace TestStack.Dossier.DataSources.Picking { - public class Pick { public Pick() { } @@ -438,13 +425,11 @@ namespace TestStack.Dossier.DataSources.Picking public static TestStack.Dossier.DataSources.Picking.RepeatingSequenceSource RepeatingSequenceFrom(System.Collections.Generic.IList list) { } } public class RandomItemSource : TestStack.Dossier.DataSources.DataSource - { public RandomItemSource(System.Collections.Generic.IList list) { } protected override System.Collections.Generic.IList InitializeDataSource() { } } public class RepeatingSequenceSource : TestStack.Dossier.DataSources.DataSource - { public RepeatingSequenceSource(System.Collections.Generic.IList list) { } protected override System.Collections.Generic.IList InitializeDataSource() { } @@ -452,7 +437,6 @@ namespace TestStack.Dossier.DataSources.Picking } namespace TestStack.Dossier.EquivalenceClasses { - public class static EnumEquivalenceClasses { public static TEnum Except(this TestStack.Dossier.AnonymousValueFixture fixture, params TEnum[] except) @@ -477,7 +461,6 @@ namespace TestStack.Dossier.EquivalenceClasses } namespace TestStack.Dossier.EquivalenceClasses.Geo { - public class static GeographyEquivalenceClassescs { [System.ObsoleteAttribute("Continent is deprecated, please use Geography.Continent instead.")] @@ -494,7 +477,6 @@ namespace TestStack.Dossier.EquivalenceClasses.Geo } namespace TestStack.Dossier.EquivalenceClasses.Person { - public class static PersonEquivalenceClasses { [System.ObsoleteAttribute("EmailAddress is deprecated, please use Person.EmailAddress instead.")] @@ -521,7 +503,6 @@ namespace TestStack.Dossier.EquivalenceClasses.Person } namespace TestStack.Dossier.Factories { - public class AllPropertiesFactory : TestStack.Dossier.Factories.CallConstructorFactory { public AllPropertiesFactory() { } @@ -559,7 +540,6 @@ namespace TestStack.Dossier.Factories } namespace TestStack.Dossier.Lists { - public class ListBuilder where TObject : class where TBuilder : TestStack.Dossier.TestDataBuilder<, >, new () @@ -567,6 +547,7 @@ namespace TestStack.Dossier.Lists public TBuilder All() { } public System.Collections.Generic.IList BuildList() { } public System.Collections.Generic.IEnumerable GetBuilders() { } + public static System.Collections.Generic.List op_Implicit(TestStack.Dossier.Lists.ListBuilder builder) { } public TBuilder TheFirst(int howMany) { } public TBuilder TheLast(int howMany) { } public TBuilder TheNext(int howMany) { } @@ -600,7 +581,6 @@ namespace TestStack.Dossier.Lists } namespace TestStack.Dossier.Suppliers { - public class DefaultEmailValueSupplier : TestStack.Dossier.IAnonymousValueSupplier { public DefaultEmailValueSupplier() { } diff --git a/TestStack.Dossier.Tests/PublicApiApproval/PublicApiApproverTests.cs b/TestStack.Dossier.Tests/PublicApiApproval/PublicApiApproverTests.cs index c3f39b6..fd38952 100644 --- a/TestStack.Dossier.Tests/PublicApiApproval/PublicApiApproverTests.cs +++ b/TestStack.Dossier.Tests/PublicApiApproval/PublicApiApproverTests.cs @@ -5,13 +5,13 @@ namespace TestStack.Dossier.Tests.PublicApiApproval { public class PublicApiApproverTests { - //[Fact] - //public void GivenDossierAssembly_WhenPublicApiChecked_ShouldHaveNoChanges() - //{ - // ShouldlyConfiguration.DiffTools.KnownDoNotLaunchStrategies.TeamCity.ShouldNotLaunch(); - // var dossierAssembly = typeof (AnonymousValueFixture).Assembly; - // var publicApi = PublicApiGenerator.PublicApiGenerator.GetPublicApi(dossierAssembly); - // publicApi.ShouldMatchApproved(); - //} + [Fact] + public void GivenDossierAssembly_WhenPublicApiChecked_ShouldHaveNoChanges() + { + ShouldlyConfiguration.DiffTools.KnownDoNotLaunchStrategies.TeamCity.ShouldNotLaunch(); + var dossierAssembly = typeof(AnonymousValueFixture).Assembly; + var publicApi = PublicApiGenerator.ApiGenerator.GeneratePublicApi(dossierAssembly, shouldIncludeAssemblyAttributes: false); + publicApi.ShouldMatchApproved(); + } } } diff --git a/TestStack.Dossier.Tests/TestStack.Dossier.Tests.csproj b/TestStack.Dossier.Tests/TestStack.Dossier.Tests.csproj index 3eabdb7..0e7fdcb 100644 --- a/TestStack.Dossier.Tests/TestStack.Dossier.Tests.csproj +++ b/TestStack.Dossier.Tests/TestStack.Dossier.Tests.csproj @@ -8,6 +8,7 @@ + From 1260e8dc8a700321912f899d9d483c9078c745c6 Mon Sep 17 00:00:00 2001 From: Rob Moore Date: Mon, 14 Jan 2019 01:02:03 +0800 Subject: [PATCH 80/86] Added xmldocs --- .../EquivalenceClasses/FinanceEquivalence.cs | 4 ---- TestStack.Dossier/TestStack.Dossier.csproj | 14 +++++++++++++- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/TestStack.Dossier/EquivalenceClasses/FinanceEquivalence.cs b/TestStack.Dossier/EquivalenceClasses/FinanceEquivalence.cs index e3f2364..c98e8a0 100644 --- a/TestStack.Dossier/EquivalenceClasses/FinanceEquivalence.cs +++ b/TestStack.Dossier/EquivalenceClasses/FinanceEquivalence.cs @@ -22,7 +22,6 @@ public FinanceEquivalence(AnonymousValueFixture fixture) /// /// Generate and return a finance credit card number. /// - /// The fixture to generate a value for. /// The generated value. public string CreditCardNumber() { @@ -32,7 +31,6 @@ public string CreditCardNumber() /// /// Generate and return a finance credit card type. /// - /// The fixture to generate a value for. /// The generated value. public string CreditCardType() { @@ -42,7 +40,6 @@ public string CreditCardType() /// /// Generate and return a finance currency name. /// - /// The fixture to generate a value for. /// The generated value. public string Currency() { @@ -52,7 +49,6 @@ public string Currency() /// /// Generate and return a finance currency code. /// - /// The fixture to generate a value for. /// The generated value. public string CurrencyCode() { diff --git a/TestStack.Dossier/TestStack.Dossier.csproj b/TestStack.Dossier/TestStack.Dossier.csproj index 7ce6c22..5fc48a2 100644 --- a/TestStack.Dossier/TestStack.Dossier.csproj +++ b/TestStack.Dossier/TestStack.Dossier.csproj @@ -12,7 +12,19 @@ testing data-generation test-fixture nbuilder nsubstitute autofixture mocking equivalence-class test-data-builder anonymous-value ntestdatabuilder https://github.com/TestStack/TestStack.Dossier - + + + bin\$(Configuration)\$(TargetFramework)\$(AssemblyName).xml + true + + + + + + + + + From 43b7250b650fc5ca449efbc8a3d2499b4aa2a7ad Mon Sep 17 00:00:00 2001 From: Rob Moore Date: Mon, 14 Jan 2019 01:07:11 +0800 Subject: [PATCH 81/86] Trying to get debug info into test project in release build (not working :/) --- TestStack.Dossier.Tests/TestStack.Dossier.Tests.csproj | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/TestStack.Dossier.Tests/TestStack.Dossier.Tests.csproj b/TestStack.Dossier.Tests/TestStack.Dossier.Tests.csproj index 0e7fdcb..a1a527f 100644 --- a/TestStack.Dossier.Tests/TestStack.Dossier.Tests.csproj +++ b/TestStack.Dossier.Tests/TestStack.Dossier.Tests.csproj @@ -4,6 +4,11 @@ netcoreapp2.0;net472 + + full + true + + From 0c6ca431a3015a1a411465a78dadd6147deeabe9 Mon Sep 17 00:00:00 2001 From: Rob Moore Date: Mon, 14 Jan 2019 12:12:46 +0800 Subject: [PATCH 82/86] Added badges --- README.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 78c9fba..585c0a6 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,9 @@ # TestStack.Dossier +[![Build status](https://ci.appveyor.com/api/projects/status/h8d3xulha7ecwb6m/branch/master?svg=true)](https://ci.appveyor.com/project/MRCollective/nhibernate-sqlazure) +[![NuGet downloads](https://img.shields.io/nuget/dt/TestStack.Dossier.svg)](https://www.nuget.org/packages/TestStack.Dossier) +[![NuGet version](https://img.shields.io/nuget/vpre/TestStack.Dossier.svg)](https://www.nuget.org/packages/TestStack.Dossier) + TestStack.Dossier provides you with the code infrastructure to easily and quickly generate test fixture data for your automated tests in a terse, readable and maintainable way using the Test Data Builder, anonymous value and equivalence class patterns. For more information please see the [blog post](http://robdmoore.id.au/blog/2013/05/26/test-data-generation-the-right-way-object-mother-test-data-builders-nsubstitute-nbuilder/) that gives the theory behind the approach this library was intended for and the [presentation and example code](https://github.com/robdmoore/TestFixtureDataGenerationPresentation) that gives a concrete example of the usage of the library (and the theory behind it). @@ -154,4 +158,4 @@ More comprehensive documentation is available on our [documentation website](htt If you would like to contribute to this project then feel free to communicate with us via Twitter ([@teststacknet](https://twitter.com/teststacknet)) or alternatively submit a [pull request](https://github.com/TestStack/TestStack.Dossier/compare/) / [issue](https://github.com/TestStack/TestStack.Dossier/issues/new). -Feel free to check out our [up-for-grabs issues if you don't know where to start](https://github.com/TestStack/TestStack.Dossier/labels/up-for-grabs). \ No newline at end of file +Feel free to check out our [up-for-grabs issues if you don't know where to start](https://github.com/TestStack/TestStack.Dossier/labels/up-for-grabs). From bc002067ccc640a522355d7546ea156eed89a5e6 Mon Sep 17 00:00:00 2001 From: Rob Moore Date: Mon, 14 Jan 2019 12:13:43 +0800 Subject: [PATCH 83/86] Added syntax highlighting on readme --- README.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 585c0a6..75ec6dc 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@ Prior to v2.0 this library was known as NTestDataBuilder. 3. If you want to build a custom builder class, e.g. for a domain object, so you can use the builder as documentation and also to make the experience of building that class in your tests more rich then you need to extend the TestDataBuilder class like in the following code example: - +```csharp // Customer.cs public class Customer @@ -96,19 +96,19 @@ Prior to v2.0 this library was known as NTestDataBuilder. ); } } - +``` 4. Use the builder in a test, e.g. - +```csharp var customer = new CustomerBuilder() .WithFirstName("Robert") .Build(); - +``` 5. Consider using the Object Mother pattern in combination with the builders, see [my blog post](http://robdmoore.id.au/blog/2013/05/26/test-data-generation-the-right-way-object-mother-test-data-builders-nsubstitute-nbuilder/) for a description of how I use this library. ## Getting started - building a list of objects This library allows you to build a list of entities fluently and tersely. Here is an example: - +```csharp var customers = CustomerBuilder.CreateListOfSize(5) .TheFirst(1).WithFirstName("First") .TheNext(1).WithLastName("Next Last") @@ -116,9 +116,9 @@ This library allows you to build a list of entities fluently and tersely. Here i .ThePrevious(2).With(b => b.WithLastName("last" + (++i).ToString())) .All().WhoJoinedIn(1999) .BuildList(); - +``` This would create the following (represented as json) - note the anonymous values that are generated: - +```json [ { "FirstName":"First", @@ -146,7 +146,7 @@ This would create the following (represented as json) - note the anonymous value "YearJoined":1999 } ] - +``` The same works with the generic `Builder` implementation too. From 3e7cf85a7eed24d483410f50ba0e07fa5e74efa5 Mon Sep 17 00:00:00 2001 From: Rob Moore Date: Mon, 14 Jan 2019 12:28:54 +0800 Subject: [PATCH 84/86] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 75ec6dc..e8d08d4 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ TestStack.Dossier provides you with the code infrastructure to easily and quickly generate test fixture data for your automated tests in a terse, readable and maintainable way using the Test Data Builder, anonymous value and equivalence class patterns. -For more information please see the [blog post](http://robdmoore.id.au/blog/2013/05/26/test-data-generation-the-right-way-object-mother-test-data-builders-nsubstitute-nbuilder/) that gives the theory behind the approach this library was intended for and the [presentation and example code](https://github.com/robdmoore/TestFixtureDataGenerationPresentation) that gives a concrete example of the usage of the library (and the theory behind it). +For more information please see the [blog post](http://robdmoore.id.au/blog/2013/05/26/test-data-generation-the-right-way-object-mother-test-data-builders-nsubstitute-nbuilder) that gives the theory behind the approach this library was intended for and the [presentation and example code](https://github.com/robdmoore/TestFixtureDataGenerationPresentation) that gives a concrete example of the usage of the library (and the theory behind it). TestStack.Dossier is integrated with NSubstitute for proxy/mock/substitute object generation and AutoFixture for anonymous value generation. Version 1 was integrated with NBuilder for list generation, but that is now replaced with internal code that uses Castle Dynamic Proxy (il-merged into the dll) for an even terser syntax. From 05041025c5fb55db00db0910a7f6c30e6ead2a66 Mon Sep 17 00:00:00 2001 From: Rob Moore Date: Mon, 14 Jan 2019 12:29:36 +0800 Subject: [PATCH 85/86] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e8d08d4..94cd318 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ TestStack.Dossier provides you with the code infrastructure to easily and quickly generate test fixture data for your automated tests in a terse, readable and maintainable way using the Test Data Builder, anonymous value and equivalence class patterns. -For more information please see the [blog post](http://robdmoore.id.au/blog/2013/05/26/test-data-generation-the-right-way-object-mother-test-data-builders-nsubstitute-nbuilder) that gives the theory behind the approach this library was intended for and the [presentation and example code](https://github.com/robdmoore/TestFixtureDataGenerationPresentation) that gives a concrete example of the usage of the library (and the theory behind it). +For more information please see the [blog post](https://robdmoore.id.au/blog/2013/05/25/test-data-generation-the-right-way-object-mother-test-data-builders-nsubstitute-nbuilder) that gives the theory behind the approach this library was intended for and the [presentation and example code](https://github.com/robdmoore/TestFixtureDataGenerationPresentation) that gives a concrete example of the usage of the library (and the theory behind it). TestStack.Dossier is integrated with NSubstitute for proxy/mock/substitute object generation and AutoFixture for anonymous value generation. Version 1 was integrated with NBuilder for list generation, but that is now replaced with internal code that uses Castle Dynamic Proxy (il-merged into the dll) for an even terser syntax. From 3ca2e7579587932be10c846c114a60a8035b0e6a Mon Sep 17 00:00:00 2001 From: Rob Moore Date: Mon, 14 Jan 2019 12:35:53 +0800 Subject: [PATCH 86/86] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 94cd318..69515f4 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,7 @@ [![Build status](https://ci.appveyor.com/api/projects/status/h8d3xulha7ecwb6m/branch/master?svg=true)](https://ci.appveyor.com/project/MRCollective/nhibernate-sqlazure) [![NuGet downloads](https://img.shields.io/nuget/dt/TestStack.Dossier.svg)](https://www.nuget.org/packages/TestStack.Dossier) [![NuGet version](https://img.shields.io/nuget/vpre/TestStack.Dossier.svg)](https://www.nuget.org/packages/TestStack.Dossier) +[![Documentation](https://img.shields.io/badge/docs-up%20to%20date-green.svg)](http://dossier.teststack.net/) TestStack.Dossier provides you with the code infrastructure to easily and quickly generate test fixture data for your automated tests in a terse, readable and maintainable way using the Test Data Builder, anonymous value and equivalence class patterns.