<?xml version="1.0" encoding="utf-8"?><rss version="2.0"><channel><title>Home</title><link>http://www.chriswagnerblog.com:80/</link><description>Home</description><item><title>Reorganizing the Visual Studio 2010 Solution Explorer Context Menu</title><link>http://www.chriswagnerblog.com:80/Reorganizing-the-Visual-Studio-2010-Solution-Explorer-Context-Menu</link><description>&lt;p&gt;&lt;img src="/media/large%20menu.png" style="margin: 16px;" align="right" height="306" width="200" alt="Long menu is loooong" /&gt;If you work extensively with Visual Studio, it's entirely possible that you've ended up with a solution explorer context menu that is strikingly similar to the one you see at the right. In fact, I have seen many substantially worse context menus in real-world scenarios. Options just tend to pile up as you approach different projects, each with different tooling requirements that can eventually culminate in a menu that is extremely difficult to browse.&lt;/p&gt;
&lt;p&gt;Luckily, Visual Studio 2010 does, in fact, let you reorganize the menu as you see fit. Since I found the functionality a little bit unintuitive, I am going to blog about it, just in case somebody else did as well. This would actually make me feel better, since I feel a little bit silly -- it was always pretty easy to find the equivalent functionality in Office...&lt;/p&gt;
&lt;p&gt;As you might expect, the first stop is &lt;strong&gt;Tools&lt;/strong&gt; -&amp;gt; &lt;strong&gt;Customize&lt;/strong&gt;&lt;strong&gt;...&lt;/strong&gt;, followed by a quick jog to the &lt;strong&gt;Commands&lt;/strong&gt; tab. From the Context Menu dropdown, you can choose which context menu you'd like to edit. An "|" indicates a submenu, which we'll get to in a moment. In my experience, the one that is most likely to become huge and unwieldy is "Project and Solution Context Menus | Project." Rearranging, adding, and removing menu items are easy enough -- and it turns out that creating a new menu is also easy. Just not quite so obvious.&lt;/p&gt;
&lt;p&gt;To create the new submenu, click the &lt;strong&gt;Add New Menu&lt;/strong&gt; button. It will be created at the current cursor position. Give this new menu a name by clicking the &lt;strong&gt;Modify Selection&lt;/strong&gt; button.&amp;nbsp;Close the dialog. This unfortunately seems to be necessary -- open the Tools -&amp;gt; Customize dialog again, and return to the Commands tab. It'll be the same as before, except there will be a new option in the context menu corresponding to what you named the new menu. For example, if you created an "Ostriches" submenu in "Project and Solution Context Menus | Project", you can select "Project and Solution Context Menus | Project | Ostrich" &amp;nbsp;from the combo box to edit the items available in that submenu.&lt;/p&gt;</description><pubDate>Thu, 19 May 2011 03:45:03 GMT</pubDate><guid isPermaLink="true">http://www.chriswagnerblog.com:80/Reorganizing-the-Visual-Studio-2010-Solution-Explorer-Context-Menu</guid></item><item><title>Nitriq Does More Than Just LINQ</title><link>http://www.chriswagnerblog.com:80/Nitriq-Does-More-Than-Just-LINQ</link><description>&lt;p&gt;Here at &lt;a href="http://www.nimblepros.com/"&gt;NimblePros&lt;/a&gt;, we&amp;rsquo;ve recently begun working to release a new &lt;strong&gt;code analysis&lt;/strong&gt; tool called &lt;a href="http://nimblepros.com/products/nitriq.aspx"&gt;Nitriq&lt;/a&gt;. Because I wasn&amp;rsquo;t personally involved in its development, my goal was to attempt to break it, as I am wont to do with any new tool. I was pleased to find that it was actually very difficult to throw an impossible query at it -- at the risk of sounding clich&amp;eacute;d, &amp;ldquo;simple queries were easy, and difficult queries were possible.&amp;rdquo; There are many different code analysis tools, but what we believe differentiates Nitriq is how customizable it is. You aren&amp;rsquo;t limited to customizing existing rules, and you don&amp;rsquo;t need to learn any kind of &amp;ldquo;special&amp;rdquo; language to create new rules &amp;ndash; they&amp;rsquo;re all written in C#, just like your project.&lt;/p&gt;
&lt;p&gt;Nitriq allows you to perform queries on the properties of types, methods, and more, and to issue warnings based on your findings. It&amp;rsquo;s easy to find methods that require too many parameters, or types that have an inordinate number of dependencies. These queries are normally written as LINQ, because it&amp;rsquo;s simple to read and write, and idiomatic to a C# developer. Most of the time, you&amp;rsquo;ll find that LINQ alone can express your rules quite elegantly, but when you start to need more complex queries, you won&amp;rsquo;t find yourself out on the street.&lt;/p&gt;
&lt;p&gt;Nitriq holds its own as your queries get more complicated. Because you&amp;rsquo;re almost always writing LINQ, it&amp;rsquo;s easy to forget that you aren&amp;rsquo;t limited to it when the task at hand requires bigger guns -- you&amp;rsquo;re really writing an honest-to-goodness C# method, and anything that is valid within method scope in a &amp;lsquo;real&amp;rsquo; project can be done in Nitriq as well, because &lt;strong&gt;Nitriq rules &lt;em&gt;are &lt;/em&gt;methods&lt;/strong&gt;. This means that you can split your queries into &lt;strong&gt;multiple steps to improve readability&lt;/strong&gt;, or &lt;strong&gt;extract methods to simplify queries&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;You can&amp;rsquo;t define a method within a method in C#, but you &lt;em&gt;can&lt;/em&gt; define a delegate, and quite easily &amp;ndash; really, the only &amp;lsquo;trick&amp;rsquo; is that we need to specify the types that are accepted and returned. Types that you&amp;rsquo;re likely to care about in Nitriq begin with Bf &amp;ndash; &lt;strong&gt;BfMethod&lt;/strong&gt;, &lt;strong&gt;BfType&lt;/strong&gt;, and &lt;strong&gt;BfNamespace&lt;/strong&gt;,&lt;strong&gt; &lt;/strong&gt;for example. As a quick first example, let&amp;rsquo;s extract a simple delegate. We want to get all public methods that are in the core assembly and which are not constructors, operators, or properties.&lt;/p&gt;
&lt;pre class="brush:csharp"&gt;Func&amp;lt;BfMethod, bool&amp;gt; isRegularMethod =
    method =&amp;gt; !(method.IsConstructor || method.IsStaticConstructor ||
    method.IsPropertyGetter || method.IsPropertySetter || method.IsOperator);

