Skip to content

Commit cc96d70

Browse files
committed
raising level of abstraction in .csproj based conventions
1 parent 6ec0390 commit cc96d70

File tree

10 files changed

+155
-60
lines changed

10 files changed

+155
-60
lines changed

TestStack.ConventionTests.Tests/ProjectBasedConventions.cs

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,12 @@
1313
[UseReporter(typeof(DiffReporter))]
1414
public class ProjectBasedConventions
1515
{
16-
Project project;
1716
IProjectProvider projectProvider;
1817

1918
[SetUp]
2019
public void Setup()
2120
{
2221
projectProvider = Substitute.For<IProjectProvider>();
23-
var projectLocator = Substitute.For<IProjectLocator>();
24-
project = new Project(typeof(ProjectBasedConventions).Assembly, projectProvider, projectLocator);
2522
}
2623

2724
[Test]
@@ -31,6 +28,8 @@ public void assemblies_referencing_bin_obj()
3128
.LoadProjectDocument(Arg.Any<string>())
3229
.Returns(XDocument.Parse(Resources.ProjectFileWithBinReference));
3330

31+
var projectLocator = Substitute.For<IProjectLocator>();
32+
var project = new ProjectReferences(typeof(ProjectBasedConventions).Assembly, projectProvider, projectLocator);
3433
var ex = Assert.Throws<ConventionFailedException>(() => Convention.Is(new ProjectDoesNotReferenceDllsFromBinOrObjDirectories(), project));
3534

3635
Approvals.Verify(ex.Message);
@@ -43,17 +42,24 @@ public void assemblies_referencing_bin_obj_with_approved_exceptions()
4342
.LoadProjectDocument(Arg.Any<string>())
4443
.Returns(XDocument.Parse(Resources.ProjectFileWithBinReference));
4544

45+
46+
var projectLocator = Substitute.For<IProjectLocator>();
47+
var project = new ProjectReferences(typeof(ProjectBasedConventions).Assembly, projectProvider, projectLocator);
4648
Convention.IsWithApprovedExeptions(new ProjectDoesNotReferenceDllsFromBinOrObjDirectories(), project);
4749
}
4850

