Skip to content

Commit b782207

Browse files
author
Jake Ginnivan
committed
Allowed reporters to be specified by using the ConventionReporterAttribute in the assembly info.
1 parent 8093735 commit b782207

10 files changed

+133
-88
lines changed

TestStack.ConventionTests.Tests/Properties/AssemblyInfo.cs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
using System.Reflection;
22
using System.Runtime.InteropServices;
3-
43
// General Information about an assembly is controlled through the following
54
// set of attributes. Change these attribute values to modify the information
65
// associated with an assembly.
6+
using TestStack.ConventionTests;
7+
using TestStack.ConventionTests.Reporting;
8+
79
[assembly: AssemblyTitle("TestStack.ConventionTests.Tests")]
810
[assembly: AssemblyDescription("")]
911
[assembly: AssemblyConfiguration("")]
@@ -33,3 +35,6 @@
3335
// [assembly: AssemblyVersion("1.0.*")]
3436
[assembly: AssemblyVersion("1.0.0.0")]
3537
[assembly: AssemblyFileVersion("1.0.0.0")]
38+
39+
[assembly: ConventionReporter(typeof(HtmlConventionResultsReporter))]
40+
[assembly: ConventionReporter(typeof(MarkdownConventionResultsReporter))]

TestStack.ConventionTests/Convention.cs

