{"__v":6,"_id":"54d5221940b6910d00c6c817","category":{"__v":2,"_id":"54d5221840b6910d00c6c815","pages":["54d5221940b6910d00c6c817","55448c5d3c2cf10d00c3adb8"],"project":"54d5221740b6910d00c6c811","version":"54d5221840b6910d00c6c814","sync":{"url":"","isSync":false},"reference":false,"createdAt":"2015-02-06T20:20:40.573Z","from_sync":false,"order":9999,"slug":"getting-started","title":"Getting Started"},"project":"54d5221740b6910d00c6c811","user":"54c4ca54686bce0d00efe1b9","version":{"__v":1,"_id":"54d5221840b6910d00c6c814","project":"54d5221740b6910d00c6c811","createdAt":"2015-02-06T20:20:40.105Z","releaseDate":"2015-02-06T20:20:40.105Z","categories":["54d5221840b6910d00c6c815"],"is_deprecated":false,"is_hidden":false,"is_beta":false,"is_stable":true,"codename":"","version_clean":"1.0.0","version":"1.0"},"updates":["55664ebf979a3c2500bbb017"],"next":{"pages":[],"description":""},"createdAt":"2015-02-06T20:20:41.242Z","link_external":false,"link_url":"","githubsync":"","sync_unique":"","hidden":false,"api":{"results":{"codes":[]},"settings":"","auth":"required","params":[],"url":""},"isReference":false,"order":999,"body":"It is really easy to get started with ConventionTests, there are a number of included conventions that come out of the box:\n\n  * All Classes Have Default Constructor\n  * All Methods are Virtual\n  * Class type has specific namespace (for example, all dtos must live in the ProjectName.Dtos namespace)\n  * Files are Embedded Resources\n  * Project does not reference dlls from Bin or Obj directory\n\nOthers are being added over time and you can create your own custom ones\n\n##Writing your first Convention test\n\n1. Using your favourite testing framework, create a new test. Lets call it:\n\nentities_must_have_default_constructor\n\n2. Define some types to validate against a convention\n\nThe following line get a list of all the types in the assembly that contains SampleDomainClass.\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"var itemsToVerify = Types.InAssemblyOf<SampleDomainClass>();\",\n      \"language\": \"csharp\"\n    }\n  ]\n}\n[/block]\nThere are also overloads to restrict the types to a specific namespace within the assembly.\n\n3. Assert the convention\n\nNow we have a list of types to check, we can use one of the pre-built conventions and check all of the types against this convention:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"Convention.Is(new AllClassesHaveDefaultConstructor(), itemsToVerify);\",\n      \"language\": \"csharp\"\n    }\n  ]\n}\n[/block]\nThat's it!\n\nWhen you run this convention, if any of the types don't meet with the chosen convention, it fails and an exception will be thrown, which will look something like this:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"ConventionFailedException\\nMessage = Failed: 'Types must have a default constructor'\\n-----------------------------------------------------------------\\n\\nTestAssembly.ClassWithNoDefaultCtor\\nTestAssembly.ClassWithPrivateDefaultCtor\",\n      \"language\": \"text\"\n    }\n  ]\n}\n[/block]\nHow cool is that!\n\n## Reporting\n\nIf you would like to use ConventionTests reporting features, you just have to opt in by specifying the reporter you want. This makes it easy to add your own reporters, for example a WikiReporter may be better than the HtmlReporter\n\nIn your Properties\\AssemblyInfo.cs file add the reporters you want. This are global reporters which will report the results of all conventions.\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"[assembly: ConventionReporter(typeof(HtmlConventionResultsReporter))]\\n[assembly: ConventionReporter(typeof(MarkdownConventionResultsReporter))]\",\n      \"language\": \"csharp\"\n    }\n  ]\n}\n[/block]\nThen if you look in the directory where your test assembly is, there will be an html report called Conventions.htm, serving as living documentation!\n\n## Defining Conventions\n\nIf you want to define your own conventions, it is really easy.\n\nStep 1\nCreate a new class, inheriting from IConvention<TData>, lets use the must have default constructor convention as an example\n\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"public class AllClassesHaveDefaultConstructor : IConvention<Types>\\n{\\n    public void Execute(Types data, IConventionResult result)\\n    {\\n\\n    }\\n}\",\n      \"language\": \"csharp\"\n    }\n  ]\n}\n[/block]\nStep 2\nWrite the convention logic\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"var typesWithoutDefaultCtor = data.TypesToVerify.Where(t => t.HasDefaultConstructor() == false);\\nresult.Is(\\\"Types must have a default constructor\\\", typesWithoutDefaultCtor);\",\n      \"language\": \"csharp\"\n    }\n  ]\n}\n[/block]\n\n## Final result\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"public class AllClassesHaveDefaultConstructor : IConvention<Types>\\n{\\n    public void Execute(Types data, IConventionResult result)\\n    {\\n        var typesWithoutDefaultCtor = data.TypesToVerify.Where(t => t.HasDefaultConstructor() == false);\\n        result.Is(\\\"Types must have a default constructor\\\", typesWithoutDefaultCtor);\\n    }\\n}\",\n      \"language\": \"csharp\"\n    }\n  ]\n}\n[/block]\n## IConventionResult\nCurrently convention tests supports two types of convention results, the one we have just seen is a normal result. The other type is a symmetric result, which is the result for a symmetric convention.\n\nAn example of a symmetric convention is ClassTypeHasSpecificNamespace. It can verify a particular class type (dto, domain object, event handler) lives in a certain namespace, but it will also verify that ONLY that class type lives in that namespace. new ClassTypeHasSpecificNamespace(t => t.Name.EndsWith(\"Dto\"), \"TestAssembly.Dtos\", \"Dto\")\n\nThe result will look like this:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"result.IsSymmetric(\\n    string.Format(\\\"{0}s must be under the '{1}' namespace\\\", classType, namespaceToCheck),\\n    string.Format(\\\"Non-{0}s must not be under the '{1}' namespace\\\", classType, namespaceToCheck),\\n    classIsApplicable,\\n    TypeLivesInSpecifiedNamespace,\\n    data.TypesToVerify);\",\n      \"language\": \"csharp\"\n    }\n  ]\n}\n[/block]\n## Symmetric Conventions\n\nSymmetric conventions will verify a convention and also the inverse of that convention.\n\nAn example of a symmetric convention is ClassTypeHasSpecificNamespace. It can verify a particular class type (dto, domain object, event handler) lives in a certain namespace, but it will also verify that ONLY that class type lives in that namespace.\n\nIn the above example, let us say 'Dtos must live under Project.Dtos'. This means that all data contains ALL TYPES in the assembly, correct data is a dto living in the Project.Dtos namespace. But we have two failure conditions.\n\nThe first is if a Dto is outside the Project.Dtos namespace, the convention fails. The second is if a non-dto class lives inside the Project.Dtos namespace.\n\n## How to use a symmetric convention\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"var types = new Types(\\\"Types in MyProject\\\")\\n{\\n    TypesToVerify = typeof(MyDto).Assembly.GetTypes()\\n};\\nvar convention = new ClassTypeHasSpecificNamespace(\\n    classIsApplicable: t => t.Name.EndsWith(\\\"Dto\\\"), \\n    namespaceToCheck : \\\"MyProject.Dtos\\\", \\n    classType: \\\"Dto\\\");\\nConvention.Is(convention, types);\",\n      \"language\": \"csharp\"\n    }\n  ]\n}\n[/block]\nAs you can see, symmetric conventions are no different to enforce","excerpt":"This page will help you get started with ConventionTests. You'll be up and running in a jiffy!","slug":"getting-started","type":"basic","title":"Getting Started with ConventionTests"}

Getting Started with ConventionTests

This page will help you get started with ConventionTests. You'll be up and running in a jiffy!

It is really easy to get started with ConventionTests, there are a number of included conventions that come out of the box: * All Classes Have Default Constructor * All Methods are Virtual * Class type has specific namespace (for example, all dtos must live in the ProjectName.Dtos namespace) * Files are Embedded Resources * Project does not reference dlls from Bin or Obj directory Others are being added over time and you can create your own custom ones ##Writing your first Convention test 1. Using your favourite testing framework, create a new test. Lets call it: entities_must_have_default_constructor 2. Define some types to validate against a convention The following line get a list of all the types in the assembly that contains SampleDomainClass. [block:code] { "codes": [ { "code": "var itemsToVerify = Types.InAssemblyOf<SampleDomainClass>();", "language": "csharp" } ] } [/block] There are also overloads to restrict the types to a specific namespace within the assembly. 3. Assert the convention Now we have a list of types to check, we can use one of the pre-built conventions and check all of the types against this convention: [block:code] { "codes": [ { "code": "Convention.Is(new AllClassesHaveDefaultConstructor(), itemsToVerify);", "language": "csharp" } ] } [/block] That's it! When you run this convention, if any of the types don't meet with the chosen convention, it fails and an exception will be thrown, which will look something like this: [block:code] { "codes": [ { "code": "ConventionFailedException\nMessage = Failed: 'Types must have a default constructor'\n-----------------------------------------------------------------\n\nTestAssembly.ClassWithNoDefaultCtor\nTestAssembly.ClassWithPrivateDefaultCtor", "language": "text" } ] } [/block] How cool is that! ## Reporting If you would like to use ConventionTests reporting features, you just have to opt in by specifying the reporter you want. This makes it easy to add your own reporters, for example a WikiReporter may be better than the HtmlReporter In your Properties\AssemblyInfo.cs file add the reporters you want. This are global reporters which will report the results of all conventions. [block:code] { "codes": [ { "code": "[assembly: ConventionReporter(typeof(HtmlConventionResultsReporter))]\n[assembly: ConventionReporter(typeof(MarkdownConventionResultsReporter))]", "language": "csharp" } ] } [/block] Then if you look in the directory where your test assembly is, there will be an html report called Conventions.htm, serving as living documentation! ## Defining Conventions If you want to define your own conventions, it is really easy. Step 1 Create a new class, inheriting from IConvention<TData>, lets use the must have default constructor convention as an example [block:code] { "codes": [ { "code": "public class AllClassesHaveDefaultConstructor : IConvention<Types>\n{\n public void Execute(Types data, IConventionResult result)\n {\n\n }\n}", "language": "csharp" } ] } [/block] Step 2 Write the convention logic [block:code] { "codes": [ { "code": "var typesWithoutDefaultCtor = data.TypesToVerify.Where(t => t.HasDefaultConstructor() == false);\nresult.Is(\"Types must have a default constructor\", typesWithoutDefaultCtor);", "language": "csharp" } ] } [/block] ## Final result [block:code] { "codes": [ { "code": "public class AllClassesHaveDefaultConstructor : IConvention<Types>\n{\n public void Execute(Types data, IConventionResult result)\n {\n var typesWithoutDefaultCtor = data.TypesToVerify.Where(t => t.HasDefaultConstructor() == false);\n result.Is(\"Types must have a default constructor\", typesWithoutDefaultCtor);\n }\n}", "language": "csharp" } ] } [/block] ## IConventionResult Currently convention tests supports two types of convention results, the one we have just seen is a normal result. The other type is a symmetric result, which is the result for a symmetric convention. An example of a symmetric convention is ClassTypeHasSpecificNamespace. It can verify a particular class type (dto, domain object, event handler) lives in a certain namespace, but it will also verify that ONLY that class type lives in that namespace. new ClassTypeHasSpecificNamespace(t => t.Name.EndsWith("Dto"), "TestAssembly.Dtos", "Dto") The result will look like this: [block:code] { "codes": [ { "code": "result.IsSymmetric(\n string.Format(\"{0}s must be under the '{1}' namespace\", classType, namespaceToCheck),\n string.Format(\"Non-{0}s must not be under the '{1}' namespace\", classType, namespaceToCheck),\n classIsApplicable,\n TypeLivesInSpecifiedNamespace,\n data.TypesToVerify);", "language": "csharp" } ] } [/block] ## Symmetric Conventions Symmetric conventions will verify a convention and also the inverse of that convention. An example of a symmetric convention is ClassTypeHasSpecificNamespace. It can verify a particular class type (dto, domain object, event handler) lives in a certain namespace, but it will also verify that ONLY that class type lives in that namespace. In the above example, let us say 'Dtos must live under Project.Dtos'. This means that all data contains ALL TYPES in the assembly, correct data is a dto living in the Project.Dtos namespace. But we have two failure conditions. The first is if a Dto is outside the Project.Dtos namespace, the convention fails. The second is if a non-dto class lives inside the Project.Dtos namespace. ## How to use a symmetric convention [block:code] { "codes": [ { "code": "var types = new Types(\"Types in MyProject\")\n{\n TypesToVerify = typeof(MyDto).Assembly.GetTypes()\n};\nvar convention = new ClassTypeHasSpecificNamespace(\n classIsApplicable: t => t.Name.EndsWith(\"Dto\"), \n namespaceToCheck : \"MyProject.Dtos\", \n classType: \"Dto\");\nConvention.Is(convention, types);", "language": "csharp" } ] } [/block] As you can see, symmetric conventions are no different to enforce