var results = Methods.Where(m =&amp;gt; m.Type.IsInCoreAssembly)
    .Where(m =&amp;gt; m.IsPublic)
    .Where(isRegularMethod);&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;It would also be easy to embed the last part of the query, but extracting parts of a query can be convenient and improve readability if they occur in multiple locations in your query, or, like in this case, the expression is very long. There are also cases where using this method will allow you to express rules that would be difficult or impossible to express if you were limited to a single LINQ expression.&lt;/p&gt;
&lt;p&gt;For a slightly more complex example: let&amp;rsquo;s say that you&amp;rsquo;ve inherited the source of a large, egg-related library with an base class called, appropriately, &lt;tt&gt;Egg&lt;/tt&gt;. There is a naming convention that the names of all of &lt;tt&gt;Egg&lt;/tt&gt;&amp;rsquo;s overly-specific derived types must be suffixed with &amp;ldquo;Egg.&amp;rdquo; Not all eggs directly inherit from &lt;tt&gt;Egg&lt;/tt&gt;, though: you have many types of &lt;tt&gt;BirdEgg&lt;/tt&gt;, many types of &lt;tt&gt;LizardEgg&lt;/tt&gt;, and even a couple of &lt;tt&gt;MammalEggs&lt;/tt&gt;, thanks to our friends the &lt;a href="http://en.wikipedia.org/wiki/Monotreme"&gt;monotremes&lt;/a&gt;. Furthermore, we can&amp;rsquo;t assume anything about the depth of our inheritance hierarchy &amp;ndash; a &lt;tt&gt;ChickenEgg&lt;/tt&gt; inherits from &lt;tt&gt;BirdEgg&lt;/tt&gt; directly, but an &lt;tt&gt;AracaunaEgg&lt;/tt&gt; is a kind of &lt;tt&gt;ChickenEgg&lt;/tt&gt;. To make matters more difficult, Eggs do not currently implement an interface, so we can&amp;rsquo;t do a &lt;span style="font-family: 'Courier New';" face="Courier New"&gt;type.Interfaces.Any(t =&amp;gt; t.Name == "IEgg")&lt;/span&gt;, and the Egg namespace is polluted with a variety of &lt;tt&gt;Nests&lt;/tt&gt;, so we can&amp;rsquo;t apply our rule to every type within the namespace. You need to find a list of all descendants of Egg &amp;ndash; no matter how indirect &amp;ndash; that do not end with &amp;ldquo;Egg.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;A type&amp;rsquo;s &lt;tt&gt;DerivedTypes&lt;/tt&gt; field includes only its directly derived types, but because we can break the query down, it doesn&amp;rsquo;t have to be difficult to find further derived classes. Using a delegate, we can use recursion, which will make it much easier to express this query.&lt;/p&gt;
&lt;pre class="brush:csharp"&gt;Func&amp;lt;BfType, System.Collections.Generic.IEnumerable&amp;lt;BfType&amp;gt;&amp;gt; allDerivedTypes = null;
allDerivedTypes = delegate(BfType type)
{
    if (type.DerivedTypes == null || !type.DerivedTypes.Any())
        return new BfType[]{};
    
    var furtherDerivedTypes = type.DerivedTypes.SelectMany(t =&amp;gt; allDerivedTypes(t));
    return type.DerivedTypes.Union(furtherDerivedTypes);
};

