Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions TestAssembly/Dtos/AnotherClass.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace TestAssembly.Dtos
{
public class AnotherClass
{

}
}
7 changes: 7 additions & 0 deletions TestAssembly/Dtos/BlahDto.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace TestAssembly.Dtos
{
public class BlahDto
{

}
}
7 changes: 7 additions & 0 deletions TestAssembly/SomeDto.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace TestAssembly
{
public class SomeDto
{

}
}
3 changes: 3 additions & 0 deletions TestAssembly/TestAssembly.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,10 @@
<Compile Include="ClassWithPrivateDefaultCtor.cs" />
<Compile Include="ClassWithProtectedDefaultCtor.cs" />
<Compile Include="ClassWithPublicDefaultCtor.cs" />
<Compile Include="Dtos\AnotherClass.cs" />
<Compile Include="Dtos\BlahDto.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="SomeDto.cs" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
Header
------

Approved Exception
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
Some invalid assembly references found in TestStack.ConventionTests.Tests
-------------------------------------------------------------------------

bin\Debug\ApprovalTests.dll
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
Some invalid assembly references found in TestStack.ConventionTests.Tests
-------------------------------------------------------------------------

bin\Debug\ApprovalTests.dll
1 change: 1 addition & 0 deletions TestStack.ConventionTests.Tests/ProjectBasedConventions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using ApprovalTests.Reporters;
using NSubstitute;
using NUnit.Framework;
using TestStack.ConventionTests.ConventionData;
using TestStack.ConventionTests.Conventions;
using TestStack.ConventionTests.Internal;
using TestStack.ConventionTests.Tests.Properties;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
The following files which should be embedded resources:
-------------------------------------------------------

Scripts\Script2.sql
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
The following files which should be embedded resources:
-------------------------------------------------------

Scripts\Script2.sql
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
The following types do not have default constructor
---------------------------------------------------

TestAssembly.ClassWithNoDefaultCtor
TestAssembly.ClassWithPrivateDefaultCtor

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
The following types do not have default constructor
---------------------------------------------------

TestAssembly.ClassWithNoDefaultCtor
TestAssembly.ClassWithPrivateDefaultCtor
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
The following methods are not virtual.
--------------------------------------

TestAssembly.SampleDomainClass.TestNonVirtual
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
The following methods are not virtual.
--------------------------------------

TestAssembly.SampleDomainClass.TestNonVirtual
29 changes: 28 additions & 1 deletion TestStack.ConventionTests.Tests/TypeBasedConventions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
using ApprovalTests.Reporters;
using NUnit.Framework;
using TestAssembly;
using TestAssembly.Dtos;
using TestStack.ConventionTests.ConventionData;
using TestStack.ConventionTests.Conventions;

[TestFixture]
Expand All @@ -17,7 +19,7 @@ public TypeBasedConventions()
var itemsToVerify = typeof (SampleDomainClass).Assembly.GetTypes();
nhibernateEntities = new Types
{
ApplicableTypes = itemsToVerify
TypesToVerify = itemsToVerify
};
}

Expand Down Expand Up @@ -48,5 +50,30 @@ public void all_methods_are_virtual_wth_approved_exceptions()
{
Convention.IsWithApprovedExeptions(new AllMethodsAreVirtual(), nhibernateEntities);
}

[Test]
public void dtos_exists_in_dto_namespace()
{
var types = new Types
{
TypesToVerify = new[] { typeof(SomeDto), typeof(BlahDto), typeof(AnotherClass)}
};
var convention = new ClassTypeHasSpecificNamespace(t => t.Name.EndsWith("Dto"), "TestAssembly.Dtos", "Dto");

var ex = Assert.Throws<ConventionFailedException>(() =>Convention.Is(convention, types));
Approvals.Verify(ex.Message);
}

