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
97 changes: 34 additions & 63 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,76 +1,47 @@
ConventionTests
===============
TestStack.ConventionTests
=========================

### What is ConventionTests?
Convention over Configuration is a great way to cut down repetitive boilerplate code. But how do you validate that your code adheres to your conventions? Convention Tests is a code-only NuGet that provides a simple API to build validation rules for convention validation tests.
Convention over Configuration is a great way to cut down repetitive boilerplate code.
But how do you validate that your code adheres to your conventions?
TestStack.ConventionTests is a simple NuGet library that makes it easy to build validation rules for convention validation tests.

### Using Con­ven­tion­Tests
Con­ven­tion­Tests is a sim­ple code-only Nuget that pro­vides a min­i­mal­is­tic and lim­ited API enforc­ing cer­tain struc­ture when writ­ing con­ven­tion tests and inte­grat­ing with NUnit. Installing it will add two .cs files to the project and a few depen­den­cies ([NUnit](http://www.nunit.org/), [Castle Wind­sor](http://stw.castleproject.org/Windsor.MainPage.ashx) and [ApprovalTests](http://approvaltests.sourceforge.net/)).

ConventionTests.NUnit file is where all the rel­e­vant code is located and __Run file is the file that runs your tests. The approach is to cre­ate a file per con­ven­tion and name them in a descrip­tive man­ner, so that you can learn what the con­ven­tions you have in the project are by just look­ing at the files in your Con­ven­tions folder, with­out hav­ing to open them.

Each con­ven­tion test inher­its (directly or indi­rectly) from the ICon­ven­tion­Test inter­face. There’s an abstract imple­men­ta­tion of the inter­face, Con­ven­tion­Test­Base and a few spe­cial­ized imple­men­ta­tions for com­mon sce­nar­ios pro­vided out of the box: Type-based one (Con­ven­tion­Test) and two for Wind­sor (Wind­sor­Con­ven­tion­Test, non-generic and generic for diagnostics-based tests).
TestStack.ConventionTests also will generate a convention report of the conventions present in your codebase, which you can publish as **living documentation**

#### Type-based con­ven­tion tests
The most com­mon and most generic group of con­ven­tions are ones based around types and type infor­ma­tion. Con­ven­tions like “every controller’s name ends with ‘Con­troller’”, or “Every method on WCF ser­vice con­tracts must have Oper­a­tionCon­trac­tAt­tribute” are exam­ples of such conventions.

You write them by cre­at­ing a class inher­it­ing Con­ven­tion­Test, which forces you to over­ride one method. Here’s a min­i­mal example
### Using Con­ven­tion­Tests

public class Controllers_have_Controller_suffix_in_type_name : ConventionTest
[Test]
public void DomainHasVirtualMethodsConvention()
{
protected override ConventionData SetUp()
{
return new ConventionData
{
Types = t => t.IsConcrete<IController>(),
Must = t => t.Name.EndsWith("Controller")
};
}
// Define some data
var nHibernateEntities = Tpes.InAssemblyOf<SampleDomainClass>()
.ConcreteTypes().InNamespace(typeof (SampleDomainClass).Namespace)
.ToTypes("nHibernate Entitites");

// Apply convention to data
Convention.Is(new AllMethodsAreVirtual(), nhibernateEntities);
}

#### Windsor-based con­ven­tion tests
Another com­mon set of con­ven­tion tests are tests regard­ing an IoC con­tainer. Cas­tle Wind­sor is sup­ported out of the box. The struc­ture of the tests and API is sim­i­lar, with the dif­fer­ence being that instead of types we’re deal­ing with Windsor’s com­po­nent Han­dlers.
For more information [view the TestStack.ConventionTests documentation](http://docs.teststack.net/conventiontests/index.html)

public class List_classes_registered_in_Windsor : WindsorConventionTest
{
protected override WindsorConventionData SetUp()
{
return new WindsorConventionData(new WindsorContainer()
.Install(FromAssembly.Containing<AuditedAction>()))
{
FailDescription = "All Windsor components",
FailItemDescription = h => BuildDetailedHandlerDescription(h)+" | "+
h.ComponentModel.GetLifestyleDescription(),
}.WithApprovedExceptions("We just list all of them.");

}
}
### Packaged Conventions
Here is a list of some of the pacakged conventions

#### Cus­tom con­ven­tion tests
Say we wanted to cre­ate a con­ven­tion test that lists all of our NHibernate col­lec­tions where we do cas­cade deletes, so that when we add a new col­lec­tion the test would fail remind­ing us of the issue, and force us to pay atten­tion to how we struc­ture rela­tion­ships in the appli­ca­tion. To do this we could cre­ate a base NHiber­nate­Con­ven­tion­Test and NHi­iber­nate­Con­ven­tion­Data to cre­ate sim­i­lar struc­ture, or just build a sim­ple one-class con­ven­tion like that:
- **AllClassesHaveDefaultConstructor** - All classes in defined data must have a default ctor (protected or public)
- **AllMethodsAreVirtual** - All classes in defined data must have virtual methods (includes get_Property/set_Property backing methods)
- **ClassTypeHasSpecificNamespace** - For example, Dto's must live in the Assembly.Dtos namespace'
- **FilesAreEmbeddedResources** - All .sql files are embedded resources
- **ProjectDoesNotReferenceDllsFromBinOrObjDirectories** - Specified project file must not reference assemblies from bin/obj directory
- **MvcControllerNameAndBaseClassConvention** - Enforces MVC controller naming conventions
- Types ending in *Controller must inherit from Controller (or ApiController), and
- Types inheriting from ControllerBase must be named *Controller
- **MvcControllerNameAndBaseClassConvention** - Enforces WebApi controller naming conventions
- Types ending in *Controller must inherit from ApiController (or Controller), and
- Types inheriting from ApiController must be named *Controller

public class List_collection_that_cascade_deletes:ConventionTestBase
{
public override void Execute()
{
// NH Bootstrapper is our custom class to set up NH
var bootstrapper = new NHibernateBootstrapper();
var configuration = bootstrapper.BuildConfiguration();

var message = new StringBuilder("Collections with cascade delete orphan");
foreach (var @class in configuration.ClassMappings)
{
foreach (var property in @class.PropertyIterator)
{
if(property.CascadeStyle.HasOrphanDelete)
{
message.AppendLine(@class.NodeName + "." + property.Name);
}
}
}
Approve(message.ToString());
}
}
If you would like to define your own conventions see [Defining Conventions](http://docs.teststack.net/ConventionTests/DefiningConventions.html)

### Where to find out more
[Krzysztof Koźmic](https://github.com/kkozmic) spoke about ConventionTests at NDC 2012. You can find the video of that talk [here](http://vimeo.com/43676874), slides [here](http://kozmic.pl/presentations/) and the introductory blog post [here](http://kozmic.pl/2012/06/14/using-conventiontests/).
[Krzysztof Koźmic](https://github.com/kkozmic) spoke about ConventionTests at NDC 2012. You can find the video of that talk [here](http://vimeo.com/43676874), slides [here](http://kozmic.pl/presentations/) and the introductory blog post [here](http://kozmic.pl/2012/06/14/using-conventiontests/).

[TestStack.ConventionTests documentation](http://docs.teststack.net/conventiontests/index.html)
5 changes: 2 additions & 3 deletions TestStack.ConventionTests/TestStack.ConventionTests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,7 @@
<Reference Include="System.Core" />
<Reference Include="System.Web" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
Expand Down Expand Up @@ -116,7 +114,8 @@
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
-->
<Target Name="AfterBuild">
<Copy SourceFiles="..\Readme.md" DestinationFiles="$(OutputPath)\Readme.txt" />
</Target>
-->
</Project>
12 changes: 10 additions & 2 deletions TestStack.ConventionTests/TestStack.ConventionTests.nuspec
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,23 @@
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<metadata>
<version>$version$</version>
<authors>Krzysztof Kozmic</authors>
<owners>Krzysztof Kozmic</owners>
<authors>Krzysztof Kozmic, Jake Ginnivan</authors>
<owners>Krzysztof Kozmic, Jake Ginnivan</owners>
<id>ConventionTests</id>
<title>ConventionTests</title>
<tags>xunit nunit convention testing documentation</tags>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>Simple convention-tester</description>
<summary>Simple library offering a simple way to test conventions.</summary>
<projectUrl>https://github.com/TestStack/ConventionTests</projectUrl>
<licenseUrl>https://github.com/TestStack/ConventionTests/blob/master/license.txt</licenseUrl>
<releaseNotes>v2 Release Highlights
- Can be used with any unit testing framework
- Outputs html convention report with your project conventions (living doco)
- Pre-packaged conventions</releaseNotes>
<dependencies>
<dependency id="Mono.Cecil" />
<dependency id="ApprovalTests" />
</dependencies>
</metadata>
<files>
Expand Down