var results = Types
    .Where(t =&amp;gt; t.Name == "Egg")
    .SelectMany(t =&amp;gt; allDerivedTypes(t))
    .Where(t =&amp;gt; !t.Name.Like("Egg$"));

WarnGreaterThan(results, 0);
&lt;/pre&gt;
&lt;p&gt;Our rule can now help us easily find that somebody forgot to put Egg at the end of several classes, causing the humble &lt;tt&gt;Ostrich&lt;/tt&gt; and many other excellent birds to have rather unexpected methods and properties such as &lt;tt&gt;BreakShell()&lt;/tt&gt; and &lt;tt&gt;ShellStrength&lt;/tt&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src="/media/OstrichShell.jpg" longdesc="I am an ostrich, excellent" alt="Ostrich" title="Ostrich" style="border-width: 0px; display: inline;" width="223" align="middle" border="0" height="205" /&gt;&lt;/p&gt;
&lt;p&gt;Nitriq has allowed us to &lt;strong&gt;save time&lt;/strong&gt; by &lt;strong&gt;automating&lt;/strong&gt; a search that would normally be cumbersome and error-prone, even with excellent tools like &lt;a href="http://www.jetbrains.com/resharper/"&gt;ReSharper&lt;/a&gt;. Chances are, your application doesn&amp;rsquo;t have any eggs in it &amp;ndash; but if I can write a rule specifically about eggs, of all things, you can write rules to handle whatever your specific requirements happen to be.&lt;/p&gt;
&lt;p&gt;There are many other things you can do with a code analysis tool like &lt;a href="http://nimblepros.com/products/nitriq.aspx"&gt;Nitriq&lt;/a&gt;, which I plan to blog about occasionally, as do my alphabetically-by-surname-ordered coworkers, &lt;a href="http://www.scottdepouw.com/"&gt;Scott&lt;/a&gt;&amp;nbsp;and&amp;nbsp;&lt;a href="http://www.benheimann.com/"&gt;Ben&lt;/a&gt;. Nitriq isn&amp;rsquo;t quite ready for mass-consumption, but if you&amp;rsquo;re feeling adventurous, and don&amp;rsquo;t mind the occasional hiccup, there&amp;rsquo;s a free &lt;a href="http://nimblepros.com/products/nitriq.aspx"&gt;beta&lt;/a&gt; available.&lt;/p&gt;</description><pubDate>Thu, 19 May 2011 03:43:55 GMT</pubDate><guid isPermaLink="true">http://www.chriswagnerblog.com:80/Nitriq-Does-More-Than-Just-LINQ</guid></item><item><title>Some Simple Nitriqular Tasks</title><link>http://www.chriswagnerblog.com:80/Some-Simple-Nitriqular-Tasks</link><description>&lt;p&gt;Since &lt;a href="http://nimblepros.com/products/nitriq.aspx"&gt;Nitriq&lt;/a&gt; is a new tool, I thought that it might be useful to share a few simple, real-world-style queries that demonstrate what you can expect Nitriq queries to look like.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;This will &lt;strong&gt;filter out automatically generated names &lt;/strong&gt;and&lt;strong&gt; generic type parameters &lt;/strong&gt;from the lists. You can replace Types with Methods as well.&lt;/p&gt;
&lt;pre class="brush:csharp;"&gt;var results = Types.Where(t =&amp;gt; !t.Name.Like("&amp;lt;.*&amp;gt;.__.*") &amp;amp;&amp;amp; t.FullName[0] != '.');&lt;/pre&gt;
&lt;p&gt;Nitriq&amp;rsquo;s simplified regular expression queries make it very easy to find identifier names &amp;ndash; ordinarily, you&amp;rsquo;d have to use a RegEx object, or roll your own extension method to hide those details.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;We can find all &lt;strong&gt;recursive methods&lt;/strong&gt;:&lt;/p&gt;
&lt;pre class="brush:csharp;"&gt;var results = Methods.Where(method =&amp;gt; method.Calls.Contains(method));&lt;/pre&gt;
&lt;p&gt;Normally, you&amp;rsquo;d have to examine individual methods to see whether or not they were recursive, but because Nitriq gives you access to all of the &lt;strong&gt;methods that a method calls&lt;/strong&gt;, we only need to find methods that call themselves and we&amp;rsquo;re done. In one line, we&amp;rsquo;ve found every recursive method. Nitriq also gives access to all of the methods that call a given method via the &lt;tt&gt;CalledBy&lt;/tt&gt; property, and makes it easy to find out where instance variables are set and where their values are used.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;As another example of using the method call information provided by Nitriq, we can find all public methods that are only called within the class in which they are defined:&lt;/p&gt;
&lt;pre class="brush:csharp;"&gt;var results = Methods
    .Where(m =&amp;gt; m.IsPublic &amp;amp;&amp;amp; m.CalledBy.All(m2 =&amp;gt; m.Type.TypeId == m2.Type.TypeId));&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Sometimes even the name of a type can provide us with information about what might be wrong with it. Oftentimes, a method name with a conjunction indicates that the method could be violating the &lt;strong&gt;single responsibility principle&lt;/strong&gt;. This query will find all methods that contain some such &lt;strong&gt;conjunctions&lt;/strong&gt; in PascalCase:&lt;/p&gt;
