{"id":3485,"date":"2012-10-10T11:08:27","date_gmt":"2012-10-10T09:08:27","guid":{"rendered":"http:\/\/www.limilabs.com\/blog\/?p=3485"},"modified":"2012-10-10T11:08:27","modified_gmt":"2012-10-10T09:08:27","slug":"testing-test-assembly","status":"publish","type":"post","link":"https:\/\/www.limilabs.com\/blog\/testing-test-assembly","title":{"rendered":"Testing test assembly"},"content":{"rendered":"<p>I recently discovered that almost 50 unit tests don&#8217;t run for <a href=\"\/mail\">Mail.dll email library<\/a> test suite. <\/p>\n<p>Mail.dll uses NUnit as its unit testing framework, and with over  <strong>3000 tests<\/strong> it&#8217;s hard to spot that some are missing. The problem was that most (of those 50 that didn&#8217;t run) test methods where missing <em>TestAttribute<\/em> and 2 test classes were missing <em>TestFixtureAttribute<\/em>.<\/p>\n<p>I decided that it&#8217;s time to create 2 unit tests that guard my unit test assembly.<\/p>\n<p>First one checks if all public methods, in classes marked with <em>TestFixtureAttribute<\/em>, have <em>TestAttribute<\/em> applied.<\/p>\n<p>Of curse we are using reflection for that. <\/p>\n<p>It would be nice if we could just double click on the trace output and be taken, by VisualStudio, to the source file. Unfortunately it&#8217;s not possible, with standard .NET reflection, to get source code file name and line. I decided against using Mono.Cecil for that, especially that with R# it&#8217;s easy enough to navigate to method name.<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\n&#x5B;Test]\r\npublic void Methods_InTestFixtureTypes_HaveTestAttribute()\r\n{\r\n    int count = 0;\r\n    foreach (Type type in this.GetType().Assembly.GetTypes())\r\n    {\r\n        if (Attribute.IsDefined(type, typeof(TestFixtureAttribute)))\r\n        {\r\n            foreach (MethodInfo method in type.GetMethods())\r\n            {\r\n                if (method.IsPublic\r\n                    &amp;&amp; method.IsSpecialName == false\r\n                    &amp;&amp; method.DeclaringType == type\r\n                    &amp;&amp; !Attribute.IsDefined(method, typeof(TearDownAttribute))\r\n                    &amp;&amp; !Attribute.IsDefined(method, typeof(SetUpAttribute))\r\n                    &amp;&amp; !Attribute.IsDefined(method, typeof(TestAttribute))\r\n                    )\r\n                {\r\n                    Trace.WriteLine(type.FullName + &quot;.&quot; + method.Name);\r\n                    count++;\r\n                }\r\n            }\r\n        }\r\n    }\r\n    Assert.AreEqual(0, count);\r\n}\r\n<\/pre>\n<p>Second test checks if all public classes, that have at least one method marked with <em>TestAttribute<\/em>, have <em>TestFixtureAttribute<\/em> applied.<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\n&#x5B;Test]\r\npublic void Types_WithTestMethods_HaveTestFixtureAttribute()\r\n{\r\n    int count = 0;\r\n    foreach (Type type in this.GetType().Assembly.GetTypes())\r\n    {\r\n        bool hasAtLeastOneTestMethod = new List&lt;MethodInfo&gt;(type.GetMethods()).Find(\r\n            method =&gt; Attribute.IsDefined(method, typeof(TestAttribute))) != null;\r\n\r\n        if (hasAtLeastOneTestMethod\r\n            &amp;&amp; Attribute.IsDefined(type, typeof(TestFixtureAttribute)) == false)\r\n        {\r\n            Trace.WriteLine(type.FullName);\r\n            count++;\r\n        }\r\n    }\r\n    Assert.AreEqual(0, count);\r\n}\r\n<\/pre>\n<p>Some of you might argue that we shouldn&#8217;t be using <em>Trace <\/em> class inside the unit test. <em>StringBuilder<\/em>, <em>WriteLine<\/em> and<br \/>\n<em>Assert.AreEqual(object expected, object actual, string message)<\/em> are your friends in such case.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I recently discovered that almost 50 unit tests don&#8217;t run for Mail.dll email library test suite. Mail.dll uses NUnit as its unit testing framework, and with over 3000 tests it&#8217;s hard to spot that some are missing. The problem was that most (of those 50 that didn&#8217;t run) test methods where missing TestAttribute and 2 [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[6],"tags":[56],"class_list":["post-3485","post","type-post","status-publish","format-standard","hentry","category-programming","tag-unit-testing"],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/www.limilabs.com\/blog\/wp-json\/wp\/v2\/posts\/3485"}],"collection":[{"href":"https:\/\/www.limilabs.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.limilabs.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.limilabs.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.limilabs.com\/blog\/wp-json\/wp\/v2\/comments?post=3485"}],"version-history":[{"count":15,"href":"https:\/\/www.limilabs.com\/blog\/wp-json\/wp\/v2\/posts\/3485\/revisions"}],"predecessor-version":[{"id":3505,"href":"https:\/\/www.limilabs.com\/blog\/wp-json\/wp\/v2\/posts\/3485\/revisions\/3505"}],"wp:attachment":[{"href":"https:\/\/www.limilabs.com\/blog\/wp-json\/wp\/v2\/media?parent=3485"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.limilabs.com\/blog\/wp-json\/wp\/v2\/categories?post=3485"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.limilabs.com\/blog\/wp-json\/wp\/v2\/tags?post=3485"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}