Lines changed: 30 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,15 @@
22
{
33
using System;
44
using System.Collections.Generic;
5-
using System.IO;
65
using System.Reflection;
76
using System.Text.RegularExpressions;
87
using TestStack.ConventionTests.Internal;
98
using TestStack.ConventionTests.Reporting;
109

1110
public static class Convention
1211
{
13-
static readonly HtmlReportRenderer HtmlRenderer = new HtmlReportRenderer(AssemblyDirectory);
12+
static IResultsProcessor[] defaultProcessors;
13+
static IResultsProcessor[] defaultApprovalProcessors;
1414

1515
static Convention()
1616
{
@@ -28,42 +28,22 @@ static Convention()
2828

2929
public static IList<IReportDataFormatter> Formatters { get; set; }
3030

31-
static string AssemblyDirectory
32-
{
33-
get
34-
{
35-
// http://stackoverflow.com/questions/52797/c-how-do-i-get-the-path-of-the-assembly-the-code-is-in#answer-283917
36-
var codeBase = Assembly.GetExecutingAssembly().CodeBase;
37-
var uri = new UriBuilder(codeBase);
38-
var path = Uri.UnescapeDataString(uri.Path);
39-
return Path.GetDirectoryName(path);
40-
}
41-
}
42-
4331
public static void Is<TDataSource>(IConvention<TDataSource> convention, TDataSource data,
4432
ITestResultProcessor resultProcessor = null)
4533
where TDataSource : IConventionData
4634
{
47-
var processors = new List<IResultsProcessor>
48-
{
49-
HtmlRenderer,
50-
new ConventionReportTraceRenderer(),
51-
new ThrowOnFailureResultsProcessor()
52-
};
53-
Execute(convention, data, processors.ToArray(), resultProcessor ?? new ConventionReportTextRenderer());
35+
if (defaultProcessors == null || defaultApprovalProcessors == null)
36+
Init(Assembly.GetCallingAssembly());
37+
Execute(convention, data, defaultProcessors, resultProcessor ?? new ConventionReportTextRenderer());
5438
}
5539

5640
public static void IsWithApprovedExeptions<TDataSource>(IConvention<TDataSource> convention, TDataSource data,
5741
ITestResultProcessor resultProcessor = null)
5842
where TDataSource : IConventionData
5943
{
60-
var processors = new List<IResultsProcessor>
61-
{
62-
HtmlRenderer,
63-
new ConventionReportTraceRenderer(),
64-
new ApproveResultsProcessor()
65-
};
66-
Execute(convention, data, processors.ToArray(), resultProcessor ?? new ConventionReportTextRenderer());
44+
if (defaultProcessors == null || defaultApprovalProcessors == null)
45+
Init(Assembly.GetCallingAssembly());
46+
Execute(convention, data, defaultApprovalProcessors, resultProcessor ?? new ConventionReportTextRenderer());
6747
}
6848

6949
static void Execute<TDataSource>(IConvention<TDataSource> convention, TDataSource data,
@@ -75,6 +55,28 @@ static void Execute<TDataSource>(IConvention<TDataSource> convention, TDataSourc
7555
context.Execute(convention, data);
7656
}
7757

58+
static void Init(Assembly assembly)
59+
{
60+
var customReporters = assembly.GetCustomAttributes(typeof(ConventionReporterAttribute), false);
61+
62+
defaultProcessors = new IResultsProcessor[customReporters.Length + 2];
63+
defaultApprovalProcessors = new IResultsProcessor[customReporters.Length + 2];
64+
65+
for (var index = 0; index < customReporters.Length; index++)
66+
{
67+
var customReporter = (ConventionReporterAttribute)customReporters[index];
68+
var resultsProcessor = (IResultsProcessor)Activator.CreateInstance(customReporter.ReporterType);
69+
defaultProcessors[index] = resultsProcessor;
70+
defaultApprovalProcessors[index] = resultsProcessor;
71+
}
72+
73+
var conventionReportTraceRenderer = new ConventionReportTraceRenderer();
74+
defaultProcessors[defaultProcessors.Length - 2] = conventionReportTraceRenderer;
75+
defaultApprovalProcessors[defaultProcessors.Length - 2] = conventionReportTraceRenderer;
76+
defaultProcessors[defaultProcessors.Length - 1] = new ThrowOnFailureResultsProcessor();
77+
defaultApprovalProcessors[defaultProcessors.Length - 1] = new ApproveResultsProcessor();
78+
}
79+
7880
static string ToSentenceCase(string str)
7981
{
8082
return Regex.Replace(str, "[a-z][A-Z]", m => m.Value[0] + " " + char.ToLower(m.Value[1]));
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
namespace TestStack.ConventionTests
2+
{
3+
using System;
4+
using TestStack.ConventionTests.Reporting;
5+
6+
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
7+
public class ConventionReporterAttribute : Attribute
8+
{
9+
public ConventionReporterAttribute(Type reporterType)
10+
{
11+
ReporterType = reporterType;
12+
if (!typeof(IResultsProcessor).IsAssignableFrom(reporterType))
13+
throw new ArgumentException("Reporters must inherit from IResultsProcessor", "reporterType");
14+
}
15+
16+
public Type ReporterType { get; private set; }
17+
}
18+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
namespace TestStack.ConventionTests.Reporting
2+
{
3+
using System;
4+
using System.Collections.Generic;
5+
using System.IO;
6+
using System.Linq;
7+
using System.Reflection;
8+
using TestStack.ConventionTests.Internal;
9+
10+
/// <summary>
11+
/// Aggregates all previous results
12+
/// </summary>
13+
public abstract class AggregatedConventionResultsReporter : IResultsProcessor
14+
{
15+
static readonly List<ConventionResult> Reports = new List<ConventionResult>();
16+
readonly string output;
17+
18+
protected AggregatedConventionResultsReporter(string outputFilename)
19+
{
20+
output = Path.Combine(AssemblyDirectory, outputFilename);
21+
}
22+
23+
static string AssemblyDirectory
24+
{
25+
get
26+
{
27+
// http://stackoverflow.com/questions/52797/c-how-do-i-get-the-path-of-the-assembly-the-code-is-in#answer-283917
28+
var codeBase = Assembly.GetExecutingAssembly().CodeBase;
29+
var uri = new UriBuilder(codeBase);
30+
var path = Uri.UnescapeDataString(uri.Path);
31+
return Path.GetDirectoryName(path);
32+
}
33+
}
34+
35+
public IEnumerable<ConventionResult> AggregatedReports { get { return Reports; } }
36+
37+
public void Process(IConventionFormatContext context, params ConventionResult[] results)
38+
{
39+
Reports.AddRange(results.Except(Reports));
40+
var outputContent = Process(context);
41+
File.WriteAllText(output, outputContent);
42+
}
43+
44+
protected abstract string Process(IConventionFormatContext context);
45+
}
46+
}

TestStack.ConventionTests/Reporting/AggregatedRenderer.cs

Lines changed: 0 additions & 23 deletions
This file was deleted.
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
namespace TestStack.ConventionTests.Reporting
2+
{
3+
using System.Collections.Generic;
4+
using System.Linq;
5+
using TestStack.ConventionTests.Internal;
6+
7+
public abstract class GroupedByDataTypeConventionResultsReporterBase : AggregatedConventionResultsReporter
8+
{
9+
protected GroupedByDataTypeConventionResultsReporterBase(string outputFilename) : base(outputFilename)
10+
{
11+
}
12+
13+
protected override string Process(IConventionFormatContext context)
14+
{
15+
return Process(context, AggregatedReports.OrderBy(c => c.ConventionTitle).GroupBy(r => r.DataDescription));
16+
}
17+
18+
protected abstract string Process(IConventionFormatContext context, IEnumerable<IGrouping<string, ConventionResult>> resultsGroupedByDataType);
19+
}
20+
}

TestStack.ConventionTests/Reporting/GroupedByDataTypeRendererBase.cs

Lines changed: 0 additions & 16 deletions
This file was deleted.

TestStack.ConventionTests/Reporting/HtmlReportRenderer.cs renamed to TestStack.ConventionTests/Reporting/HtmlConventionResultsReporter.cs

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,13 @@
77
using System.Web.UI;
88
using TestStack.ConventionTests.Internal;
99

10-
public class HtmlReportRenderer : GroupedByDataTypeRendererBase
10+
public class HtmlConventionResultsReporter : GroupedByDataTypeConventionResultsReporterBase
1111
{
12-
readonly string file;
13-
14-
public HtmlReportRenderer(string assemblyDirectory)
12+
public HtmlConventionResultsReporter() : base("Conventions.htm")
1513
{
16-
file = Path.Combine(assemblyDirectory, "Conventions.htm");
1714
}
1815

19-
protected override void Process(IConventionFormatContext context, IEnumerable<IGrouping<string, ConventionResult>> resultsGroupedByDataType)
16+
protected override string Process(IConventionFormatContext context, IEnumerable<IGrouping<string, ConventionResult>> resultsGroupedByDataType)
2017
{
2118
var sb = new StringBuilder();
2219
var html = new HtmlTextWriter(new StringWriter(sb));
@@ -100,8 +97,7 @@ protected override void Process(IConventionFormatContext context, IEnumerable<IG
10097
html.RenderEndTag(); // </body>
10198
html.RenderEndTag(); // </html>
10299
html.Flush();
103-
104-
File.WriteAllText(file, sb.ToString());
100+
return sb.ToString();
105101
}
106102
}
107103
}
Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,17 @@
11
namespace TestStack.ConventionTests.Reporting
22
{
33
using System.Collections.Generic;
4-
using System.IO;
54
using System.Linq;
65
using System.Text;
76
using TestStack.ConventionTests.Internal;
87

9-
public class MarkdownReportRenderer : GroupedByDataTypeRendererBase
8+
public class MarkdownConventionResultsReporter : GroupedByDataTypeConventionResultsReporterBase
109
{
11-
readonly string file;
12-
13-
public MarkdownReportRenderer(string assemblyDirectory)
10+
public MarkdownConventionResultsReporter() : base("Conventions.md")
1411
{
15-
file = Path.Combine(assemblyDirectory, "Conventions.md");
1612
}
1713

18-
protected override void Process(IConventionFormatContext context, IEnumerable<IGrouping<string, ConventionResult>> resultsGroupedByDataType)
14+
protected override string Process(IConventionFormatContext context, IEnumerable<IGrouping<string, ConventionResult>> resultsGroupedByDataType)
1915
{
2016
var sb = new StringBuilder();
2117
sb.AppendLine("# Project Conventions");
@@ -31,7 +27,7 @@ protected override void Process(IConventionFormatContext context, IEnumerable<IG
3127
}
3228
}
3329

34-
File.WriteAllText(file, sb.ToString());
30+
return sb.ToString();
3531
}
3632
}
3733
}

TestStack.ConventionTests/TestStack.ConventionTests.csproj

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@
6161
<Compile Include="ConventionData\TypeExtensions.cs" />
6262
<Compile Include="ConventionFailedException.cs" />
6363
<Compile Include="Conventions\ViewModelShouldInheritFromINotifyPropertyChanged.cs" />
64+
<Compile Include="ConventionReporterAttribute.cs" />
6465
<Compile Include="IConventionResultContext.cs" />
6566
<Compile Include="Conventions\ApiControllerNamingAndBaseClassConvention.cs" />
6667
<Compile Include="Conventions\MvcControllerNameAndBaseClassConvention.cs" />
@@ -69,18 +70,18 @@
6970
<Compile Include="Internal\ConventionTestsApprovalTextWriter.cs" />
7071
<Compile Include="Internal\IConventionFormatContext.cs" />
7172
<Compile Include="Internal\NoDataFormatterFoundException.cs" />
72-
<Compile Include="Reporting\AggregatedRenderer.cs" />
73+
<Compile Include="Reporting\AggregatedConventionResultsReporter.cs" />
7374
<Compile Include="Reporting\ApproveResultsProcessor.cs" />
7475
<Compile Include="Reporting\ConvertibleFormatter.cs" />
7576
<Compile Include="Reporting\CsvReporter.cs" />
7677
<Compile Include="Reporting\DefaultFormatter.cs" />
7778
<Compile Include="Reporting\FallbackFormatter.cs" />
78-
<Compile Include="Reporting\GroupedByDataTypeRendererBase.cs" />
79-
<Compile Include="Reporting\HtmlReportRenderer.cs" />
79+
<Compile Include="Reporting\GroupedByDataTypeConventionResultsReporterBase.cs" />
80+
<Compile Include="Reporting\HtmlConventionResultsReporter.cs" />
8081
<Compile Include="Reporting\ConventionReportTextRenderer.cs" />
8182
<Compile Include="Reporting\ConventionReportTraceRenderer.cs" />
8283
<Compile Include="Reporting\ITestResultProcessor.cs" />
83-
<Compile Include="Reporting\MarkdownReportRenderer.cs" />
84+
<Compile Include="Reporting\MarkdownConventionResultsReporter.cs" />
8485
<Compile Include="Reporting\ThrowOnFailureResultsProcessor.cs" />
8586
<Compile Include="Conventions\ClassTypeHasSpecificNamespace.cs" />
8687
<Compile Include="Conventions\ConventionSourceInvalidException.cs" />

0 commit comments

Comments
 (0)