&lt;pre class="brush:csharp;"&gt;var results = Methods
    .Where(method =&amp;gt; method.Name.Like(".*And.*|.*Then.*|.*Or.*", false));&lt;/pre&gt;
&lt;p&gt;The &amp;lsquo;false&amp;rsquo; we&amp;rsquo;ve passed in makes the query case-sensitive so that methods like &lt;a href="/media/OstrichEgg.png" title="I am an ostrich again?"&gt;&lt;tt&gt;HideHeadInS&lt;em&gt;and()&lt;/em&gt;&lt;/tt&gt;&lt;/a&gt; don&amp;rsquo;t trigger the rule.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Find all methods that return or take in &lt;tt&gt;&lt;strong&gt;System.Object&lt;/strong&gt;&lt;/tt&gt;:&lt;/p&gt;
&lt;pre class="brush:csharp;"&gt;var objectType = Types.Where(t =&amp;gt; t.FullName == "System.Object").Single();
var results = Methods
    .Where(m =&amp;gt; m.ParameterTypes.Contains(objectType) || m.ReturnType == objectType);&lt;/pre&gt;
&lt;p&gt;C# has excellent type-safety, but inappropriate use of &lt;tt&gt;object&lt;/tt&gt; negates many of these benefits. It often indicates a place where another approach, such as generics, should be preferred.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Find &lt;strong&gt;excessively commented methods&lt;/strong&gt;:&lt;/p&gt;
&lt;pre class="brush:csharp;"&gt;var results = Methods.Where(m =&amp;gt; m.PercentComment &amp;gt; 10);&lt;/pre&gt;
&lt;p&gt;Depending on how your religion treats comments, you may want to tweak this value, but methods with more than a few lines of comments tend to indicate either a case where an old implementation has been commented out as a &lt;a href="http://www.markhneedham.com/blog/2009/01/17/the-danger-of-commenting-out-code/"&gt;poor substitute for version control&lt;/a&gt;, or an futile attempt to shoehorn clarity into a &lt;a href="http://brendan.enrick.com/blog/when-should-you-comment-you-code/"&gt;muddled method&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;As &lt;a href="http://scottdepouw.com"&gt;Scott&lt;/a&gt; recently discussed in his amazingly alliterative post, &lt;a href="http://scottdepouw.com/blog/copious-cyclomatic-complexity-creates-confusing-code/"&gt;Copious Cyclomatic Complexity Creates Confusing Code&lt;/a&gt;, excessive cyclomatic complexity can be strongly indicative of &lt;strong&gt;potential faults&lt;/strong&gt;. This little snippet gives you the &lt;strong&gt;average cyclomatic complexity&lt;/strong&gt; of all of the methods in each type.&lt;/p&gt;
&lt;pre class="brush:csharp;"&gt;Func&amp;lt;BfType, System.Collections.Generic.IEnumerable&amp;lt;BfMethod&amp;gt;&amp;gt;
    cyclomaticMethods = t =&amp;gt; t.Methods.Where(m =&amp;gt; m.Cyclomatic &amp;gt; 0);

var results = Types.Select(
    t =&amp;gt; new {
        TypeId = t.TypeId,
        TypeName = t.Name,
        AverageCyclomatic = 
            cyclomaticMethods(t).Any() ? 
            cyclomaticMethods(t).Average(m =&amp;gt; m.Cyclomatic) : 0
    }
);&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;For today&amp;rsquo;s final example, we can see a few other neat features while we &lt;strong&gt;find circular dependencies&lt;/strong&gt;:&lt;/p&gt;
&lt;pre class="brush:csharp;"&gt;var inTypePairs = Types
    .SelectMany(t =&amp;gt; t.InTypes.Select(
        u =&amp;gt; new { TypeId = t.TypeId, TypeName = t.FullName, DependentOn = u.FullName })
    )
    .Where(t =&amp;gt; t.TypeName != t.DependentOn);