4951
[Test]
5052
public void scripts_not_embedded_resources()
5153
{
52-
project.Includes = i => i.EndsWith(".sql");
5354
projectProvider
5455
.LoadProjectDocument(Arg.Any<string>())
5556
.Returns(XDocument.Parse(Resources.ProjectFileWithInvalidSqlScriptFile));
5657

58+
var projectLocator = Substitute.For<IProjectLocator>();
59+
var project = new ProjectFiles(typeof (ProjectBasedConventions).Assembly, projectProvider, projectLocator)
60+
{
61+
Items = i => i.FilePath.EndsWith(".sql")
62+
};
5763
var ex = Assert.Throws<ConventionFailedException>(() => Convention.Is(new FilesAreEmbeddedResources(), project));
5864

5965
Approvals.Verify(ex.Message);
@@ -62,7 +68,11 @@ public void scripts_not_embedded_resources()
6268
[Test]
6369
public void scripts_not_embedded_resources_with_approved_exceptions()
6470
{
65-
project.Includes = i => i.EndsWith(".sql");
71+
var projectLocator = Substitute.For<IProjectLocator>();
72+
var project = new ProjectFiles(typeof(ProjectBasedConventions).Assembly, projectProvider, projectLocator)
73+
{
74+
Items = i => i.FilePath.EndsWith(".sql")
75+
};
6676
projectProvider
6777
.LoadProjectDocument(Arg.Any<string>())
6878
.Returns(XDocument.Parse(Resources.ProjectFileWithInvalidSqlScriptFile));

TestStack.ConventionTests/Conventions/Project.cs renamed to TestStack.ConventionTests/Conventions/AbstractProjectData.cs

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,12 @@
11
namespace TestStack.ConventionTests.Conventions
22
{
3-
using System;
43
using System.Reflection;
54
using System.Xml.Linq;
65
using TestStack.ConventionTests.Internal;
76

8-
public class Project : IConventionData
7+
public abstract class AbstractProjectData : IConventionData
98
{
10-
public Func<string, bool> Includes;
11-
12-
public Project(Assembly assembly, IProjectProvider projectProvider, IProjectLocator projectLocator)
9+
protected AbstractProjectData(Assembly assembly, IProjectProvider projectProvider, IProjectLocator projectLocator)
1310
{
1411
Assembly = assembly;
1512
ProjectProvider = projectProvider;
@@ -28,9 +25,7 @@ public void ThrowIfHasInvalidSource()
2825
throw new ConventionSourceInvalidException("Cannot resolve project file for assembly {0}");
2926
}
3027

31-
public bool HasApprovedExceptions { get; set; }
32-
33-
public XDocument GetProject()
28+
protected XDocument GetProject()
3429
{
3530
var location = ProjectLocator.ResolveProjectFilePath(Assembly);
3631
var project = ProjectProvider.LoadProjectDocument(location);
Lines changed: 4 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,15 @@
11
namespace TestStack.ConventionTests.Conventions
22
{
3-
using System;
4-
using System.Collections.Generic;
53
using System.Linq;
6-
using System.Xml.Linq;
74
using TestStack.ConventionTests.Internal;
85

9-
public class FilesAreEmbeddedResources : IConvention<Project>
6+
public class FilesAreEmbeddedResources : IConvention<ProjectFiles>
107
{
11-
public ConventionResult Execute(Project data)
8+
public ConventionResult Execute(ProjectFiles data)
129
{
13-
return ConventionResult.For(GetProjectFiles(data).Where(s => s.Item1 != "EmbeddedResource"),
10+
return ConventionResult.For(data.Files.Where(s => s.ReferenceType != "EmbeddedResource"),
1411
"The following files which should be embedded resources:",
15-
(t, m) => m.AppendLine("\t" + t.Item2));
16-
}
17-
18-
IEnumerable<Tuple<string, string>> GetProjectFiles(Project project)
19-
{
20-
if (project.Includes == null)
21-
throw new InvalidOperationException(
22-
"This convention requires you to provide a filter on the convention data");
23-
const string msbuild = "http://schemas.microsoft.com/developer/msbuild/2003";
24-
var projDefinition = project.GetProject();
25-
var references = projDefinition
26-
.Element(XName.Get("Project", msbuild))
27-
.Elements(XName.Get("ItemGroup", msbuild))
28-
.Elements()
29-
.Select(refElem => Tuple.Create(refElem.Name.LocalName, refElem.Attribute("Include").Value))
30-
.Where(i => project.Includes(i.Item2));
31-
32-
return references;
12+
(t, m) => m.AppendLine("\t" + t.FilePath));
3313
}
3414
}
3515
}
Lines changed: 7 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,29 @@
11
namespace TestStack.ConventionTests.Conventions
22
{
3-
using System.Collections.Generic;
43
using System.Linq;
54
using System.Text;
65
using System.Text.RegularExpressions;
7-
using System.Xml.Linq;
86
using TestStack.ConventionTests.Internal;
97

10-
public class ProjectDoesNotReferenceDllsFromBinOrObjDirectories : IConvention<Project>
8+
public class ProjectDoesNotReferenceDllsFromBinOrObjDirectories : IConvention<ProjectReferences>
119
{
1210
const string AssemblyReferencingObjRegex = @"^(?<assembly>.*?(obj|bin).*?)$";
1311

14-
public ConventionResult Execute(Project data)
12+
public ConventionResult Execute(ProjectReferences data)
1513
{
16-
var projDefinition = data.GetProject();
17-
var invalid = AllProjectReferences(projDefinition).Where(IsBinOrObjReference);
14+
var invalid = data.References.Where(IsBinOrObjReference);
1815
var header = string.Format("Some invalid assembly references found in {0}", data.Assembly.GetName().Name);
1916
return ConventionResult.For(invalid, header, FormatLine);
2017
}
2118

22-
void FormatLine(string assemblyReference, StringBuilder m)
19+
void FormatLine(ProjectReference assemblyReference, StringBuilder m)
2320
{
24-
m.AppendLine("\t" + assemblyReference);
21+
m.AppendLine("\t" + assemblyReference.ReferencedPath);
2522
}
2623

27-
static bool IsBinOrObjReference(string reference)
24+
static bool IsBinOrObjReference(ProjectReference reference)
2825
{
29-
return Regex.IsMatch(reference, AssemblyReferencingObjRegex, RegexOptions.IgnoreCase);
30-
}
31-
32-
static IEnumerable<string> AllProjectReferences(XDocument projDefinition)
33-
{
34-
XNamespace msbuild = "http://schemas.microsoft.com/developer/msbuild/2003";
35-
var references = projDefinition
36-
.Element(msbuild + "Project")
37-
.Elements(msbuild + "ItemGroup")
38-
.Elements(msbuild + "Reference")
39-
.Elements(msbuild + "HintPath")
40-
.Select(refElem => refElem.Value);
41-
return references;
26+
return Regex.IsMatch(reference.ReferencedPath, AssemblyReferencingObjRegex, RegexOptions.IgnoreCase);
4227
}
4328
}
4429
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
namespace TestStack.ConventionTests.Conventions
2+
{
3+
public class ProjectFile
4+
{
5+
public string FilePath { get; set; }
6+
public string ReferenceType { get; set; }
7+
}
8+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
namespace TestStack.ConventionTests.Conventions
2+
{
3+
using System;
4+
using System.Linq;
5+
using System.Reflection;
6+
using System.Xml.Linq;
7+
using TestStack.ConventionTests.Internal;
8+
9+
public class ProjectFiles : AbstractProjectData
10+
{
11+
public ProjectFiles(Assembly assembly, IProjectProvider projectProvider, IProjectLocator projectLocator)
12+
: base(assembly, projectProvider, projectLocator)
13+
{
14+
Items = PredicateHelpers.All<ProjectFile>();
15+
}
16+
17+
18+
public ProjectFile[] Files
19+
{
20+
get
21+
{
22+
var project = GetProject();
23+
const string msbuild = "http://schemas.microsoft.com/developer/msbuild/2003";
24+
return project
25+
.Element(XName.Get("Project", msbuild))
26+
.Elements(XName.Get("ItemGroup", msbuild))
27+
.Elements()
28+
.Select(refElem =>
29+
new ProjectFile
30+
{
31+
ReferenceType = refElem.Name.LocalName,
32+
FilePath = refElem.Attribute("Include").Value
33+
})
34+
.Where(Items)
35+
.ToArray();
36+
}
37+
}
38+
39+
public Func<ProjectFile, bool> Items { get; set; }
40+
}
41+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
namespace TestStack.ConventionTests.Conventions
2+
{
3+
public class ProjectReference
4+
{
5+
public string ReferencedPath { get; set; }
6+
}
7+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
namespace TestStack.ConventionTests.Conventions
2+
{
3+
using System;
4+
using System.Collections.Generic;
5+
using System.Linq;
6+
using System.Reflection;
7+
using System.Xml.Linq;
8+
using TestStack.ConventionTests.Internal;
9+
10+
public class ProjectReferences : AbstractProjectData
11+
{
12+
public ProjectReferences(Assembly assembly, IProjectProvider projectProvider, IProjectLocator projectLocator)
13+
: base(assembly, projectProvider, projectLocator)
14+
{
15+
Items = PredicateHelpers.All<ProjectReference>();
16+
}
17+
18+
public ProjectReference[] References
19+
{
20+
get
21+
{
22+
var project = GetProject();
23+
return AllProjectReferences(project)
24+
.Select(r => new ProjectReference
25+
{
26+
ReferencedPath = r
27+
})
28+
.Where(Items)
29+
.ToArray();
30+
}
31+
}
32+
33+
static IEnumerable<string> AllProjectReferences(XDocument projDefinition)
34+
{
35+
XNamespace msbuild = "http://schemas.microsoft.com/developer/msbuild/2003";
36+
var references = projDefinition
37+
.Element(msbuild + "Project")
38+
.Elements(msbuild + "ItemGroup")
39+
.Elements(msbuild + "Reference")
40+
.Elements(msbuild + "HintPath")
41+
.Select(refElem => refElem.Value);
42+
return references;
43+
}
44+
45+
public Func<ProjectReference, bool> Items { get; set; }
46+
}
47+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
namespace TestStack.ConventionTests.Internal
2+
{
3+
using System;
4+
5+
public static class PredicateHelpers
6+
{
7+
public static Func<T, bool> All<T>()
8+
{
9+
return _ => true;
10+
}
11+
12+
public static Func<T, bool> None<T>()
13+
{
14+
return _ => false;
15+
}
16+
}
17+
}

TestStack.ConventionTests/TestStack.ConventionTests.csproj

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,10 @@
6161
<ItemGroup>
6262
<Compile Include="ConventionFailedException.cs" />
6363
<Compile Include="Conventions\ConventionSourceInvalidException.cs" />
64+
<Compile Include="Conventions\ProjectFile.cs" />
65+
<Compile Include="Conventions\ProjectFiles.cs" />
66+
<Compile Include="Conventions\ProjectReference.cs" />
67+
<Compile Include="Conventions\ProjectReferences.cs" />
6468
<Compile Include="IConventionData.cs" />
6569
<Compile Include="Internal\ConventionResult.cs" />
6670
<Compile Include="Conventions\AllMethodsAreVirtual.cs" />
@@ -69,13 +73,14 @@
6973
<Compile Include="Internal\AssemblyProjectLocator.cs" />
7074
<Compile Include="Convention.cs" />
7175
<Compile Include="IConvention.cs" />
72-
<Compile Include="Conventions\Project.cs" />
76+
<Compile Include="Conventions\AbstractProjectData.cs" />
7377
<Compile Include="Conventions\Types.cs" />
7478
<Compile Include="ConventionData.cs" />
7579
<Compile Include="Internal\IProjectLocator.cs" />
7680
<Compile Include="Internal\IProjectProvider.cs" />
7781
<Compile Include="Internal\LinqExtensions.cs" />
7882
<Compile Include="Conventions\ProjectDoesNotReferenceDllsFromBinOrObjDirectories.cs" />
83+
<Compile Include="Internal\PredicateHelpers.cs" />
7984
<Compile Include="Internal\ProjectProvider.cs" />
8085
<Compile Include="Properties\AssemblyInfo.cs" />
8186
<Compile Include="Internal\ReflectionExtensions.cs" />

0 commit comments

Comments
 (0)