[Test]
public void dtos_exists_in_dto_namespace_wth_approved_exceptions()
{
var types = new Types
{
TypesToVerify = new[] { typeof(SomeDto), typeof(BlahDto), typeof(AnotherClass) }
};
var convention = new ClassTypeHasSpecificNamespace(t => t.Name.EndsWith("Dto"), "TestAssembly.Dtos", "Dto");

Convention.IsWithApprovedExeptions(convention, types);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
Dtos must be under the 'TestAssembly.Dtos' namespace
----------------------------------------------------

TestAssembly.SomeDto


Non-Dtos must not be under the 'TestAssembly.Dtos' namespace
------------------------------------------------------------

TestAssembly.Dtos.AnotherClass
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
Dtos must be under the 'TestAssembly.Dtos' namespace
----------------------------------------------------

TestAssembly.SomeDto


Non-Dtos must not be under the 'TestAssembly.Dtos' namespace
------------------------------------------------------------

TestAssembly.Dtos.AnotherClass
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
namespace TestStack.ConventionTests.Conventions
namespace TestStack.ConventionTests.ConventionData
{
using System.Reflection;
using System.Xml.Linq;
using TestStack.ConventionTests.Conventions;
using TestStack.ConventionTests.Internal;

public abstract class AbstractProjectData : IConventionData
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
namespace TestStack.ConventionTests.Conventions
namespace TestStack.ConventionTests.ConventionData
{
public class ProjectFile
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
namespace TestStack.ConventionTests.Conventions
namespace TestStack.ConventionTests.ConventionData
{
using System;
using System.Linq;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
namespace TestStack.ConventionTests.Conventions
namespace TestStack.ConventionTests.ConventionData
{
public class ProjectReference
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
namespace TestStack.ConventionTests.Conventions
namespace TestStack.ConventionTests.ConventionData
{
using System;
using System.Collections.Generic;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,21 +1,19 @@
namespace TestStack.ConventionTests.Conventions
namespace TestStack.ConventionTests.ConventionData
{
using System;
using TestStack.ConventionTests.Conventions;
using TestStack.ConventionTests.Internal;

/// <summary>
/// This is where we set what our convention is all about.
/// </summary>
public class Types : IConventionData
{
//NOTE: that's a terrible name
public Type[] ApplicableTypes { get; set; }

public bool HasApprovedExceptions { get; set; }
public Type[] TypesToVerify { get; set; }

public void EnsureHasNonEmptySource()
{
if (ApplicableTypes.None())
if (TypesToVerify.None())
throw new ConventionSourceInvalidException("You must supply types to verify");
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
namespace TestStack.ConventionTests.Conventions
{
using System.Linq;
using TestStack.ConventionTests.ConventionData;
using TestStack.ConventionTests.Internal;

public class AllClassesHaveDefaultConstructor : IConvention<Types>
Expand All @@ -14,7 +15,7 @@ public AllClassesHaveDefaultConstructor()

public ConventionResult Execute(Types data)
{
var invalid = data.ApplicableTypes.Where(t => t.HasDefaultConstructor() == false);
var invalid = data.TypesToVerify.Where(t => t.HasDefaultConstructor() == false);
return ConventionResult.For(invalid, HeaderMessage, t => "\t" + t);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System.Linq;
using System.Reflection;
using System.Text;
using TestStack.ConventionTests.ConventionData;
using TestStack.ConventionTests.Internal;

public class AllMethodsAreVirtual : IConvention<Types>
Expand All @@ -20,7 +21,7 @@ public ConventionResult Execute(Types data)
{
// do we want to encapsulate that in some way?
// also notice how data gives us types, yet the convention acts upon methods.
var items = from applicableType in data.ApplicableTypes
var items = from applicableType in data.TypesToVerify
let nonVirtuals = applicableType.NonVirtualMethods()
where nonVirtuals.Any()
select Tuple.Create(applicableType, nonVirtuals);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
namespace TestStack.ConventionTests.Conventions
{
using System;
using System.Linq;
using TestStack.ConventionTests.ConventionData;
using TestStack.ConventionTests.Internal;

/// <summary>
/// This convention allows you to enforce a particular type of class is under a namespace, for instance.
///
/// Dto must be under App.Contracts.Dtos
/// Domain Objects must be under App.Domain
/// Event Handlers must be under App.Handlers
///
/// This is a Symmetric convention, and will verify all of a Class Type lives in the namespace, but also that only that class type is in that namespace
/// </summary>
public class ClassTypeHasSpecificNamespace : IConvention<Types>
{
readonly Func<Type, bool> classIsApplicable;
readonly string namespaceToCheck;
readonly string classType;

/// <summary>
/// Ctor
/// </summary>
/// <param name="classIsApplicable">Predicate to verify if the class is the right type</param>
/// <param name="namespaceToCheck"></param>
/// <param name="classType">The class type. ie, Dto, Domain Object, Event Handler</param>
public ClassTypeHasSpecificNamespace(Func<Type, bool> classIsApplicable, string namespaceToCheck, string classType)
{
this.classIsApplicable = classIsApplicable;
this.namespaceToCheck = namespaceToCheck;
this.classType = classType;
}

public ConventionResult Execute(Types data)
{
var applicableTypes = data.TypesToVerify.Where(classIsApplicable);
var nonApplicableTypes = data.TypesToVerify.Where(t => !classIsApplicable(t));

var applicableTypesWhichDoNotConform = applicableTypes
.Where(t => t.Namespace == null || !t.Namespace.StartsWith(namespaceToCheck))
.ToArray();
var nonApplicableTypesInNamespace = nonApplicableTypes
.Where(t => t.Namespace != null && t.Namespace.StartsWith(namespaceToCheck))
.ToArray();

return ConventionResult.ForSymmetric(
string.Format("{0}s must be under the '{1}' namespace", classType, namespaceToCheck),
applicableTypesWhichDoNotConform,
string.Format("Non-{0}s must not be under the '{1}' namespace", classType, namespaceToCheck),
nonApplicableTypesInNamespace,
t => "\t" + t.FullName);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
namespace TestStack.ConventionTests.Conventions
{
using System.Linq;
using TestStack.ConventionTests.ConventionData;
using TestStack.ConventionTests.Internal;

public class FilesAreEmbeddedResources : IConvention<ProjectFiles>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using TestStack.ConventionTests.ConventionData;
using TestStack.ConventionTests.Internal;

public class ProjectDoesNotReferenceDllsFromBinOrObjDirectories : IConvention<ProjectReferences>
Expand Down
49 changes: 49 additions & 0 deletions TestStack.ConventionTests/Internal/ConventionResult.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ public static ConventionResult For<TResult>(
// NOTE: we might possibly want to abstract the StringBuilder to have more high level construct that would allow us to plug rich reports here...
var message = new StringBuilder(header);
message.AppendLine();
message.AppendLine(string.Empty.PadRight(header.Length, '-'));
message.AppendLine();
Array.ForEach(array, r => itemDescriptor(r, message));
result.Message = message.ToString();
Expand All @@ -46,5 +47,53 @@ public static ConventionResult For<TResult>(
{
return For(items, header, (item, message) => message.AppendLine(itemDescriptor(item)));
}

public static ConventionResult ForSymmetric<TResult>(
string firstHeader, TResult[] firstResults,
string secondHeader, TResult[] secondResults,
Action<TResult, StringBuilder> itemDescriptor)
{
var firstArray = firstResults.ToArray();
var secondArray = secondResults.ToArray();
var result = new ConventionResult();
if (firstArray.None() && secondArray.None())
{
return result;
}

var message = new StringBuilder();
if (firstArray.Any())
{
message.AppendLine(firstHeader);
message.AppendLine(string.Empty.PadRight(firstHeader.Length, '-'));
message.AppendLine();
Array.ForEach(firstArray, r => itemDescriptor(r, message));
}
if (secondArray.Any())
{
if (firstArray.Any())
{
message.AppendLine();
message.AppendLine();
}
message.AppendLine(secondHeader);
message.AppendLine(string.Empty.PadRight(secondHeader.Length, '-'));
message.AppendLine();
Array.ForEach(secondArray, r => itemDescriptor(r, message));
}
result.Message = message.ToString();
return result;
}

public static ConventionResult ForSymmetric<TResult>(
string firstHeader, TResult[] firstResults,
string secondHeader, TResult[] secondResults,
Func<TResult, string> itemDescriptor)
{
return ForSymmetric(
firstHeader, firstResults, secondHeader,
secondResults,
(item, message) => message.AppendLine(itemDescriptor(item)));
}
}
}
Loading