var reverseTypePairs = Types
    .SelectMany(t =&amp;gt; t.InTypes.Select(
        u =&amp;gt; new { TypeId = u.TypeId, TypeName = u.FullName, DependentOn = t.FullName })
    );
var results = inTypePairs.Intersect(reverseTypePairs);&lt;/pre&gt;
&lt;p&gt;Nitriq exposes the types that a type depends on as &lt;tt&gt;InTypes&lt;/tt&gt;, and the types that depend on a type as &lt;tt&gt;OutTypes&lt;/tt&gt;. This allows us to see a list of all types such that have circular dependencies, which, although allowed within a namespace, might not be ideal, especially if the two types really belong in different modules. This query selects a list of pairs (Type, InType) for each of a Type&amp;rsquo;s InTypes. It also selects the reverse pairs (InType, Type), and performs an intersection between the two list.        &lt;br /&gt; &lt;br /&gt; &lt;a href="media/WindowsLiveWriter/SomeSimpleNitriqularTasks_D975/Dependencies.png"&gt;&lt;img style="border: 0px none; margin-left: 10px; display: inline;" title="Dependencies" alt="Dependencies" src="/media/WindowsLiveWriter/SomeSimpleNitriqularTasks_D975/Dependencies_thumb.png" width="265" align="right" border="0" height="115" /&gt;&lt;/a&gt; This query is also doing something different than all of the previous queries: here, we&amp;rsquo;re &lt;strong&gt;selecting an anonymous type&lt;/strong&gt;, instead of one of the Bf- types &amp;lsquo;native&amp;rsquo; to Nitriq. Nitriq is smart enough to show the fields of an anonymous type with the &lt;strong&gt;appropriate column headings&lt;/strong&gt;, as you can see to the right.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;I haven&amp;rsquo;t really delved deeply into what you can do with &lt;a href="http://nimblepros.com/products/nitriq.aspx"&gt;Nitriq&lt;/a&gt; here, but I hope that I&amp;rsquo;ve at least demonstrated how easy it is to accomplish many real-world queries.&lt;/p&gt;</description><pubDate>Thu, 19 May 2011 03:42:31 GMT</pubDate><guid isPermaLink="true">http://www.chriswagnerblog.com:80/Some-Simple-Nitriqular-Tasks</guid></item><item><title>Code Coverage Analysis with PartCover</title><link>http://www.chriswagnerblog.com:80/Code-Coverage-Analysis-with-PartCover</link><description>&lt;p&gt;In this article, I give a brief tutorial on how to use &lt;a href="http://sourceforge.net/projects/partcover/"&gt;PartCover&lt;/a&gt;, a free, open-source &lt;a href="http://en.wikipedia.org/wiki/Code_coverage"&gt;code coverage&lt;/a&gt; analysis tool for .NET developers. Code coverage can help you to determine whether or not your software has been adequately unit tested, and is particularly useful in highlighting edge cases that may have been overlooked.&lt;/p&gt;
&lt;p&gt;As far as free code coverage tools for .NET developers are concerned, neither the &lt;a href="http://www.ncover.com/download/community"&gt;NCover Community Edition&lt;/a&gt; nor PartCover are 64-bit compatible out of the box yet, which is quite a shame, since I think most developers have moved on to 64-bit boxen by now. Luckily, the &lt;a href="http://stackoverflow.com/questions/256287/how-do-i-run-partcover-in-x64-windows"&gt;solution&lt;/a&gt; was readily available on the venerable &lt;a href="http://www.stackoverflow.com/"&gt;StackOverflow&lt;/a&gt;. Note that if you&amp;rsquo;re running Windows 7, there is a a minor additional step: you will have to launch PowerShell or cmd as an administrator, because otherwise Program Files is read-only. Alternatively, you can download this version of &lt;a href="http://chriswagnerblog.com/files/uploads/PartCover2.3-32bit.zip"&gt;PartCover.exe&lt;/a&gt; that has already been converted and place it in your installation directory.&lt;/p&gt;
&lt;h3&gt;Running the Analysis from the GUI&lt;/h3&gt;
&lt;p&gt;Before you can view the results of your analysis, you&amp;rsquo;ll have to run it. It&amp;rsquo;s not exactly immediately clear how to set up the analysis from within the PartCover Browser, so here&amp;rsquo;s a quick rundown of the dialog you&amp;rsquo;ll see when you do a File &amp;ndash;&amp;gt; Run Target&amp;hellip;&lt;/p&gt;
&lt;p&gt;&lt;a href="/media/WindowsLiveWriter/CodeCoverageAnalysiswithPartCover_14549/image_2.png"&gt;&lt;img style="display: inline; margin-left: 0px; margin-right: 0px; border-width: 0px;" title="image" border="0" alt="image" align="right" width="342" height="201" src="/media/WindowsLiveWriter/CodeCoverageAnalysiswithPartCover_14549/image_thumb.png" /&gt;&lt;/a&gt;The &lt;strong&gt;Executable File&lt;/strong&gt; should be set to the &lt;strong&gt;32-bit&lt;/strong&gt; version of your &lt;strong&gt;unit testing framework&amp;rsquo;s runner&lt;/strong&gt; &amp;ndash; in my case, that&amp;rsquo;s &lt;tt&gt;nunit-console-x86.exe&lt;/tt&gt;. It should &lt;em&gt;not&lt;/em&gt; be the path to your project&amp;rsquo;s binary.&lt;/p&gt;
&lt;p&gt;Set the &lt;strong&gt;Working Directory &lt;/strong&gt;to your unit test project&amp;rsquo;s &lt;tt&gt;bin&lt;/tt&gt; folder. &lt;strong&gt;Working Arguments &lt;/strong&gt;is where you&amp;rsquo;ll finally specify the &lt;strong&gt;path to your unit test project&amp;rsquo;s binary &lt;/strong&gt;&amp;ndash; in my case, this is &lt;tt&gt;Debug\SuffixArrayTests.dll&lt;/tt&gt;.&lt;/p&gt;
&lt;p&gt;Last, you need to specify the &lt;strong&gt;rules&lt;/strong&gt; for what to run. Each rule takes the form of &lt;tt&gt;+&lt;var&gt;filter&lt;/var&gt;&lt;/tt&gt; or &lt;tt&gt;&amp;ndash;&lt;var&gt;filter&lt;/var&gt;&lt;/tt&gt;, where &lt;tt&gt;+&lt;var&gt;filter&lt;/var&gt;&lt;/tt&gt; causes a class to be included in the coverage report, and &lt;tt&gt;&amp;ndash;&lt;var&gt;filter&lt;/var&gt;&lt;/tt&gt; causes it to be excluded even if a previous rule would have included it. Filters, in turn, take the form &lt;tt&gt;[&lt;em&gt;Namespace&lt;/em&gt;]&lt;em&gt;Class&lt;/em&gt;&lt;/tt&gt;, with support for wildcards. In the case depicted here, coverage analysis will be provided for all classes in the SuffixArray namespace, and all classes in the SuffixArrayTests namespace.&lt;/p&gt;
&lt;p&gt;You can save these settings for later, but remember that the Save / Load buttons here are &lt;strong&gt;not&lt;/strong&gt; the same as the Save/Open report buttons in the main window, which are for the &lt;em&gt;results&lt;/em&gt; of the coverage analysis, not for these settings. That is to say, if you want to load your target settings again later, you&amp;rsquo;ll need to do so within this window.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3&gt;Running the Analysis from the Console&lt;/h3&gt;
&lt;p&gt;You can also run the coverage analysis from the command line or with a batch file like this one. This is useful if you&amp;rsquo;d like to run the same coverage report frequently, or if you&amp;rsquo;d like the analysis to be performed as part of your continuous integration.&lt;/p&gt;
&lt;pre class="brush:bash;"&gt;set partcover="C:\Program Files (x86)\Gubka Bob\PartCover .NET 2.3\partcover.exe"
set nunit="C:\Program Files (x86)\NUnit 2.5.3\bin\net-2.0\nunit-console-x86.exe"
set tests="Debug\YourTests.dll"
%partcover% --target %nunit% --target-args %tests% --include [*]* --output PartCoverResults.xml&lt;/pre&gt;
&lt;p&gt;Once your coverage report has been generated, you can open it in the PartCover Browser exactly as if it had been created from within the GUI.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3&gt;What Your Coverage Is Telling You&lt;/h3&gt;
&lt;p&gt;Before you do anything else, enable &amp;ldquo;&lt;strong&gt;View Coverage Details&lt;/strong&gt;.&amp;rdquo; Frankly, I&amp;rsquo;m not sure why this isn&amp;rsquo;t enabled by default, because it&amp;rsquo;s what reveals most of the information you&amp;rsquo;re interested in.&lt;/p&gt;
&lt;p&gt;&lt;img style="display: inline; border-width: 0px;" title="image" border="0" alt="image" width="215" height="88" src="/media/WindowsLiveWriter/CodeCoverageAnalysiswithPartCover_14549/image_5.png" /&gt;&lt;/p&gt;
&lt;p&gt;The pane to the left shows you the structure of your code, as well as how much of the code was reached during execution. Code that is &lt;strong&gt;reached&lt;/strong&gt; is &lt;span style="background-color: #c8fadc;"&gt;green&lt;/span&gt;, while code that is &lt;strong&gt;never reached&lt;/strong&gt; is &lt;span style="background-color: #fac8dc;"&gt;red&lt;/span&gt;. If code is not reached, &lt;strong&gt;a unit test is probably missing&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href="/media/WindowsLiveWriter/CodeCoverageAnalysiswithPartCover_14549/image_7.png"&gt;&lt;img style="display: inline; border-width: 0px;" title="image" border="0" alt="image" width="418" height="280" src="/media/WindowsLiveWriter/CodeCoverageAnalysiswithPartCover_14549/image_thumb_2.png" /&gt;&lt;/a&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Essentially, unreached code means that there is a path of execution that is not hit by any of your unit tests. This doesn&amp;rsquo;t necessarily mean that you&amp;rsquo;re missing a unit test &amp;ndash; there is some grey area &amp;ndash; but it is definitely a warning light. Even if you&amp;rsquo;re confident that the code works, it&amp;rsquo;s worth remembering that unit tests are one of the few kinds of &lt;strong&gt;documentation&lt;/strong&gt; capable of &lt;a href="http://www.agilestl.com/Articles/DoubleDuty.pdf"&gt;yelling at you&lt;/a&gt; when they&amp;rsquo;ve become outdated or inaccurate.&lt;/p&gt;
&lt;h3&gt;What Your Coverage Is Not Telling You&lt;/h3&gt;
&lt;p&gt;Remember that a code coverage analysis tool can &lt;strong&gt;only &lt;/strong&gt;analyze the coverage of your unit tests in terms of &lt;strong&gt;how many paths through your code get exercised&lt;/strong&gt;. It can&amp;rsquo;t tell you if you&amp;rsquo;re exercising these paths properly, or whether you are checking for meaningful conditions.&lt;/p&gt;
&lt;p&gt;Another case where your coverage tool cannot help you is when your unit tests are &lt;strong&gt;conflated&lt;/strong&gt;. In my example, there is a SuffixArray class and a SuffixComparer class. In this example, I did not even load the unit tests for the latter class, but it&amp;rsquo;s still considered to have 100% coverage. This is because the SuffixComparer&amp;rsquo;s sole method has only one execution path, and it is used by SuffixArray methods which &lt;em&gt;are&lt;/em&gt; tested, despite not having been tested itself. That&amp;rsquo;s not to say that code coverage analysis is useless in this case, though &amp;ndash; if you&amp;rsquo;re like me, &lt;strong&gt;unexpectedly covered code&lt;/strong&gt; can also help you realize when you&amp;rsquo;ve forgotten a unit test. I&amp;rsquo;ll be honest with you: although I&amp;rsquo;ve fixed it now, when I first started writing this article, I didn&amp;rsquo;t forget to &lt;em&gt;load &lt;/em&gt;the tests for SuffixComparer -- I forgot to &lt;em&gt;write &lt;/em&gt;them. As I looked at the results, it jumped out at me that SuffixComparer was &amp;ldquo;covered&amp;rdquo; even though I had failed to write tests &amp;ndash; and having noticed this, I went back and created the missing tests. Even when code coverage does notice your failures, it may help you to notice them yourself.&lt;/p&gt;</description><pubDate>Thu, 19 May 2011 03:41:19 GMT</pubDate><guid isPermaLink="true">http://www.chriswagnerblog.com:80/Code-Coverage-Analysis-with-PartCover</guid></item><item><title>A funny thing happened on the way to the topic</title><link>http://www.chriswagnerblog.com:80/A-funny-thing-happened-on-the-way-to-the-topic</link><description>&lt;p&gt;&amp;nbsp;After no small amount of prodding, poking, and piddling about, and with only eleven months to spare*, I have now joined the current decade with a &lt;em&gt;blog of my very own&lt;/em&gt;, where I can post my thoughts and musings about software development without bringing harm to the internet community at large. Although it may be too much to hope that my posts will be insightful, I certainly hope that they will at least be informative. Except for this one. This one is a lost cause, as are all introductory posts.&lt;/p&gt;
&lt;p&gt;As for who this Chris Wagner is, I work as a part-time developer at &lt;a href="http://www.nimblepros.com"&gt;Nimble Software Professionals&lt;/a&gt;, a software consultancy in perennially&amp;nbsp;sunny Hudson, OH, while also working toward an M.S. in Computer Science at the nearby Kent State University. I genuinely enjoy my work and my work environment -- I consider myself very fortunate to be in this position.&lt;/p&gt;
&lt;p&gt;At any rate, I aspire to make my first real post at some point in the near future. I also aspire to be be more coherent at that time, but I do not want to set the bar so high so soon.&lt;/p&gt;
&lt;p style="font-size: smaller;"&gt;* Or a few negative months, if you are such a real coder that you feel that the common era should zero-indexed, just like an array.&lt;/p&gt;</description><pubDate>Mon, 16 May 2011 19:03:06 GMT</pubDate><guid isPermaLink="true">http://www.chriswagnerblog.com:80/A-funny-thing-happened-on-the-way-to-the-topic</guid></item><item><title>Caps Lock Me Up</title><link>http://www.chriswagnerblog.com:80/Caps-Lock-Me-Up</link><description>&lt;p&gt;When is the last time you voluntarily pressed Caps Lock for its intended purpose? When was the last time &lt;em&gt;that&lt;/em&gt; last time wasn&amp;rsquo;t meant as an ironic mocking of the key&amp;rsquo;s intended function? And yet, the key is so easy to reach, nestled in the loving embrace of the fan favorites Shift and Tab. It seems quite unfortunate that such a &lt;strong&gt;useless key&lt;/strong&gt; has such a prime piece of keyboard real-estate.&lt;/p&gt;
&lt;p&gt;Replacing the Caps Lock key is definitely not groundbreaking &amp;ndash; indeed, many archeologists believe that the Caps Lock key is &lt;em&gt;itself&lt;/em&gt; an usurper. Harkening back to the days of yore, many modern developers opt to replace the function of the caps lock key with Control, hearkening back to the ways of their ancestors, who in the early 1640&amp;rsquo;s apparently manufactured keyboards with the Controlle Ceye in that position. For a period in the early 18th century, it was popular to place an additional Back&lt;b&gt;ſ&lt;/b&gt;pace there instead. The Caps Lock key was only seated in its modern-day position beginning in the 1830&amp;rsquo;s, where it has remained a thorn in the side of many coders ever since.&lt;/p&gt;
&lt;p&gt;But what can be done to right the wrongs that history has wrought? Many &lt;a href="http://c2.com/cgi/wiki?RemapCapsLock"&gt;traditionalists&lt;/a&gt; revert the key to its historical mappings. &lt;a href="http://www.xkcd.com/"&gt;Randall Monroe&lt;/a&gt; did something &lt;a href="http://blog.xkcd.com/2007/08/14/mirrorboard-a-one-handed-keyboard-layout-for-the-lazy/"&gt;awesome&lt;/a&gt;, as usual. Both of these are more useful than the Caps Lock key in its native state. Another useful technique is to turn the Billy Mays key into an &lt;strong&gt;additional modifier key&lt;/strong&gt;, allowing you to have &lt;em&gt;even more&lt;/em&gt; &lt;strong&gt;useful shortcut keys&lt;/strong&gt; to barely remember.&lt;/p&gt;
&lt;p&gt;I use a buckling-spring &lt;a href="http://pckeyboards.stores.yahoo.net/customizer.html"&gt;Customer 104&lt;/a&gt; Keyboard, and love it, but I occasionally miss having modern conveniences such as easily keyboard-accessible volume controls. The idea of repurposing Ctrl, Shift, and Alt for global shortcuts makes me nervous, because real programs use these keys. But real programs generally &lt;em&gt;don&amp;rsquo;t&lt;/em&gt; use Caps Lock in their shortcut keys, so there&amp;rsquo;s essentially &lt;strong&gt;no chance of a collision&lt;/strong&gt;, and you are likely to be able to select better mnemonics because you have no competition.&lt;/p&gt;
&lt;p&gt;The tool I use for my Caps Lock adventure is &lt;a href="http://www.autohotkey.com/download/"&gt;AutoHotkey&lt;/a&gt;. Install the program, then edit your global script. Disabling Caps Lock in the conventional sense is as easy as &lt;tt&gt;SetCapsLockState AlwaysOff&lt;/tt&gt;, but CapsLock will still function in your own aliases. Simply remapping keys is trivial, and fairly complex things are easily possible in the script as well &amp;ndash; an excellent place to start looking is Lifehacker&amp;rsquo;s extensive &lt;a href="http://lifehacker.com/tag/autohotkey/"&gt;AutoHotkey directory&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Among other changes, I&amp;rsquo;ve mapped CapsLock+Up/Down to volume controls, CapsLock+PageUp/PageDn to the media next/previous, and CapsLock+Home is Pause/Play. These combinations are both extremely easy to reach and extremely unlikely to be used by other programs. You are more likely to have the media keys already, but you get the drift &amp;ndash; there is a large number of unused key combinations available that you can repurpose for whatever actions would be most beneficial in your daily life. If you&amp;rsquo;re feeling ambitious, script them up to do something smart. You have dozens and dozens of potential shortcut keys waiting to serve, and you don&amp;rsquo;t have to involve six modifier keys or Scroll Lock to avoid trampling over that obscure shortcut that launches HyperTerminal.&lt;/p&gt;</description><pubDate>Mon, 09 May 2011 00:38:18 GMT</pubDate><guid isPermaLink="true">http://www.chriswagnerblog.com:80/Caps-Lock-Me-Up</guid></item></channel></rss>
