diff --git a/TestAssembly/Collections/Branch.cs b/TestAssembly/Collections/Branch.cs new file mode 100644 index 0000000..0530072 --- /dev/null +++ b/TestAssembly/Collections/Branch.cs @@ -0,0 +1,20 @@ +namespace TestAssembly.Collections +{ + using System.Collections; + using System.Collections.Generic; + + public class Branch : IEnumerable + { + readonly List items = new List(); + + public IEnumerator GetEnumerator() + { + return items.GetEnumerator(); + } + + IEnumerator IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + } +} \ No newline at end of file diff --git a/TestAssembly/Collections/Forest.cs b/TestAssembly/Collections/Forest.cs new file mode 100644 index 0000000..cff3c49 --- /dev/null +++ b/TestAssembly/Collections/Forest.cs @@ -0,0 +1,30 @@ +namespace TestAssembly.Collections +{ + using System.Collections; + using System.Collections.Generic; + + public class Forest : ICanAdd, ICanRemove + { + readonly List items = new List(); + + public void Add(Tree item) + { + items.Add(item); + } + + IEnumerator IEnumerable.GetEnumerator() + { + return ((IEnumerable) items).GetEnumerator(); + } + + public IEnumerator GetEnumerator() + { + return items.GetEnumerator(); + } + + public bool Remove(Tree item) + { + return items.Remove(item); + } + } +} \ No newline at end of file diff --git a/TestAssembly/Collections/ICanAdd.cs b/TestAssembly/Collections/ICanAdd.cs new file mode 100644 index 0000000..1115878 --- /dev/null +++ b/TestAssembly/Collections/ICanAdd.cs @@ -0,0 +1,9 @@ +namespace TestAssembly.Collections +{ + using System.Collections.Generic; + + public interface ICanAdd : IEnumerable + { + void Add(T item); + } +} \ No newline at end of file diff --git a/TestAssembly/Collections/ICanRemove.cs b/TestAssembly/Collections/ICanRemove.cs new file mode 100644 index 0000000..23cd643 --- /dev/null +++ b/TestAssembly/Collections/ICanRemove.cs @@ -0,0 +1,9 @@ +namespace TestAssembly.Collections +{ + using System.Collections.Generic; + + public interface ICanRemove : IEnumerable + { + bool Remove(T item); + } +} \ No newline at end of file diff --git a/TestAssembly/Collections/Leaf.cs b/TestAssembly/Collections/Leaf.cs new file mode 100644 index 0000000..42dfd08 --- /dev/null +++ b/TestAssembly/Collections/Leaf.cs @@ -0,0 +1,6 @@ +namespace TestAssembly.Collections +{ + public class Leaf + { + } +} \ No newline at end of file diff --git a/TestAssembly/Collections/Tree.cs b/TestAssembly/Collections/Tree.cs new file mode 100644 index 0000000..e8da998 --- /dev/null +++ b/TestAssembly/Collections/Tree.cs @@ -0,0 +1,31 @@ +namespace TestAssembly.Collections +{ + using System.Collections; + using System.Collections.Generic; + using System.Linq; + + public class Tree : ICanAdd, IEnumerable + { + readonly List items = new List(); + + public void Add(Branch item) + { + items.Add(item); + } + + public IEnumerator GetEnumerator() + { + return items.GetEnumerator(); + } + + IEnumerator IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + + IEnumerator IEnumerable.GetEnumerator() + { + return items.SelectMany(i => i).GetEnumerator(); + } + } +} \ No newline at end of file diff --git a/TestAssembly/TestAssembly.csproj b/TestAssembly/TestAssembly.csproj index 253435e..7be1ca1 100644 --- a/TestAssembly/TestAssembly.csproj +++ b/TestAssembly/TestAssembly.csproj @@ -44,6 +44,12 @@ + + + + + + diff --git a/TestStack.ConventionTests.Tests/ConventionAssertionClassTests.cs b/TestStack.ConventionTests.Tests/ConventionAssertionClassTests.cs index a72203d..8b187f1 100644 --- a/TestStack.ConventionTests.Tests/ConventionAssertionClassTests.cs +++ b/TestStack.ConventionTests.Tests/ConventionAssertionClassTests.cs @@ -33,7 +33,7 @@ public ConventionReportFailure Format(string failingData) public class FailingConvention : IConvention { - public void Execute(FakeData data, IConventionResult result) + public void Execute(FakeData data, IConventionResultContext result) { result.Is("Header", new[] {"Different"}); } diff --git a/TestStack.ConventionTests.Tests/CsvReportTests.Can_run_convention_with_simple_reporter.approved.txt b/TestStack.ConventionTests.Tests/CsvReportTests.Can_run_convention_with_simple_reporter.approved.txt new file mode 100644 index 0000000..07a98d3 --- /dev/null +++ b/TestStack.ConventionTests.Tests/CsvReportTests.Can_run_convention_with_simple_reporter.approved.txt @@ -0,0 +1,5 @@ +collection,item,can add,can remove +TestAssembly.Collections.Branch,TestAssembly.Collections.Leaf,False,False +TestAssembly.Collections.Forest,TestAssembly.Collections.Tree,True,True +TestAssembly.Collections.Tree,TestAssembly.Collections.Branch,True,False +TestAssembly.Collections.Tree,TestAssembly.Collections.Leaf,False,False diff --git a/TestStack.ConventionTests.Tests/CsvReportTests.cs b/TestStack.ConventionTests.Tests/CsvReportTests.cs new file mode 100644 index 0000000..f9d98c3 --- /dev/null +++ b/TestStack.ConventionTests.Tests/CsvReportTests.cs @@ -0,0 +1,24 @@ +namespace TestStack.ConventionTests.Tests +{ + using System.Linq; + using ApprovalTests.Reporters; + using NUnit.Framework; + using TestAssembly.Collections; + using TestStack.ConventionTests.ConventionData; + using TestStack.ConventionTests.Tests.TestConventions; + + [UseReporter(typeof(DiffReporter))] + public class CsvReportTests + { + [Test] + public void Can_run_convention_with_simple_reporter() + { + Convention.IsWithApprovedExeptions(new CollectionsRelationsConvention(), new Types("Entities") + { + TypesToVerify = + typeof (Leaf).Assembly.GetExportedTypes() + .Where(t => t.Namespace == typeof (Leaf).Namespace).ToArray() + }); + } + } +} \ No newline at end of file diff --git a/TestStack.ConventionTests.Tests/TestConventions/CollectionsRelationsConvention.cs b/TestStack.ConventionTests.Tests/TestConventions/CollectionsRelationsConvention.cs new file mode 100644 index 0000000..cf49baf --- /dev/null +++ b/TestStack.ConventionTests.Tests/TestConventions/CollectionsRelationsConvention.cs @@ -0,0 +1,42 @@ +namespace TestStack.ConventionTests.Tests.TestConventions +{ + using System; + using System.Collections.Generic; + using System.Linq; + using TestAssembly.Collections; + using TestStack.ConventionTests.ConventionData; + + public class CollectionsRelationsConvention : IConvention + { + public string ConventionTitle { get; private set; } + + public void Execute(Types data, IConventionResultContext result) + { + ConventionTitle = "well, does the header apply here all across the board? How would that work for CSV?"; + var types = data.TypesToVerify; + var collectionToItemLookup = from collection in types + where collection.IsClass + orderby collection.FullName + from item in GetItemTypes(collection) + select new + { + collection, + item, + can_add = typeof (ICanAdd<>).MakeGenericType(item).IsAssignableFrom(collection), + can_remove = typeof (ICanRemove<>).MakeGenericType(item).IsAssignableFrom(collection) + }; + + result.Is("Some title", collectionToItemLookup); + } + + IEnumerable GetItemTypes(Type type) + { + return from @interface in type.GetInterfaces() + where @interface.IsGenericType + where @interface.GetGenericTypeDefinition() == typeof (IEnumerable<>) + let item = @interface.GetGenericArguments().Single() + orderby item.FullName + select item; + } + } +} \ No newline at end of file diff --git a/TestStack.ConventionTests.Tests/TestStack.ConventionTests.Tests.csproj b/TestStack.ConventionTests.Tests/TestStack.ConventionTests.Tests.csproj index 5736818..43afb54 100644 --- a/TestStack.ConventionTests.Tests/TestStack.ConventionTests.Tests.csproj +++ b/TestStack.ConventionTests.Tests/TestStack.ConventionTests.Tests.csproj @@ -52,6 +52,7 @@ + @@ -59,6 +60,7 @@ True Resources.resx + diff --git a/TestStack.ConventionTests.Tests/TypeBasedConventions.cs b/TestStack.ConventionTests.Tests/TypeBasedConventions.cs index 5f3c2d4..27d0aa5 100644 --- a/TestStack.ConventionTests.Tests/TypeBasedConventions.cs +++ b/TestStack.ConventionTests.Tests/TypeBasedConventions.cs @@ -1,5 +1,6 @@ namespace TestStack.ConventionTests.Tests { + using System.Linq; using ApprovalTests; using ApprovalTests.Reporters; using NUnit.Framework; @@ -16,7 +17,9 @@ public class TypeBasedConventions public TypeBasedConventions() { - var itemsToVerify = typeof (SampleDomainClass).Assembly.GetTypes(); + var itemsToVerify = typeof (SampleDomainClass).Assembly.GetTypes() + .Where(t => t.IsClass && t.Namespace == typeof (SampleDomainClass).Namespace) + .ToArray(); nhibernateEntities = new Types("nHibernate Entitites") { TypesToVerify = itemsToVerify @@ -76,4 +79,4 @@ public void dtos_exists_in_dto_namespace_wth_approved_exceptions() Convention.IsWithApprovedExeptions(convention, types); } } -} \ No newline at end of file +} diff --git a/TestStack.ConventionTests/Convention.cs b/TestStack.ConventionTests/Convention.cs index f4439af..86a85f9 100644 --- a/TestStack.ConventionTests/Convention.cs +++ b/TestStack.ConventionTests/Convention.cs @@ -12,7 +12,7 @@ public static class Convention { static readonly HtmlReportRenderer HtmlRenderer = new HtmlReportRenderer(AssemblyDirectory); - static readonly List Reports = new List(); + static readonly List Reports = new List(); static Convention() { @@ -26,7 +26,7 @@ static Convention() }; } - public static IEnumerable ConventionReports { get { return Reports; } } + public static IEnumerable ConventionReports { get { return Reports; } } public static IList Formatters { get; set; } public static void Is(IConvention convention, TDataSource data) @@ -40,7 +40,8 @@ public static void Is(IConvention convention, TDataSou { try { - var conventionResult = Executor.GetConventionResults(convention, data); + var context = new ConventionContext(data.Description, Formatters); + var conventionResult = context.GetConventionResults(convention, data); Reports.AddRange(conventionResult); new ConventionReportTraceRenderer().Render(conventionResult); @@ -55,7 +56,8 @@ public static void Is(IConvention convention, TDataSou public static void IsWithApprovedExeptions(IConvention convention, TDataSource data) where TDataSource : IConventionData { - var conventionResult = Executor.GetConventionResultsWithApprovedExeptions(convention, data); + var context = new ConventionContext(data.Description, Formatters); + var conventionResult = context.GetConventionResultsWithApprovedExeptions(convention, data); Reports.AddRange(conventionResult); try diff --git a/TestStack.ConventionTests/Conventions/AllClassesHaveDefaultConstructor.cs b/TestStack.ConventionTests/Conventions/AllClassesHaveDefaultConstructor.cs index ed8647f..4de15e4 100644 --- a/TestStack.ConventionTests/Conventions/AllClassesHaveDefaultConstructor.cs +++ b/TestStack.ConventionTests/Conventions/AllClassesHaveDefaultConstructor.cs @@ -6,7 +6,7 @@ public class AllClassesHaveDefaultConstructor : IConvention { - public void Execute(Types data, IConventionResult result) + public void Execute(Types data, IConventionResultContext result) { result.Is("Types must have a default constructor", data.TypesToVerify.Where(t => t.HasDefaultConstructor() == false)); diff --git a/TestStack.ConventionTests/Conventions/AllMethodsAreVirtual.cs b/TestStack.ConventionTests/Conventions/AllMethodsAreVirtual.cs index b6d7d1e..70d7fd9 100644 --- a/TestStack.ConventionTests/Conventions/AllMethodsAreVirtual.cs +++ b/TestStack.ConventionTests/Conventions/AllMethodsAreVirtual.cs @@ -6,7 +6,7 @@ public class AllMethodsAreVirtual : IConvention { - public void Execute(Types data, IConventionResult result) + public void Execute(Types data, IConventionResultContext result) { result.Is("Methods must be virtual", data.TypesToVerify.SelectMany(t => t.NonVirtualMethods())); } diff --git a/TestStack.ConventionTests/Conventions/ClassTypeHasSpecificNamespace.cs b/TestStack.ConventionTests/Conventions/ClassTypeHasSpecificNamespace.cs index 25da3af..104c013 100644 --- a/TestStack.ConventionTests/Conventions/ClassTypeHasSpecificNamespace.cs +++ b/TestStack.ConventionTests/Conventions/ClassTypeHasSpecificNamespace.cs @@ -31,7 +31,7 @@ public ClassTypeHasSpecificNamespace(Func classIsApplicable, string this.classType = classType; } - public void Execute(Types data, IConventionResult result) + public void Execute(Types data, IConventionResultContext result) { result.IsSymmetric( string.Format("{0}s must be under the '{1}' namespace", classType, namespaceToCheck), diff --git a/TestStack.ConventionTests/Conventions/FilesAreEmbeddedResources.cs b/TestStack.ConventionTests/Conventions/FilesAreEmbeddedResources.cs index 53f83af..3d6becf 100644 --- a/TestStack.ConventionTests/Conventions/FilesAreEmbeddedResources.cs +++ b/TestStack.ConventionTests/Conventions/FilesAreEmbeddedResources.cs @@ -12,7 +12,7 @@ public FilesAreEmbeddedResources(string fileExtension) public string FileExtension { get; private set; } - public void Execute(ProjectFiles data, IConventionResult result) + public void Execute(ProjectFiles data, IConventionResultContext result) { result.Is( string.Format("{0} Files must be embedded resources", FileExtension), diff --git a/TestStack.ConventionTests/Conventions/ProjectDoesNotReferenceDllsFromBinOrObjDirectories.cs b/TestStack.ConventionTests/Conventions/ProjectDoesNotReferenceDllsFromBinOrObjDirectories.cs index 29eab34..5247982 100644 --- a/TestStack.ConventionTests/Conventions/ProjectDoesNotReferenceDllsFromBinOrObjDirectories.cs +++ b/TestStack.ConventionTests/Conventions/ProjectDoesNotReferenceDllsFromBinOrObjDirectories.cs @@ -8,7 +8,7 @@ public class ProjectDoesNotReferenceDllsFromBinOrObjDirectories : IConvention.*?(obj|bin).*?)$"; - public void Execute(ProjectReferences data, IConventionResult result) + public void Execute(ProjectReferences data, IConventionResultContext result) { result.Is("Project must not reference dlls from bin or obj directories", data.References.Where(IsBinOrObjReference)); diff --git a/TestStack.ConventionTests/IConvention.cs b/TestStack.ConventionTests/IConvention.cs index 641dc53..2c7621e 100644 --- a/TestStack.ConventionTests/IConvention.cs +++ b/TestStack.ConventionTests/IConvention.cs @@ -2,6 +2,6 @@ { public interface IConvention where T : IConventionData { - void Execute(T data, IConventionResult result); + void Execute(T data, IConventionResultContext result); } } \ No newline at end of file diff --git a/TestStack.ConventionTests/IConventionResult.cs b/TestStack.ConventionTests/IConventionResultContext.cs similarity index 74% rename from TestStack.ConventionTests/IConventionResult.cs rename to TestStack.ConventionTests/IConventionResultContext.cs index 9442528..c40023e 100644 --- a/TestStack.ConventionTests/IConventionResult.cs +++ b/TestStack.ConventionTests/IConventionResultContext.cs @@ -3,7 +3,7 @@ using System; using System.Collections.Generic; - public interface IConventionResult + public interface IConventionResultContext { void Is(string resultTitle, IEnumerable failingData); @@ -14,13 +14,13 @@ public interface IConventionResult /// and if a non-dto is in Project.Dto the test will also fail /// /// The data type the convention is applied to - /// Title of the convention, i.e Dto's must live in Project.Dto namespace - /// Data failing to conform to the convention - /// The inverse scenario title, i.e Non-dtos must not live inside Project.Dto namespace - /// Data failing to conform to the inverse of the convention + /// Title of the convention, i.e Dto's must live in Project.Dto namespace + /// Data failing to conform to the convention + /// The inverse scenario title, i.e Non-dtos must not live inside Project.Dto namespace + /// Data failing to conform to the inverse of the convention void IsSymmetric( - string conventionResultTitle, IEnumerable conventionFailingData, - string inverseResultTitle, IEnumerable inverseFailingData); + string firstSetFailureTitle, IEnumerable firstSetFailureData, + string secondSetFailureTitle, IEnumerable secondSetFailureData); /// /// A symmetric convention is a convention which also can be applied in reverse. For example diff --git a/TestStack.ConventionTests/Internal/ConventionContext.cs b/TestStack.ConventionTests/Internal/ConventionContext.cs new file mode 100644 index 0000000..028daec --- /dev/null +++ b/TestStack.ConventionTests/Internal/ConventionContext.cs @@ -0,0 +1,111 @@ +namespace TestStack.ConventionTests.Internal +{ + using System; + using System.Collections.Generic; + using System.Linq; + using TestStack.ConventionTests.Conventions; + using TestStack.ConventionTests.Reporting; + + public class ConventionContext : IConventionResultContext + { + readonly string dataDescription; + readonly IList formatters; + readonly IList results = new List(); + + public ConventionContext(string dataDescription, IList formatters) + { + this.formatters = formatters; + this.dataDescription = dataDescription; + } + + public ConventionResult[] ConventionResults + { + get { return results.ToArray(); } + } + + void IConventionResultContext.Is(string resultTitle, IEnumerable failingData) + { + // ReSharper disable PossibleMultipleEnumeration + results.Add(new ConventionResult( + failingData.None() ? TestResult.Passed : TestResult.Failed, + resultTitle, + dataDescription, + failingData.Select(FormatData).ToArray())); + } + + void IConventionResultContext.IsSymmetric( + string firstSetFailureTitle, IEnumerable firstSetFailureData, + string secondSetFailureTitle, IEnumerable secondSetFailureData) + { + results.Add(new ConventionResult( + firstSetFailureData.None() ? TestResult.Passed : TestResult.Failed, + firstSetFailureTitle, + dataDescription, + firstSetFailureData.Select(FormatData).ToArray())); + results.Add(new ConventionResult( + secondSetFailureData.None() ? TestResult.Passed : TestResult.Failed, + secondSetFailureTitle, + dataDescription, + secondSetFailureData.Select(FormatData).ToArray())); + } + + void IConventionResultContext.IsSymmetric( + string firstSetFailureTitle, + string secondSetFailureTitle, + Func isPartOfFirstSet, + Func isPartOfSecondSet, + IEnumerable allData) + { + var firstSetFailingData = allData.Where(isPartOfFirstSet).Unless(isPartOfSecondSet); + var secondSetFailingData = allData.Where(isPartOfSecondSet).Unless(isPartOfFirstSet); + + (this as IConventionResultContext).IsSymmetric( + firstSetFailureTitle, firstSetFailingData, + secondSetFailureTitle, secondSetFailingData); + } + + ConventionReportFailure FormatData(T failingData) + { + var formatter = formatters.FirstOrDefault(f => f.CanFormat(failingData)); + if (formatter == null) + { + throw new NoDataFormatterFoundException( + typeof (T).Name + + " has no formatter, add one with `Convention.Formatters.Add(new MyDataFormatter());`"); + } + + return formatter.Format(failingData); + } + + public ConventionResult[] GetConventionResults(IConvention convention, + TDataSource data) + where TDataSource : IConventionData + { + if (!data.HasData) + throw new ConventionSourceInvalidException(String.Format("{0} has no data", data.Description)); + + convention.Execute(data, this); + + return ConventionResults; + } + + public ConventionResult[] GetConventionResultsWithApprovedExeptions( + IConvention convention, TDataSource data) + where TDataSource : IConventionData + { + var conventionReportTextRenderer = new ConventionReportTextRenderer(); + // Add approved exceptions to report + if (!data.HasData) + throw new ConventionSourceInvalidException(String.Format("{0} has no data", data.Description)); + + convention.Execute(data, this); + foreach (var conventionResult in ConventionResults) + { + conventionReportTextRenderer.RenderItems(conventionResult); + conventionResult.WithApprovedException(conventionReportTextRenderer.Output); + } + + return ConventionResults; + } + } +} \ No newline at end of file diff --git a/TestStack.ConventionTests/Internal/ConventionResult.cs b/TestStack.ConventionTests/Internal/ConventionResult.cs index 53d1112..a9fc654 100644 --- a/TestStack.ConventionTests/Internal/ConventionResult.cs +++ b/TestStack.ConventionTests/Internal/ConventionResult.cs @@ -1,79 +1,28 @@ -namespace TestStack.ConventionTests.Internal -{ - using System; - using System.Collections.Generic; - using System.Linq; - using TestStack.ConventionTests.Reporting; - - public class ConventionResult : IConventionResult - { - readonly List conventionResults; - readonly string dataDescription; - - public ConventionResult(string dataDescription) - { - this.dataDescription = dataDescription; - conventionResults = new List(); - } - - public ResultInfo[] ConventionResults - { - get { return conventionResults.ToArray(); } - } - - public void Is(string resultTitle, IEnumerable failingData) - { - // ReSharper disable PossibleMultipleEnumeration - conventionResults.Add(new ResultInfo( - failingData.None() ? TestResult.Passed : TestResult.Failed, - resultTitle, - dataDescription, - failingData.Select(FormatData).ToArray())); - } - - public void IsSymmetric( - string conventionResultTitle, IEnumerable conventionFailingData, - string inverseResultTitle, IEnumerable inverseFailingData) - { - conventionResults.Add(new ResultInfo( - conventionFailingData.None() ? TestResult.Passed : TestResult.Failed, - conventionResultTitle, - dataDescription, - conventionFailingData.Select(FormatData).ToArray())); - conventionResults.Add(new ResultInfo( - inverseFailingData.None() ? TestResult.Passed : TestResult.Failed, - inverseResultTitle, - dataDescription, - inverseFailingData.Select(FormatData).ToArray())); - } - - public void IsSymmetric( - string firstSetFailureTitle, - string secondSetFailureTitle, - Func isPartOfFirstSet, - Func isPartOfSecondSet, - IEnumerable allData) - { - var firstSetFailingData = allData.Where(isPartOfFirstSet).Where(d => !isPartOfSecondSet(d)); - var secondSetFailingData = allData.Where(d => !isPartOfFirstSet(d)).Where(isPartOfSecondSet); - - IsSymmetric( - firstSetFailureTitle, firstSetFailingData, - secondSetFailureTitle, secondSetFailingData); - } - - static ConventionReportFailure FormatData(T failingData) - { - var formatter = Convention.Formatters.FirstOrDefault(f => f.CanFormat(failingData)); - - if (formatter == null) - { - throw new NoDataFormatterFoundException( - typeof (T).Name + - " has no formatter, add one with `Convention.Formatters.Add(new MyDataFormatter());`"); - } - - return formatter.Format(failingData); - } - } +namespace TestStack.ConventionTests.Internal +{ + using TestStack.ConventionTests.Reporting; + + public class ConventionResult + { + public TestResult Result { get; private set; } + public string ConventionTitle { get; private set; } + public string DataDescription { get; private set; } + public ConventionReportFailure[] ConventionFailures { get; private set; } + public string ApprovedException { get; private set; } + + public ConventionResult(TestResult result, string conventionTitle, string dataDescription, ConventionReportFailure[] conventionFailures) + { + Result = result; + ConventionTitle = conventionTitle; + DataDescription = dataDescription; + ConventionFailures = conventionFailures; + } + + public void WithApprovedException(string output) + { + ApprovedException = output; + Result = TestResult.Passed; + ConventionFailures = new ConventionReportFailure[0]; + } + } } \ No newline at end of file diff --git a/TestStack.ConventionTests/Internal/Executor.cs b/TestStack.ConventionTests/Internal/Executor.cs deleted file mode 100644 index a39c3cf..0000000 --- a/TestStack.ConventionTests/Internal/Executor.cs +++ /dev/null @@ -1,41 +0,0 @@ -namespace TestStack.ConventionTests.Internal -{ - using System; - using TestStack.ConventionTests.Conventions; - using TestStack.ConventionTests.Reporting; - - public static class Executor - { - public static ResultInfo[] GetConventionResults(IConvention convention, TDataSource data) - where TDataSource : IConventionData - { - if (!data.HasData) - throw new ConventionSourceInvalidException(string.Format("{0} has no data", data.Description)); - - var resultGatherer = new ConventionResult(data.Description); - convention.Execute(data, resultGatherer); - - return resultGatherer.ConventionResults; - } - - public static ResultInfo[] GetConventionResultsWithApprovedExeptions( - IConvention convention, TDataSource data) - where TDataSource : IConventionData - { - var conventionReportTextRenderer = new ConventionReportTextRenderer(); - // Add approved exceptions to report - if (!data.HasData) - throw new ConventionSourceInvalidException(string.Format("{0} has no data", data.Description)); - - var resultGatherer = new ConventionResult(data.Description); - convention.Execute(data, resultGatherer); - foreach (var conventionResult in resultGatherer.ConventionResults) - { - conventionReportTextRenderer.RenderItems(conventionResult); - conventionResult.WithApprovedException(conventionReportTextRenderer.Output); - } - - return resultGatherer.ConventionResults; - } - } -} \ No newline at end of file diff --git a/TestStack.ConventionTests/Internal/LinqExtensions.cs b/TestStack.ConventionTests/Internal/LinqExtensions.cs index 920e4e5..b2f7ee6 100644 --- a/TestStack.ConventionTests/Internal/LinqExtensions.cs +++ b/TestStack.ConventionTests/Internal/LinqExtensions.cs @@ -1,6 +1,4 @@ -// ReSharper disable once CheckNamespace - -namespace TestStack.ConventionTests.Internal +namespace TestStack.ConventionTests.Internal { using System; using System.Collections.Generic; @@ -17,5 +15,11 @@ public static bool None(this IEnumerable enumerable, Func predica { return !enumerable.Any(predicate); } + + + public static IEnumerable Unless(this IEnumerable enumerable, Func predicate) + { + return enumerable.Where(i => predicate(i) == false); + } } } \ No newline at end of file diff --git a/TestStack.ConventionTests/Internal/ResultInfo.cs b/TestStack.ConventionTests/Internal/ResultInfo.cs deleted file mode 100644 index 3b2828b..0000000 --- a/TestStack.ConventionTests/Internal/ResultInfo.cs +++ /dev/null @@ -1,28 +0,0 @@ -namespace TestStack.ConventionTests.Internal -{ - using TestStack.ConventionTests.Reporting; - - public class ResultInfo - { - public TestResult Result { get; private set; } - public string ConventionTitle { get; private set; } - public string DataDescription { get; private set; } - public ConventionReportFailure[] ConventionFailures { get; private set; } - public string ApprovedException { get; private set; } - - public ResultInfo(TestResult result, string conventionTitle, string dataDescription, ConventionReportFailure[] conventionFailures) - { - Result = result; - ConventionTitle = conventionTitle; - DataDescription = dataDescription; - ConventionFailures = conventionFailures; - } - - public void WithApprovedException(string output) - { - ApprovedException = output; - Result = TestResult.Passed; - ConventionFailures = new ConventionReportFailure[0]; - } - } -} \ No newline at end of file diff --git a/TestStack.ConventionTests/Reporting/ConventionReportTextRenderer.cs b/TestStack.ConventionTests/Reporting/ConventionReportTextRenderer.cs index 3fda3d0..dc7f72e 100644 --- a/TestStack.ConventionTests/Reporting/ConventionReportTextRenderer.cs +++ b/TestStack.ConventionTests/Reporting/ConventionReportTextRenderer.cs @@ -5,7 +5,7 @@ public class ConventionReportTextRenderer : IConventionReportRenderer { - public void Render(params ResultInfo[] conventionResult) + public void Render(params ConventionResult[] conventionResult) { var stringBuilder = new StringBuilder(); @@ -34,14 +34,14 @@ public void Render(params ResultInfo[] conventionResult) public string Output { get; private set; } - public void RenderItems(ResultInfo conventionResult) + public void RenderItems(ConventionResult conventionResult) { var stringBuilder = new StringBuilder(); RenderItems(conventionResult, stringBuilder); Output = stringBuilder.ToString(); } - static void RenderItems(ResultInfo resultInfo, StringBuilder stringBuilder) + static void RenderItems(ConventionResult resultInfo, StringBuilder stringBuilder) { foreach (var conventionFailure in resultInfo.ConventionFailures) { diff --git a/TestStack.ConventionTests/Reporting/ConventionReportTraceRenderer.cs b/TestStack.ConventionTests/Reporting/ConventionReportTraceRenderer.cs index 7c4d68d..d283562 100644 --- a/TestStack.ConventionTests/Reporting/ConventionReportTraceRenderer.cs +++ b/TestStack.ConventionTests/Reporting/ConventionReportTraceRenderer.cs @@ -5,7 +5,7 @@ public class ConventionReportTraceRenderer : IConventionReportRenderer { - public void Render(params ResultInfo[] conventionResult) + public void Render(params ConventionResult[] conventionResult) { var conventionReportTextRenderer = new ConventionReportTextRenderer(); conventionReportTextRenderer.Render(conventionResult); diff --git a/TestStack.ConventionTests/Reporting/ConventionResultExceptionReporter.cs b/TestStack.ConventionTests/Reporting/ConventionResultExceptionReporter.cs index c4cc903..e2d788b 100644 --- a/TestStack.ConventionTests/Reporting/ConventionResultExceptionReporter.cs +++ b/TestStack.ConventionTests/Reporting/ConventionResultExceptionReporter.cs @@ -5,7 +5,7 @@ public class ConventionResultExceptionReporter : IConventionReportRenderer { - public void Render(params ResultInfo[] conventionResult) + public void Render(params ConventionResult[] conventionResult) { var conventionReportTextRenderer = new ConventionReportTextRenderer(); conventionReportTextRenderer.Render(conventionResult); diff --git a/TestStack.ConventionTests/Reporting/CsvReporter.cs b/TestStack.ConventionTests/Reporting/CsvReporter.cs new file mode 100644 index 0000000..a8f57d7 --- /dev/null +++ b/TestStack.ConventionTests/Reporting/CsvReporter.cs @@ -0,0 +1,19 @@ +namespace TestStack.ConventionTests.Reporting +{ + using System.Collections; + using System.Text; + + public class CsvReporter + { + public string Build(IEnumerable results, string header, DefaultFormatter formatter) + { + var message = new StringBuilder(); + message.AppendLine(string.Join(",", formatter.DesribeType())); + foreach (var result in results) + { + message.AppendLine(string.Join(",", formatter.DesribeItem(result))); + } + return message.ToString(); + } + } +} \ No newline at end of file diff --git a/TestStack.ConventionTests/Reporting/DefaultFormatter.cs b/TestStack.ConventionTests/Reporting/DefaultFormatter.cs new file mode 100644 index 0000000..eaf7fb7 --- /dev/null +++ b/TestStack.ConventionTests/Reporting/DefaultFormatter.cs @@ -0,0 +1,34 @@ +namespace TestStack.ConventionTests.Reporting +{ + using System; + using System.Linq; + using System.Reflection; + + public class DefaultFormatter + { + readonly PropertyInfo[] properties; + readonly Type type; + + public DefaultFormatter(Type type) + { + this.type = type; + properties = type.GetProperties(); + } + + // TODO: this is a very crappy name for a method + public string[] DesribeType() + { + return properties.Select(Describe).ToArray(); + } + + string Describe(PropertyInfo property) + { + return property.Name.Replace('_', ' '); + } + + public string[] DesribeItem(object result) + { + return properties.Select(p => p.GetValue(result, null).ToString()).ToArray(); + } + } +} \ No newline at end of file diff --git a/TestStack.ConventionTests/Reporting/HtmlReportRenderer.cs b/TestStack.ConventionTests/Reporting/HtmlReportRenderer.cs index 2f646b3..79ae3b9 100644 --- a/TestStack.ConventionTests/Reporting/HtmlReportRenderer.cs +++ b/TestStack.ConventionTests/Reporting/HtmlReportRenderer.cs @@ -14,7 +14,7 @@ public HtmlReportRenderer(string assemblyDirectory) file = Path.Combine(assemblyDirectory, "Conventions.htm"); } - public void Render(params ResultInfo[] conventionResult) + public void Render(params ConventionResult[] conventionResult) { var sb = new StringBuilder(); var html = new HtmlTextWriter(new StringWriter(sb)); diff --git a/TestStack.ConventionTests/Reporting/IConventionReportRenderer.cs b/TestStack.ConventionTests/Reporting/IConventionReportRenderer.cs index 15ee9fc..c472036 100644 --- a/TestStack.ConventionTests/Reporting/IConventionReportRenderer.cs +++ b/TestStack.ConventionTests/Reporting/IConventionReportRenderer.cs @@ -4,6 +4,6 @@ public interface IConventionReportRenderer { - void Render(params ResultInfo[] conventionResult); + void Render(params ConventionResult[] conventionResult); } } \ No newline at end of file diff --git a/TestStack.ConventionTests/TestStack.ConventionTests.csproj b/TestStack.ConventionTests/TestStack.ConventionTests.csproj index 3e8b083..dae9795 100644 --- a/TestStack.ConventionTests/TestStack.ConventionTests.csproj +++ b/TestStack.ConventionTests/TestStack.ConventionTests.csproj @@ -61,12 +61,13 @@ - + + - - + +