<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" gd:etag="W/&quot;AkQFQX0-fip7ImA9WxNUEUU.&quot;"><id>tag:blogger.com,1999:blog-4775121157402872976</id><updated>2009-11-02T20:58:30.356+02:00</updated><title>From The Software Development Trenches</title><subtitle type="html">Thoughts on software development</subtitle><link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="http://fromthedevtrenches.blogspot.com/feeds/posts/default" /><link rel="alternate" type="text/html" href="http://fromthedevtrenches.blogspot.com/" /><link rel="hub" href="http://pubsubhubbub.appspot.com/" /><author><name>Carel Lotz</name><uri>http://www.blogger.com/profile/13701537592037249529</uri><email>noreply@blogger.com</email></author><generator version="7.00" uri="http://www.blogger.com">Blogger</generator><openSearch:totalResults>9</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><link rel="self" href="http://feeds.feedburner.com/FromTheSoftwareDevelopmentTrenches" type="application/atom+xml" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com" /><entry gd:etag="W/&quot;C04CQ3Y5fCp7ImA9WxNUEU0.&quot;"><id>tag:blogger.com,1999:blog-4775121157402872976.post-6153531594031129556</id><published>2009-11-01T20:59:00.001+02:00</published><updated>2009-11-01T20:59:22.824+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-11-01T20:59:22.824+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="CodeAnalysis" /><category scheme="http://www.blogger.com/atom/ns#" term="TeamWork" /><category scheme="http://www.blogger.com/atom/ns#" term="Metrics" /><title>Code Metrics</title><content type="html">&lt;p&gt;&lt;strong&gt;NOTE: This is a repost of on old post as &lt;a href="http://fromthedevtrenches.blogspot.com/2009/10/migrating-blog-onto-blogger.html"&gt;I am moving&lt;/a&gt; onto the Blogger platform&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;img style="margin: 0px 10px 5px 0px" border="0" alt="image" align="left" src="http://dotnet.org.za/blogs/cjlotz/WindowsLiveWriter/CodeMetrics_70CB/image_3.png" width="136" height="136" /&gt; I've been wanting to do a post about code metrics for quite a while now - mostly to organize my thoughts on the topic as it is something that I want to introduce at work, but also to get some feedback from other people as to if and how they are using metrics to assist them in crafting quality code.&amp;#160; After reading Jeremy Miller's &lt;a href="http://codebetter.com/blogs/jeremy.miller/archive/2006/12/29/Are-Code-Statistics-Useful_3F00_.aspx"&gt;post&lt;/a&gt; on the topic, I thought I might as well take the plunge.&amp;#160;&amp;#160; I'll start by musing over what metrics I found to be useful, then continue with looking at tool support for generating these metrics and finish off with considering when to use these metrics.&lt;/p&gt;  &lt;h2&gt;Metrics&lt;/h2&gt;  &lt;p&gt;I am not going to cover all the different metrics in detail but instead highlight what seems to me to be the most useful metrics and refer to articles/links where other people who have done an excellent job on covering these metrics in detail.&amp;#160; Here are the reference articles that I used:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Robert C. Martin's article on &lt;a href="http://www.objectmentor.com/resources/articles/oodmetrc.pdf"&gt;OO design quality metrics&lt;/a&gt; [1] &lt;/li&gt;    &lt;li&gt;Wikipedia's &lt;a href="http://en.wikipedia.org/wiki/Software_package_metrics"&gt;summary&lt;/a&gt; of these package metrics [2] &lt;/li&gt;    &lt;li&gt;Kirk Knoernschild's excellent &lt;a href="http://www.agilejournal.com/component/option,com_magazine/func,show_article/id,47/"&gt;introductory article&lt;/a&gt; on metrics with sample refactorings included [3] &lt;/li&gt;    &lt;li&gt;Patrick Smacchia's (developer of &lt;a href="http://www.ndepend.com"&gt;NDepend&lt;/a&gt; software) &lt;a href="http://www.ndepend.com/Metrics.aspx"&gt;excellent coverage&lt;/a&gt; on all the types of metrics supported by &lt;a href="http://www.ndepend.com"&gt;NDepend&lt;/a&gt; [4] &lt;/li&gt;    &lt;li&gt;&lt;a href="http://www.sdmetrics.com/DProp.html"&gt;Write up&lt;/a&gt; on the software metrics supported by the &lt;a href="http://www.sdmetrics.com"&gt;Software Design Metrics&lt;/a&gt; software [5] &lt;/li&gt; &lt;/ol&gt;  &lt;h4&gt;&lt;strong&gt;Size metrics&lt;/strong&gt;&lt;/h4&gt;  &lt;p&gt;Size metrics are consistently good indicators of fault-proneness: large methods/classes/packages contain more faults [5].&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;strong&gt;Source Lines Of Code (SLOC) &lt;/strong&gt;measures the amount of lines of code.&amp;#160; To be really useful comment lines and lines that have been broken into multiple lines need to be factored out.&amp;#160; Some people refer to this as the logical LOC vs. the physical LOC.&amp;#160; &lt;/li&gt; &lt;/ul&gt;  &lt;blockquote&gt;   &lt;p&gt;&amp;quot;2 significant advantages of &lt;i&gt;logical&lt;/i&gt; LOC over &lt;i&gt;physical&lt;/i&gt; LOC are:&lt;/p&gt;    &lt;ul&gt;     &lt;li&gt;Coding style doesn’t interfere with &lt;i&gt;logical&lt;/i&gt; LOC. For example the LOC won’t change because a method call is spawn on several lines because of a high number of argument. &lt;/li&gt;      &lt;li&gt;&lt;i&gt;logical&lt;/i&gt; LOC is independent from the language. Values obtained from assemblies written with different languages are comparable and can be summed.&amp;quot; [4] &lt;/li&gt;   &lt;/ul&gt; &lt;/blockquote&gt;  &lt;h4&gt;&lt;strong&gt;Complexity metrics&lt;/strong&gt;&lt;/h4&gt;  &lt;p&gt;There is a direct correlation between complexity and the defect rate of software, so keeping code simple is a solid first step toward lowering the defect rate of software [3].&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;strong&gt;Cyclomatic Complexity (CC)&lt;/strong&gt; measures code complexity by counting the number of linearly independent paths through code. Complex conditionals and boolean operators increase the number of linear paths, resulting in a higher CCN. Methods with a CCN of five or higher are good refactoring candidates to help ensure code remains easy to understand [3] &lt;/li&gt; &lt;/ul&gt;  &lt;h4&gt;&lt;strong&gt;Package metrics&lt;/strong&gt;&lt;/h4&gt;  &lt;h5&gt;Coupling/Dependency metrics&lt;/h5&gt;  &lt;p&gt;Excessive dependencies between packages compromise architecture and design. Complex dependencies inhibit the testability of your system and presents numerous other challenges as presented in [1] and [3].&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;strong&gt;Afferent Coupling (Ca)&lt;/strong&gt; measures the number of types outside a package that depend on types within the package (incoming dependencies). High afferent coupling indicates that the concerned packages have many responsibilities. [1] &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Efferent Coupling (Ce)&lt;/strong&gt; measures the number of types inside a package that depends on types outside of the package (outgoing dependencies). High efferent coupling indicates that the concerned package is dependant. [1] &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;It goes to reason that:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;em&gt;&amp;quot;...afferent and efferent coupling allows you to more effectively evaluate the cost of change and the likelihood of reuse. For instance, maintaining a module with many incoming dependencies is more costly and risky since there is greater risk of impacting other modules, requiring more thorough integration testing. Conversely, a module with many outgoing dependencies is more difficult to test and reuse since all dependent modules are required ... Concrete modules with high afferent coupling will be difficult to change because of the high number of incoming dependencies. Modules with many abstractions are typically more extensible, so long as the dependencies are on the abstract portion of a module.&amp;quot;&lt;/em&gt; [3]&lt;/p&gt; &lt;/blockquote&gt;  &lt;ul&gt;   &lt;li&gt;&lt;strong&gt;Instability (I) &lt;/strong&gt;measures the ratio of efferent coupling (Ce) to total coupling. I = Ce / (Ce + Ca). This metric is an indicator of the package's resilience to change. The range for this metric is 0 to 1, with I=0 indicating a completely stable package and I=1 indicating a completely instable package. [1] &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Abstractness (A) &lt;/strong&gt;measures the ratio of the number of internal abstract types (i.e abstract classes and interfaces) to the number of internal types. The range for this metric is 0 to 1, with A=0 indicating a completely concrete package and A=1 indicating a completely abstract package. [1] &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Distance from main sequence (D) &lt;/strong&gt;measures the perpendicular normalized distance of a package from the idealized line A + I = 1 (called main sequence). This metric is an indicator of the package's balance between abstractness and stability. A package squarely on the main sequence is optimally balanced with respect to its abstractness and stability. Ideal packages are either completely abstract and stable (I=0, A=1) or completely concrete and instable (I=1, A=0). The range for this metric is 0 to 1. [1][4] &lt;/li&gt; &lt;/ul&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;em&gt;&amp;quot;A value approaching zero indicates a module is abstract is relation to its incoming dependencies. As distance approaches one, a module is either concrete with many incoming dependencies or abstract with many outgoing dependencies. The first case represents a lack of design integrity, while the second is useless design.&amp;quot;&lt;/em&gt; [3]&lt;/p&gt; &lt;/blockquote&gt;  &lt;h5&gt;Cohesion metrics&lt;/h5&gt;  &lt;p&gt;&lt;em&gt;&amp;quot;A low cohesive design element has been assigned many unrelated responsibilities. Consequently, the design element is more difficult to understand and therefore also harder to maintain and reuse. Design elements with low cohesion should be considered for refactoring, for instance, by extracting parts of the functionality to separate classes with clearly defined responsibilities.&amp;quot; &lt;/em&gt;[5]&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;strong&gt;Relational Cohesion (H)&lt;/strong&gt; measures the average number of internal relationships per type. Let R be the number of type relationships that are internal to this package (i.e that do not connect to types outside the package). Let N be the number of types within the package. H = (R + 1)/ N. The extra 1 in the formula prevents H=0 when N=1. The relational cohesion represents the relationship that this package has to all its types.&amp;#160; As classes inside an package should be strongly related, the cohesion should be high. On the other hand, too high values may indicate over-coupling. A good range for RelationalCohesion is 1.5 to 4.0. Packages where RelationalCohesion &amp;lt; 1.5 or RelationalCohesion &amp;gt; 4.0 might be problematic. [4] &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Lack of Cohesion of Methods (LCOM)&lt;/strong&gt; The single responsibility principle states that a class should not have more than one reason to change. Such a class is said to be cohesive. A high LCOM value generally pinpoints a poorly cohesive class [4] &lt;/li&gt; &lt;/ul&gt;  &lt;h5&gt;Inheritance metrics&lt;/h5&gt;  &lt;p&gt;&lt;em&gt;&amp;quot;Deep inheritance structures are hypothesized to be more fault-prone. The information needed to fully understand a class situated deep in the inheritance tree is spread over several ancestor classes, thus more difficult to overview.&amp;#160; Similar to high export coupling, a modification to a design element with a large number of descendents can have a large effect on the system.&amp;quot; [5]&lt;/em&gt;&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;strong&gt;Depth of Inheritance Tree (DIT) &lt;/strong&gt;measures the number of base classes for a class or structure.&amp;#160; Types where DIT is higher than 6 might be hard to maintain. However it is not a rule since sometime your classes might inherit from tier classes which have a high value for depth of inheritance. [4] &lt;/li&gt; &lt;/ul&gt;  &lt;h2&gt;Tools&lt;/h2&gt;  &lt;p&gt;When it comes to tools, the Mercedes Benz of .NET code metrics tools from my point of view has to be &lt;a href="http://www.ndepend.com/Default.aspx"&gt;NDepend 2.0&lt;/a&gt;.&amp;#160; &lt;a href="http://www.ndepend.com/Default.aspx"&gt;NDepend 2&lt;/a&gt; provides more than 60 metrics (including all of the metrics listed above) and includes integration into your automated build via support for MSBuild, NAnt and CruiseControl.NET.&amp;#160; Browse to &lt;a href="http://www.ndepend.com/SampleReports/OnNUnit/NDependReport.html"&gt;here&lt;/a&gt; for a sample report and &lt;a href="http://s3.amazonaws.com/NDependOnlineDemos/NDependBuildProcessIntegration_viewlet_swf.html"&gt;here&lt;/a&gt; for a demo on how to integrate it into your build.&amp;#160; &lt;/p&gt;  &lt;p&gt;There is a visual GUI (&lt;a href="http://www.ndepend.com/VisualNDepend.aspx"&gt;VisualNDepend&lt;/a&gt;) that allows you to browse your code structure and evaluate the metrics as well as a &lt;a href="http://www.ndepend.com/NDependConsole.aspx"&gt;console application&lt;/a&gt; that you can generate the metrics with.&amp;#160; Patrick has also created a &lt;strong&gt;&lt;a href="http://www.ndepend.com/CQL.htm"&gt;CQL&lt;/a&gt; (Code Query Language)&lt;/strong&gt; which allows NDepend to consider your code as a database with CQL being the query language with which you can check some assertions on this database. As a consequence, CQL is similar to SQL and supports the typical &lt;b&gt;&lt;em&gt;SELECT TOP FROM WHERE ORDER BY&lt;/em&gt;&lt;/b&gt; patterns. Here is an example of a CQL query:&lt;/p&gt;  &lt;pre&gt;&lt;p&gt;WARN IF Count &amp;gt; 0 IN SELECT METHODS 
WHERE NbILInstructions &amp;gt; 200 ORDER BY NbILInstructions DESC
// METHODS WHERE NbILInstructions &amp;gt; 200 are extremely complex and            
// should be split in smaller methods.
&lt;/p&gt;&lt;/pre&gt;

&lt;p&gt;How cool is this! To quote: &lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;em&gt;&amp;quot;CQL constraints are customisable and typically tied with a particular application. For example, they can allow the specification of customized encapsulation constraints, such as, I want to ensure that this layer will never use this other layer or I want to ensure that this class will never be instantiated outside this particular namespace&lt;/em&gt;.&amp;quot;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;VisualNDepend also provides a &lt;a href="http://www.ndepend.com/VisualNDepend.aspx#CQLEdition"&gt;CQL editor&lt;/a&gt; which supports intellisense and verbose compile error descriptions to make writing CQL queries a lot easier.&amp;#160; Enough said!&amp;#160; Browse to &lt;a href="http://www.ndepend.com/Features.aspx"&gt;here&lt;/a&gt; for a complete overview of the NDepend 2 features. &lt;/p&gt;

&lt;p&gt;Other tools that that you can have a look at include &lt;a href="http://www.campwoodsw.com/sourcemonitor.html"&gt;SourceMonitor&lt;/a&gt;, &lt;a href="http://sourceforge.net/projects/devadvantage"&gt;DevMetrics&lt;/a&gt;, &lt;a href="http://www.sdmetrics.com/"&gt;Software Design Metrics&lt;/a&gt; and &lt;a href="http://www.1bot.com/"&gt;vil&lt;/a&gt; to name a few. vil does not support .NET 2.0 and does not seem to be under active development. DevMetrics, after being open-sourced, seemed to have stagnated with no visible activity on SourceForge. SourceMonitor is actively under development and supports a variety of programming languages. However, it supports only a small subset of the metrics mentioned which does not include support for important metrics like efferent and afferent coupling etc. Software Design Metrics takes a novel approach in that it measures the complexity based on the UML models for the software. This has the advantage of being language independent, but you obviously need to have UML models to run 

  &lt;br /&gt;the analysis. &lt;/p&gt;

&lt;h2&gt;When to use&lt;/h2&gt;

&lt;p&gt;When should one use these metrics? I agree with &lt;a href="http://codebetter.com/blogs/jeremy.miller/archive/2006/12/29/Are-Code-Statistics-Useful_3F00_.aspx"&gt;Jeremy Miller in his post&lt;/a&gt; that the metrics should not replace the visual inspection/QA process and be performed in addition to it. It would be nice to have these metrics at hand to assist in the QA process though. I also agree with &lt;a href="http://softarc.blogspot.com/2006/12/code-metrics-how-useful-are-they.html"&gt;Frank Kelly in his post&lt;/a&gt; that a working system with no severity 1/2 errors and happy end users are more important than getting the right balance of Ca/Ce or whatever metric you are interested in. &lt;/p&gt;

&lt;p&gt;I think I will stick with an approach of identifying a subset of useful metrics and using these as part of an overall process of static code analysis on a regular basis. When I say regular basis I feel it should be part of your &lt;a href="http://fromthedevtrenches.blogspot.com/2009/11/continuous-integration-from-theory-to_01.html"&gt;continuous build process&lt;/a&gt; to prevent people from committing code into your repository that does not satisfy your constraints. With a tool like NDepend you can create your own custom level of acceptance criteria by which the build will fail/succeed and exclude metrics that you feel should not apply to your code base. &lt;/p&gt;

&lt;p&gt;As mentioned, the code metrics should form part of a bigger quality process that includes: &lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Visual inspection/QA via &lt;a href="http://fromthedevtrenches.blogspot.com/2009/11/code-reviews.html"&gt;peer code reviews&lt;/a&gt; (as mentioned having the metrics via a tool like VisualNDepend can greatly assist in the QA) &lt;/li&gt;

  &lt;li&gt;Automated code standards check (I prefer &lt;a href="http://fromthedevtrenches.blogspot.com/2009/11/fxcop.html"&gt;FxCop&lt;/a&gt;) &lt;/li&gt;

  &lt;li&gt;Automated code metric check (NDepend seems like the tool to use here) &lt;/li&gt;

  &lt;li&gt;Automated code coverage statistics (I prefer NCover and NCoverExplorer) &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Well, that basically covers my thoughts on the topic for now. I'm interested to know how many people are actively using metrics and what metrics they are using. I'd also like to know what processes or tools people are using to generate these metrics on their code. Let me know what's working for you in your environment.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4775121157402872976-6153531594031129556?l=fromthedevtrenches.blogspot.com'/&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/FromTheSoftwareDevelopmentTrenches/~4/ym_YsOinL00" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://fromthedevtrenches.blogspot.com/feeds/6153531594031129556/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://fromthedevtrenches.blogspot.com/2009/11/code-metrics.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4775121157402872976/posts/default/6153531594031129556?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4775121157402872976/posts/default/6153531594031129556?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/FromTheSoftwareDevelopmentTrenches/~3/ym_YsOinL00/code-metrics.html" title="Code Metrics" /><author><name>Carel Lotz</name><uri>http://www.blogger.com/profile/13701537592037249529</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="05471999821481181728" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://fromthedevtrenches.blogspot.com/2009/11/code-metrics.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C08MRH48cCp7ImA9WxNUEU0.&quot;"><id>tag:blogger.com,1999:blog-4775121157402872976.post-3315957687821968027</id><published>2009-11-01T20:58:00.001+02:00</published><updated>2009-11-01T20:58:05.078+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-11-01T20:58:05.078+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Tools" /><category scheme="http://www.blogger.com/atom/ns#" term="TeamWork" /><category scheme="http://www.blogger.com/atom/ns#" term="Metrics" /><title>Code Reviews</title><content type="html">&lt;p&gt;&lt;strong&gt;NOTE: This is a repost of on old post as &lt;a href="http://fromthedevtrenches.blogspot.com/2009/10/migrating-blog-onto-blogger.html"&gt;I am moving&lt;/a&gt; onto the Blogger platform&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://dotnet.org.za/blogs/cjlotz/WindowsLiveWriter/CodeReviews_7854/image_2.png"&gt;&lt;img style="margin: 0px 10px 5px 0px" border="0" alt="image" align="left" src="http://dotnet.org.za/blogs/cjlotz/WindowsLiveWriter/CodeReviews_7854/image_thumb.png" width="129" height="144" /&gt;&lt;/a&gt; Code reviews are a proven, effective way to minimize defects, improve code quality and keep code more maintainable.&amp;#160; It encourages team collaboration and assists with mentoring developers. Yet, not many projects employ code reviews as a regular part of their development process. Why is this?&amp;#160; Programmer egos and the hassles of packaging source code for review are often sited as some reasons for not doing code reviews. &lt;/p&gt;  &lt;p&gt;I felt that code reviews should form part of a good code quality control process that includes: &lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Visual inspection/QA via peer code reviews &lt;/li&gt;    &lt;li&gt;Automated code standards check (I prefer &lt;a href="http://blogs.msdn.com/fxcop/"&gt;FxCop&lt;/a&gt;) &lt;/li&gt;    &lt;li&gt;Automated code metrics check (I prefer &lt;a href="http://www.ndepend.com/"&gt;NDepend&lt;/a&gt;) &lt;/li&gt;    &lt;li&gt;Automated code coverage statistics (I prefer &lt;a href="http://ncover.org/site/"&gt;NCover&lt;/a&gt; and &lt;a href="http://www.kiwidude.com/dotnet/DownloadPage.html"&gt;NCoverExplorer&lt;/a&gt;) &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;In this post I will spend some time looking at code reviews.&amp;#160; I'll start by considering different styles of code review and some code review metrics. I'll then move on to some thoughts on review frequencies and best practices for peer code review.&amp;#160; I'll finish off by considering some tools that can assist with the code review process itself. &lt;/p&gt;  &lt;h4&gt;References&lt;/h4&gt;  &lt;p&gt;I used the following books and articles to organize my thoughts on the topic: &lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;&lt;a href="http://www.smartbear.com/"&gt;Smart Bear Software's&lt;/a&gt; free, excellent book &lt;em&gt;&lt;a href="http://codereviewbook.com/"&gt;Best Kept Secrets of Peer Code Review&lt;/a&gt;&lt;/em&gt;. [Cohen01] &lt;/li&gt;    &lt;li&gt;&lt;a href="http://www.smartbear.com/"&gt;Smart Bear Software's&lt;/a&gt; whitepaper on &lt;a href="http://www.smartbearsoftware.com/docs/BestPracticesForPeerCodeReview.pdf"&gt;&lt;em&gt;Best Practices for Peer Code Review&lt;/em&gt;&lt;/a&gt;. [Cohen02] &lt;/li&gt;    &lt;li&gt;Robert Bogue's article on &lt;i&gt;&lt;a href="http://www.developer.com/java/other/article.php/3579756"&gt;Effective Code Reviews Without the Pain&lt;/a&gt;&lt;/i&gt;. [Bogue] &lt;/li&gt;    &lt;li&gt;Wikipedia article on &lt;i&gt;&lt;a href="http://en.wikipedia.org/wiki/Code_review"&gt;Code Review&lt;/a&gt;&lt;/i&gt;. [Wikipedia01] &lt;/li&gt;    &lt;li&gt;Wikipedia article on &lt;a href="http://en.wikipedia.org/wiki/Hawthorne_effect"&gt;&lt;em&gt;Hawtorne Effect&lt;/em&gt;&lt;/a&gt;. [Wikipedia02] &lt;/li&gt; &lt;/ol&gt;  &lt;h4&gt;Review Types&lt;/h4&gt;  &lt;p&gt;Code review practices often fall into two main categories: formal code review and lightweight code review. &lt;/p&gt;  &lt;h5&gt;Formal Code Review&lt;/h5&gt;  &lt;p&gt;Formal code review, such as a &lt;a href="http://en.wikipedia.org/wiki/Fagan_inspection"&gt;Fagan inspection&lt;/a&gt;, involves a careful and detailed process with multiple participants and multiple phases. Software developers attend a series of meetings and review code line by line, usually using printed copies of the material. An &lt;b&gt;Introductory meeting&lt;/b&gt; is held where the goals and rules for the review are explained and the review material is handed out. Reviewers inspect the code privately and feedback is given in a subsequent &lt;b&gt;Inspection meeting&lt;/b&gt;. The author fixes any defects identified and the reviewers verify that the defects are fixed in a further &lt;b&gt;Verification meeting&lt;/b&gt;. &lt;/p&gt;  &lt;p&gt;Formal inspections are extremely thorough and effective at finding defects in code but take a long time to complete. &lt;/p&gt;  &lt;h5&gt;Lightweight Code Review&lt;/h5&gt;  &lt;p&gt;Lightweight code review typically requires less overhead than formal code inspections. However, if done properly, it can be equally effective.&amp;#160; Lightweight reviews are often conducted as part of the normal software development process and attempt to improve the cost-benefit factor – providing improved code quality without incurring the overhead of traditional meetings-based inspections [Wikipedia01] [Cohen01]: &lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;strong&gt;Over-the-shoulder review&lt;/strong&gt; – One developer standing over the author’s workstation while the author walks the reviewer through a set of code changes. Simple to execute, these kinds of reviews lend themselves to learning and sharing between developers and gets people interacting with each other instead of hiding behind impersonal e-mail and instant messages. The informality and simplicity unfortunately also leads to some shortcomings such as the process not being enforceable; lack of code review process metrics; does not work for distributed teams; the reviewer being led too hastily through the code and the reviewer not verifying that defects were fixed properly. &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Email pass-around&lt;/strong&gt; – The author or source code management system packages the code changes and sends an e-mail to the reviewers. Relatively simple to execute, these kinds of reviews have the added benefit of working equally well with distributed teams. Other people, like domain experts, can also be brought in to review certain areas or a reviewer may even defer to another reviewer. Some shortcomings include the difficulty to track the various threads of conversation or code changes; lack of code review process metrics and the reviewers not being able to verify that defects were fixed properly. &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Tool-assisted reviews&lt;/strong&gt; – Specialized tools are used in all aspects of the review such as collecting files, transmitting and displaying files, commentary, collecting metrics and controlling the code review process workflow. The major drawback of any tool-assisted review is the cost of buying a commercial offering or the development cost associated with developing an in-house tool. &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Pair Programming&lt;/strong&gt; – Two developers write code together at a single workstation using continuous free-form discussion and review such as is common in &lt;a href="http://en.wikipedia.org/wiki/Extreme_Programming"&gt;Extreme Programming&lt;/a&gt;. Some people argue in favour of the deep insight the reviewer has into the problem at hand, whilst other argue that the closeness is exactly what you do not want from a reviewer as you want a fresh, unbiased opinion. Some people suggest doing both pair programming and a follow-up standard review using a fresh pair of eyes. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;In a current project that I am working on, we are using the over-the-shoulder kind of review process.&amp;#160; Rather than doing no review, we opted for using this approach as the best way to balance the cost-benefit factor of our reviews.&amp;#160; Every submission into the repository needs to be reviewed by a fellow developer.&amp;#160; The details of the reviewer is added to the check-in note to provide the necessary traceability and visibility.&amp;#160; Authors rotate the developers doing the reviews based on the area of the system changed and also to do some cross-skilling.&amp;#160; &lt;/p&gt;  &lt;p&gt;From our experience, we also find the informality of the process as its biggest downfall.&amp;#160; As pressure starts to build, less time is spend on doing reviews and the process sometimes gets perilously close to becoming a mere formality.&lt;/p&gt;  &lt;h4&gt;Review Metrics&lt;/h4&gt;  &lt;p&gt;The following metrics are typically used to measure the effectiveness of a code review process: &lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;b&gt;Inspection Rate&lt;/b&gt;: How fast are we able to review code? Normally measured in kLOC (thousand Lines Of Code) per man-hour. &lt;/li&gt;    &lt;li&gt;&lt;b&gt;Defect Rate&lt;/b&gt;: How fast are we able to find defects? Normally measured in number of defects found per man-hour. &lt;/li&gt;    &lt;li&gt;&lt;b&gt;Defect Density&lt;/b&gt;: How many defects do we find in a given amount of code? Normally measured in number of defects found per kLOC.&amp;#160; The higher the defect density, the more defects are being identified which usually implies a more effective review process. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;This begs the question, what are good values for these metrics?&amp;#160; [Cohen01] uses two examples to illustrate the difficulties with evaluating these metrics:&amp;#160; &lt;/p&gt;  &lt;p&gt;In Example A a few lines of code to a mission critical module are evaluated by 3 reviewers to absolutely ensure that no defects are introduced.&amp;#160; The review results in a high defect density (say 4 defects in a few lines), slow inspection rate and a defect rate of 1 defect per hour.&amp;#160; In Example B changes made to a GUI dialog box results in 120&amp;#160; lines of changed code, of which some of the code was generated by the GUI designer.&amp;#160; One reviewer is assigned to verify the changes and the reviewer chooses to ignore the designer generated code and only evaluates the code behind the GUI elements added.&amp;#160; This results in a low defect density (say 1 bug in 120 lines), fast inspection rate (say 30 minutes) and a defect rate of 2 defects per hour.&lt;/p&gt;  &lt;p&gt;As evident, the metrics are quite different. Should the high defect density rate of Example A reflect badly on the developer? [Cohen01] argues probably not as the high defect density is the result of the multiple reviewers scrutinizing every line of code to make absolutely sure no defects are introduced.&amp;#160; Should the low defect density rate of Example B reflect badly on the reviewer?&amp;#160; [Cohen01] argues probably not as it is difficult to review designer generated code.&amp;#160; As the code is also not mission critical like in Example A, the reviewer was perhaps intentionally tasked to spend less time reviewing the changes.&lt;/p&gt;  &lt;h4&gt;Review Frequency&lt;/h4&gt;  &lt;p&gt;There are no hard and fast rules for determining the frequency of code reviews. The frequency of code reviews can be influenced by quite a few factors and has to be determined contextually. Some of the factors to consider include: &lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Review type: Formal Code Review requires more time and effort to complete than Lightweight Code Review. &lt;/li&gt;    &lt;li&gt;Review purpose: Code reviews used to mentor and improve team collaboration might need to be executed more frequently. &lt;/li&gt;    &lt;li&gt;Frequency and scope of code changes: Frequent, small check-ins versus irregular, big check-ins. &lt;/li&gt;    &lt;li&gt;Nature of the development effort: Open Source; Onshore; Offshore. &lt;/li&gt;    &lt;li&gt;Business need for quality: Mission critical applications need to ensure a high level of quality. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Having said of all this, doing infrequent code reviews or waiting to do reviews till code complete seriously undermines the benefit and integrity of the code review process. Reviewing code frequently motivates the developers to ensure the quality of the code being delivered – better known as the &lt;a href="http://en.wikipedia.org/wiki/Hawthorne_effect"&gt;Hawthorne Effect&lt;/a&gt; [Wikipedia02]. &lt;/p&gt;  &lt;h4&gt;Best Practices for Peer Code Review&lt;/h4&gt;  &lt;p&gt;[Cohen02] and [Bogue] present several techniques to ensure that your code reviews improve your code without wasting your developer’s time: &lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Verify that defects are actually fixed! &lt;/li&gt;    &lt;li&gt;Remember the purpose: Code reviews often start off on the wrong foot because they are perceived as an unnecessary step that has been forced upon the developers or, in some cases evidence that management doesn’t trust the developers. Code reviews are a proven, effective way to minimize defects and they are, at their core, an industry best practice. &lt;/li&gt;    &lt;li&gt;A matter of approach: Prevent code reviews from becoming mental jousting matches where people take shots at each other. Consider the review process as a forum to collaborate and learn from one another. Reviewers should ask questions rather than making statements; remember to praise and also be mindful of the fact that there is often more than one way to approach a solution. Authors should try to hear past attacking comments and try to focus on the learning that they can get out of the process. &lt;/li&gt;    &lt;li&gt;Review fewer than 200-400 lines of code at a time and aim for an inspection rate of less than 300-500 LOC/hour: Take your time when doing a review - faster is not better. &lt;/li&gt;    &lt;li&gt;Never review for more than 60-90 minutes at a time.&amp;#160; &lt;/li&gt;    &lt;li&gt;Authors should consider how to best explain their changes before the review begins: [Cohen02] refers to this process as “annotating the source code”. As the author has to re-think and explain the changes during the annotation process, the author will uncover many defects before the review even begins. &lt;/li&gt;    &lt;li&gt;Checklists substantially improve results for both authors and reviewers: Omissions are the hardest defects to find. A checklist is a great way to avoid this problem as it reminds the reviewer or author to take the time to look for something that might be missing. Publish the checklists on a wiki. As each person typically makes the same 15-20 mistakes, also consider creating personal checklists. &lt;/li&gt;    &lt;li&gt;Management must foster a good code review culture in which finding defects is viewed positively: A negative attitude towards defects found can sour a whole team and sabotage the bug-finding process. &lt;/li&gt;    &lt;li&gt;Beware of the “Big Brother” effect: Code review metrics should never be used to single out developers, particularly not in front of their peers. Metrics should be used to measure the efficiency or the effect of the process. &lt;/li&gt;    &lt;li&gt;The Ego Effect: Do at least some code review, even if you don’t have time to review it all. The Ego effect drives developers to review their own work and write better code because they know others will be looking at their code. &lt;/li&gt; &lt;/ul&gt;  &lt;h4&gt;Tools&lt;/h4&gt;  &lt;p&gt;I found the following tools to support a lightweight, tool-assisted peer code review process: &lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;&lt;a href="http://www.smartbear.com/codecollab.php"&gt;Code Collaborator&lt;/a&gt; - Commercial offering from &lt;a href="http://www.smartbear.com/"&gt;Smart Bear Software&lt;/a&gt; that supports online reviews with inline source commenting, threaded contextual chat, asynchronous reviews for when participants are separated by many timezones, review metrics and reports, version control integration, customisable workflow and &lt;a href="http://smartbearsoftware.com/codecollab-features.php"&gt;much more&lt;/a&gt;. &lt;/li&gt;    &lt;li&gt;&lt;a href="http://www.atlassian.com/software/crucible/"&gt;Crucible&lt;/a&gt; - Commercial offering from &lt;a href="http://www.atlassian.com/"&gt;Atlassian&lt;/a&gt; that supports online reviews with inline source commenting, threaded comments, review metrics, version control integration, workflow and &lt;a href="http://www.atlassian.com/software/crucible/features/"&gt;much more&lt;/a&gt;. &lt;/li&gt;    &lt;li&gt;&lt;a href="http://codestriker.sourceforge.net/"&gt;Codestriker&lt;/a&gt; - Open source project that supports online reviews with version control integration and review metrics. &lt;/li&gt; &lt;/ol&gt;  &lt;h4&gt;Conclusion&lt;/h4&gt;  &lt;p&gt;Well that about covers my thoughts on the topic.&amp;#160; I'm interested to know how many people are actually doing some form of peer code review.&amp;#160; What type of reviews are you doing?&amp;#160; How often do you do reviews? Do you use any tools to assist you with your reviews?&amp;#160; What code review practices work best in your environment?&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4775121157402872976-3315957687821968027?l=fromthedevtrenches.blogspot.com'/&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/FromTheSoftwareDevelopmentTrenches/~4/_ClGtwj7coE" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://fromthedevtrenches.blogspot.com/feeds/3315957687821968027/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://fromthedevtrenches.blogspot.com/2009/11/code-reviews.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4775121157402872976/posts/default/3315957687821968027?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4775121157402872976/posts/default/3315957687821968027?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/FromTheSoftwareDevelopmentTrenches/~3/_ClGtwj7coE/code-reviews.html" title="Code Reviews" /><author><name>Carel Lotz</name><uri>http://www.blogger.com/profile/13701537592037249529</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="05471999821481181728" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://fromthedevtrenches.blogspot.com/2009/11/code-reviews.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C0AAQ30-eyp7ImA9WxNUEU0.&quot;"><id>tag:blogger.com,1999:blog-4775121157402872976.post-5749519246118577828</id><published>2009-11-01T20:55:00.001+02:00</published><updated>2009-11-01T20:55:42.353+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-11-01T20:55:42.353+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="CodeAnalysis" /><category scheme="http://www.blogger.com/atom/ns#" term="FxCop" /><title>FxCop</title><content type="html">&lt;p&gt;&lt;strong&gt;NOTE: This is a repost of on old post as &lt;a href="http://fromthedevtrenches.blogspot.com/2009/10/migrating-blog-onto-blogger.html"&gt;I am moving&lt;/a&gt; onto the Blogger platform&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;img style="margin: 0px 5px 0px 0px" border="0" alt="image" align="left" src="http://dotnet.org.za/blogs/cjlotz/WindowsLiveWriter/StaticCodeAnalysisusingFxCop_9648/image_thumb.png" width="244" height="164" /&gt; In previous posts about &lt;a href="http://dotnet.org.za/cjlotz/archive/2007/01/02/Code-Metrics.aspx"&gt;Code Metrics&lt;/a&gt; and &lt;a href="http://dotnet.org.za/cjlotz/archive/2007/08/28/code-reviews.aspx"&gt;Code Reviews&lt;/a&gt;, I explored some metrics and techniques that I felt should form part of any good software quality control process.&amp;#160; One of the tools that I mentioned is FxCop.&amp;#160; &lt;/p&gt;  &lt;p&gt;In this post I take a closer look at FxCop.&amp;#160; I start by looking at how FxCop works and how you can fit it into your development process.&amp;#160; I then consider the different rule sets to use and look at how you can utilise FxCop to guide your VS 2003/2005/2008 development efforts.&amp;#160; I finish off the article by linking to articles that show you how to develop your own custom FxCop rules.&lt;/p&gt;  &lt;h4&gt;Introduction&lt;/h4&gt;  &lt;p&gt;FxCop analyses .NET assemblies for potential code compliance problems and forms part of &lt;a href="http://en.wikipedia.org/wiki/Static_code_analysis"&gt;static code analysis&lt;/a&gt;. With static code analysis the compiled code is checked for compliance to identify possible defects before executing the code as illustrated in the following diagram. &lt;/p&gt;  &lt;p&gt;&lt;img border="0" alt="image" src="http://dotnet.org.za/blogs/cjlotz/WindowsLiveWriter/StaticCodeAnalysisusingFxCop_9648/image_5.png" width="361" height="271" /&gt;&lt;/p&gt;  &lt;p&gt;FxCop employs assembly analysis of generated assemblies using an introspection engine. Since the analysis is performed on the generated intermediate language (&lt;a href="http://en.wikipedia.org/wiki/MSIL"&gt;MSIL&lt;/a&gt;) code, FxCop is not dependent on any particular .NET implementation language.&amp;#160; However, it is important to remember that assembly analysis cannot analyse certain aspects of the original source code, such as code comments, since these are not carried over in the compilation process.&amp;#160;&amp;#160; You may also run into a scenarios where there are differences between the FxCop violations in Debug and Release configurations due to the compiler optimisations being applied in Release mode. &lt;/p&gt;  &lt;p&gt;FxCop ships with a large rule set analysing library design, globalization, interoperability, maintainability, mobility, naming, performance, portability, reliability, security and usage aspects of the assembly. The rule set can be extended to include new custom rules and existing rules can be switched off if necessary. &lt;/p&gt;  &lt;h4&gt;Process&lt;/h4&gt;  &lt;p&gt;FxCop will typically be used by the following people: &lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Developers use FxCop continuously during development, because it helps with familiarising themselves with the .NET coding best practices. As they progress they should find that they break fewer rules and can consequently rely on the tool less often. However, they should still continue to evaluate their code at predefined intervals in the SDLC. By actively using this tool, developers raise the standard of code going into code review sessions. I advocate for using the tool before every commit. &lt;/li&gt;    &lt;li&gt;Code reviewers use the tool to verify that developers are indeed complying with the best practices as defined in the rule set. They should also check that they agree with any &amp;quot;excluded&amp;quot; defects. Use of FxCop should rapidly improve both the speed and breadth of code review sessions by instantly highlighting the most obvious problems. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;I &lt;strong&gt;strongly&lt;/strong&gt; recommend using FxCop together with a refactoring tool like &lt;a href="http://www.jetbrains.com/resharper/"&gt;ReSharper&lt;/a&gt; which makes fixing the rule violations a lot easier and less error prone. &lt;/p&gt;  &lt;h5&gt;FxCop Backlogs&lt;/h5&gt;  &lt;p&gt;The following articles present some ideas on how to introduce FxCop into your SDLC: &lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;&lt;a href="http://msmvps.com/blogs/calinoiu/archive/2007/04/22/fxcop-and-the-big-bad-backlog.aspx"&gt;FxCop and the big-bad-backlog&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://msmvps.com/blogs/calinoiu/archive/2007/04/29/fxcop-backlogs-some-rules-for-rule-activation.aspx"&gt;FxCop backlogs: Some rules for rule activation&lt;/a&gt; &lt;/li&gt; &lt;/ol&gt;  &lt;h4&gt;Rule sets&lt;/h4&gt;  &lt;p&gt;The rule sets provided with FxCop are quite extensive.&amp;#160; Some rule sets (i.e Globalization/Mobility rule set) also includes rules that only apply to applications that target certain platforms/cultures/languages etc. Microsoft itself uses &lt;a href="http://blogs.msdn.com/fxcop/archive/2007/08/09/what-rules-do-microsoft-have-turned-on-internally.aspx"&gt;a sub-set&lt;/a&gt; of the complete FxCop rules to guide their own internal development efforts. From experience, I have created two rule sets to guide my own development efforts. &lt;/p&gt;  &lt;h5&gt;Base Rule Set&lt;/h5&gt;  &lt;p&gt;The Base Rule Set is the rule set that I use for all &lt;strong&gt;new&lt;/strong&gt; .NET development efforts. This rule set &lt;strong&gt;excludes&lt;/strong&gt; the following rules: &lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;strong&gt;Globalization Rules:&lt;/strong&gt; CA1300: Specify MessageBoxOptions &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Globalization Rules:&lt;/strong&gt; CA1301: Avoid duplicate accelerators &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Globalization Rules:&lt;/strong&gt; CA1302: Do not hardcode locale specific strings &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Globalization Rules&lt;sup&gt;+&lt;/sup&gt;:&lt;/strong&gt; CA1303: Do not pass literals as localized parameters &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Naming Rules: CA1701:&lt;/strong&gt; Resource string compound words should be cased correctly &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Naming Rules: CA1702:&lt;/strong&gt; Compound words should be cased correctly &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Naming Rules: CA1703:&lt;/strong&gt; Resource strings should be spelled correctly &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Naming Rules: CA1704:&lt;/strong&gt; Identifiers should be spelled correctly &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Naming Rules: CA1726:&lt;/strong&gt; Use preferred terms &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Usage Rules: CA2204&lt;sup&gt;+&lt;/sup&gt;:&lt;/strong&gt; Literals should be spelled correctly &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Usage Rules: CA2243:&lt;/strong&gt; Attribute string literals should parse correctly &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;&lt;strong&gt;&lt;sub&gt;+ Not available in VS 2008&lt;/sub&gt;&lt;/strong&gt;&lt;/p&gt;  &lt;h5&gt;Minimum Rule Set&lt;/h5&gt;  &lt;p&gt;The Minimum Rule Set is the rule set that I use for all &lt;strong&gt;existing&lt;/strong&gt; .NET development efforts. The idea is that these projects will most likely hit more rule violations on their existing code base and I therefore want to exclude some rules that add a lot of noise without providing IMO a lot of benefit. &lt;strong&gt;This rule set adds the following &lt;em&gt;additional&lt;/em&gt; exclusions to those already excluded within the Base Rule Set:&lt;/strong&gt;&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;strong&gt;Design Rules:&lt;/strong&gt; CA1002: Do not expose generic lists &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Design Rules:&lt;/strong&gt; CA1003: Use generic event handler instances &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Design Rules:&lt;/strong&gt; CA1004: Generic method should provide type parameter &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Design Rules:&lt;/strong&gt; CA1005: Avoid excessive parameters on generic types &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Design Rules:&lt;/strong&gt; CA1007: Use generics where appropriate &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Design Rules:&lt;/strong&gt; CA1010: Collections should implement generic interface &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Design Rules:&lt;/strong&gt; CA1020: Use properties where appropriate &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Design Rules:&lt;/strong&gt; CA1024: Avoid namespaces with few types &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Design Rules:&lt;/strong&gt; CA1031: Do not catch general exception types &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Design Rules:&lt;/strong&gt; CA1064: Exceptions should be public &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Globalization Rules:&lt;/strong&gt; CA1304: Specify CultureInfo &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Globalization Rules:&lt;/strong&gt; CA1305: Specify IFormatProvider &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Globalization Rules:&lt;/strong&gt; CA1306: Set locale for data types &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Naming Rules:&lt;/strong&gt; CA1705&lt;sup&gt;+&lt;/sup&gt;: Long acronyms should be pascal-cased &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Naming Rules:&lt;/strong&gt; CA1706&lt;sup&gt;+&lt;/sup&gt;: Short acronyms should be uppercase &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Naming Rules:&lt;/strong&gt; CA1707: Identifiers should not contain underscores &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Naming Rules:&lt;/strong&gt; CA1713: Events should not have before or after prefix &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Naming Rules:&lt;/strong&gt; CA1714: Flags enums should have plural names &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Naming Rules:&lt;/strong&gt; CA1717: Only FlagsAttribute enums should have plural names &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Mobility Rules:&lt;/strong&gt; CA1600: Do not use idle process priority &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Mobility Rules:&lt;/strong&gt; CA1601: Do not use timers that prevent power state changes &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Performance Rules:&lt;/strong&gt; CA1800: Do not cast unnecessary &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Performance Rules:&lt;/strong&gt; CA1802: Use literals where appropriate &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Performance Rules:&lt;/strong&gt; CA1805: Do not initialize unnecessary &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Performance Rules:&lt;/strong&gt; CA1822: Mark members as static &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Usage Rules:&lt;/strong&gt; CA2201: Do not raise reserved exception types &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Usage Rules:&lt;/strong&gt; CA2205: Use managed equivalent of win32 api &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Usage Rules:&lt;/strong&gt; CA2225: Operator overloads have named alternates &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Usage Rules:&lt;/strong&gt; CA2242: Test for NaN correctly &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;&lt;strong&gt;&lt;sub&gt;+ Not available in VS 2008&lt;/sub&gt;&lt;/strong&gt;&amp;#160;&lt;/p&gt;  &lt;h4&gt;Implementation&lt;/h4&gt;  &lt;p&gt;There are differences between using FxCop for Visual Studio 2003 and Visual Studio 2005/2008 development. For projects that have been upgraded from VS 2003 to VS 2005, read the &lt;a href="http://blogs.msdn.com/fxcop/archive/2006/05/19/making-it-easier-to-move-from-fxcop-to-visual-studio-code-analysis-jeffrey-van-gogh.aspx"&gt;following article&lt;/a&gt; for tips on how to migrate your existing VS 2003 FxCop exclusions file over to VS 2005 FxCop code exclusions. &lt;/p&gt;  &lt;h5&gt;VS 2003&lt;/h5&gt;  &lt;p&gt;Obtain FxCop from &lt;a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=3389f7e4-0e55-4a4d-bc74-4aeabb17997b&amp;amp;displaylang=en"&gt;here&lt;/a&gt;. Analyses can be performed from either using the FxCop GUI directly or from the FxCop command-line utility which allows you to integrate into a &lt;a href="http://dotnet.org.za/cjlotz/archive/2007/12/03/continuous-integration-from-theory-to-practice.aspx"&gt;continuous integration process&lt;/a&gt;. &lt;/p&gt;  &lt;h5&gt;VS 2005&lt;/h5&gt;  &lt;p&gt;VS 2005 adds static code analysis through integrating FxCop directly into the IDE. A developer can select to include static code analysis as part of the compilation process which will fire off FxCop and produce a list of errors/warnings in the Error list pane that prevents the code from compiling successfully. &lt;a href="http://msdn2.microsoft.com/en-us/library/ms182075%28VS.90%29.aspx"&gt;Code Analysis Policy&lt;/a&gt; for VS Team System can also be created that makes this code analysis process a compulsory step within the compilation process. This will prevent developers from skipping the static code analysis process. &lt;/p&gt;  &lt;h5&gt;VS 2008&lt;/h5&gt;  &lt;p&gt;VS 2008 expands and improves on the code analysis provided in the VS 2005 IDE. Some of the improvements made are: &lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;a href="http://blogs.msdn.com/fxcop/archive/2006/12/21/two-new-features-for-orcas.aspx"&gt;Ability to exclude generated code from code analysis&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/fxcop/archive/2007/08/08/_24002800_CodeAnalysisTreatWarningAsErrors_2900_-MSBuild-property.aspx"&gt;Single MSBuild property to treat all violations as errors&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/fxcop/archive/2007/08/12/new-for-visual-studio-2008-spelling-rules.aspx"&gt;Inclusion of the FxCop standalone spelling rules&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/fxcop/archive/2007/08/20/new-for-visual-studio-2008-custom-dictionaries.aspx"&gt;Support for custom dictionaries to support the spelling rules&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/fxcop/archive/2007/09/20/new-for-visual-studio-2008-code-analysis-policy-improvements.aspx"&gt;Improvements to Code Analysis Policy&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/fxcop/archive/2007/09/21/new-for-visual-studio-2008-support-for-anonymous-methods-and-lambda-expressions.aspx"&gt;Support for Anonymous Methods and Lamda Expressions&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/fxcop/archive/2007/11/15/code-metrics-as-check-in-policy.aspx"&gt;Ability to Use Code Metrics as Check-in Policy&lt;/a&gt; &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Also be sure to check out the &lt;a href="http://blogs.msdn.com/kcwalina/archive/2007/10/02/Multi_2D00_TargetingAndFxCop.aspx"&gt;custom FxCop rule&lt;/a&gt; to support the multi-targeting feature of VS 2008. &lt;/p&gt;  &lt;h4&gt;Continuous Integration&lt;/h4&gt;  &lt;p&gt;FxCop can easily be integrated into a &lt;a href="http://fromthedevtrenches.blogspot.com/2009/11/continuous-integration-from-theory-to_01.html"&gt;continuous integration&lt;/a&gt; process by using the standalone FxCop command-line utility for VS 2003 or by using VS 2005/2008 Code Analysis.&amp;#160; As already mentioned, development teams using Visual Studio Team System can include &lt;a href="http://msdn2.microsoft.com/en-us/library/ms182075%28VS.90%29.aspx"&gt;Code Analysis Policy&lt;/a&gt; to enforce the continuous use of FxCop in their development environments. &lt;/p&gt;  &lt;h4&gt;Custom rule development&lt;/h4&gt;  &lt;p&gt;It is possible to write your own rules to integrate with FxCop running standalone or integrated into the VS IDE. Here are some articles on the topic: &lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;a href="http://blogs.interknowlogy.com/timmccarthy/archive/2007/02/13/11543.aspx"&gt;How to write custom code analysis rules for VS 2005&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://bordecal.mvps.org/Nicole/FxCop/CustomRulesSample.htm"&gt;Custom rule sample&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.msdn.com/fxcop/archive/2007/05/16/faq-how-do-i-debug-a-custom-rule.aspx"&gt;How to debug a custom rule&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://msmvps.com/blogs/calinoiu/archive/2007/04/21/no-rules-in-your-fxcop-rule-assembly.aspx"&gt;No rules in your FxCop assembly&lt;/a&gt; &lt;/li&gt; &lt;/ul&gt;  &lt;h4&gt;Further reading&lt;/h4&gt;  &lt;ul&gt;   &lt;li&gt;&lt;a href="http://blogs.msdn.com/fxcop/"&gt;Code Analysis and Code Metrics&lt;/a&gt; - The Visual Studio Code Analysis Team &lt;/li&gt;    &lt;li&gt;&lt;a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpgenref/html/cpconnetframeworkdesignguidelines.asp"&gt;Design Guidelines for Class Library Developers&lt;/a&gt; - The FxCop rules are largely based on the guidelines contained in this document &lt;/li&gt;    &lt;li&gt;&lt;a href="http://www.amazon.com/Framework-Design-Guidelines-Conventions-Development/dp/0321246756/ref=pd_bbs_sr_1?ie=UTF8&amp;amp;s=books&amp;amp;qid=1198227102&amp;amp;sr=8-1"&gt;Framework Design Guidelines&lt;/a&gt; by Krzysztof Cwalina and Brad Abrams &lt;/li&gt; &lt;/ul&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4775121157402872976-5749519246118577828?l=fromthedevtrenches.blogspot.com'/&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/FromTheSoftwareDevelopmentTrenches/~4/DUIOAhubP-c" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://fromthedevtrenches.blogspot.com/feeds/5749519246118577828/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://fromthedevtrenches.blogspot.com/2009/11/fxcop.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4775121157402872976/posts/default/5749519246118577828?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4775121157402872976/posts/default/5749519246118577828?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/FromTheSoftwareDevelopmentTrenches/~3/DUIOAhubP-c/fxcop.html" title="FxCop" /><author><name>Carel Lotz</name><uri>http://www.blogger.com/profile/13701537592037249529</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="05471999821481181728" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://fromthedevtrenches.blogspot.com/2009/11/fxcop.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C0INQXo_cSp7ImA9WxNUEU0.&quot;"><id>tag:blogger.com,1999:blog-4775121157402872976.post-6109644880957140797</id><published>2009-11-01T20:53:00.001+02:00</published><updated>2009-11-01T20:53:10.449+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-11-01T20:53:10.449+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="ContinuousIntegration" /><title>Continuous Integration: From Theory to Practice</title><content type="html">&lt;p&gt;&lt;strong&gt;NOTE: This is a repost of on old post as &lt;a href="http://fromthedevtrenches.blogspot.com/2009/10/migrating-blog-onto-blogger.html"&gt;I am moving&lt;/a&gt; onto the Blogger platform&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://dotnet.org.za/blogs/cjlotz/WindowsLiveWriter/ContinuousIntegrationSomeTheoryandPracti_D266/image_2.png"&gt;&lt;img style="margin: 0px 0px 5px 10px" border="0" alt="image" align="right" src="http://dotnet.org.za/blogs/cjlotz/WindowsLiveWriter/ContinuousIntegrationSomeTheoryandPracti_D266/image_thumb.png" width="244" height="183" /&gt;&lt;/a&gt; &lt;a href="http://www.martinfowler.com/articles/continuousIntegration.html"&gt;Continuous Integration&lt;/a&gt; (CI) is a popular incremental integration process whereby each change made to the system is integrated into a latest build. These integration points can occur continuously on every commit to the repository or on regular intervals like every 30 minutes.&amp;#160; They should however not take longer than a day i.e. you need to integrate at least once daily. &lt;/p&gt;  &lt;p&gt;In this article I take a closer look at CI.&amp;#160; The article is divided into two main sections: theory and practice.&amp;#160; In the &lt;em&gt;theory&lt;/em&gt; section, I consider some CI best practices; look at the benefits of integrating frequently and reflect on some recommendations for introducing CI into your environment.&amp;#160; The &lt;em&gt;practice&lt;/em&gt; section provides an in-depth example of how to implement a CI process using .NET development tooling.&amp;#160; I conclude the article by providing some additional, recommended reading. &lt;/p&gt;  &lt;h4&gt;References&lt;/h4&gt;  &lt;p&gt;I used the following references in creating the article: &lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;[McConnell] &lt;a href="http://www.cc2e.com/Default.aspx"&gt;&lt;em&gt;Code Complete, 2nd Edition&lt;/em&gt;&lt;/a&gt;&lt;em&gt; &lt;/em&gt;by Steve McConnell. &lt;/li&gt;    &lt;li&gt;[Fowler] &lt;a href="http://martinfowler.com/articles/continuousIntegration.html"&gt;&lt;em&gt;Continuous Integration&lt;/em&gt;&lt;/a&gt;&lt;em&gt; &lt;/em&gt;by Martin Fowler. &lt;/li&gt;    &lt;li&gt;[Miller] &lt;a href="http://codebetter.com/blogs/jeremy.miller/archive/2005/07/25/129797.aspx"&gt;&lt;em&gt;Using Continuous Integration?&amp;#160; Better do the &amp;quot;Check In Dance&amp;quot;&lt;/em&gt;&lt;/a&gt; by Jeremy Miller. &lt;/li&gt;    &lt;li&gt;[Elssamadisy] &lt;em&gt;&lt;a href="http://www.infoq.com/minibooks/agile-patterns"&gt;Patterns of Agile Practice Adoption: The Technical Cluster&lt;/a&gt;&lt;/em&gt; by Amr Elssamadisy. &lt;/li&gt;    &lt;li&gt;[Duvall] &lt;a href="http://www.ibm.com/developerworks/java/library/j-ap11297/index.html"&gt;&lt;em&gt;Continuous Integration Anti-Patterns&lt;/em&gt;&lt;/a&gt; by Paul Duvall. &lt;/li&gt; &lt;/ul&gt;  &lt;h4&gt;Practices&lt;/h4&gt;  &lt;p&gt;Martin Fowler presents the following set of practices for CI [Fowler]:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;strong&gt;Maintain a single source repository&lt;/strong&gt; - Use a decent source code management system and make sure its location is well known as the place where everyone can go to get source code.&amp;#160; Also ensure that everything is put into the repository (test scripts, database schema, third party libraries etc.) &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Automate the build&lt;/strong&gt; - Make sure you can build and launch your system using MSBuild/NAnt scripts in a single command.&amp;#160; Include everything into your build.&amp;#160; As a simple rule of thumb: anyone should be able to bring in a clean machine, check the sources out of the repository and issue a single command to have a running system on their machine. &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Make your build self-testing&lt;/strong&gt; - Include automated tests in your build process.&amp;#160; &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Everyone commits every day&lt;/strong&gt; - &amp;quot;&lt;em&gt;A commit a day keeps the integration woes away&amp;quot;&lt;/em&gt; [Duvall].&amp;#160; Frequent commits encourage developers to break down their work into small chunks of a few hours each. Before committing their code, they need to update their working copy with the &lt;a href="http://www.scmpatterns.com/book/pattern-summary.html"&gt;mainline&lt;/a&gt;, resolve any conflicts and ensure that everything still works fine.&amp;#160; Jeremy Miller refers to this process as the &amp;quot;Check In Dance&amp;quot; [Miller]. &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Every commit should build the mainline on an integration machine&lt;/strong&gt; - Use a CI server like or &lt;a href="http://ccnet.thoughtworks.com/"&gt;CruiseControl.NET&lt;/a&gt; or &lt;a href="http://msdn2.microsoft.com/en-us/library/ms181710%28VS.90%29.aspx"&gt;Team Foundation Build&lt;/a&gt;.&amp;#160; If the mainline build fails, it needs to be fixed right away. &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Keep the build fast&lt;/strong&gt; - If the build takes too long to execute, try and create a staged build/build pipeline where multiple builds are done in a sequence.&amp;#160; The first build (aka &lt;em&gt;''commit build''&lt;/em&gt;) executes quickly and gives other people confidence that they can work with the code in the repository.&amp;#160; Further builds can run additional, slower running unit tests, create code metrics, check the code against coding standards, create documentation etc. &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Test in a clone of the production environment&lt;/strong&gt; - Try to set up your test environment to be as exact a mimic of your production environment as possible.&amp;#160; Use the same versions of third party software, the same operating system version etc.&amp;#160;&amp;#160; Consider using virtualization to make it easy to put together test environments. &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Make it easy for anyone to get the latest executable&lt;/strong&gt; - Make sure that there is a well known place where people can find the latest executable. &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Everyone can see what's happening&lt;/strong&gt; - Make the state of the mainline build as visible as possible. Use various feedback mechanisms to relate build status information [Duvall].&amp;#160; Some fun examples include using &lt;a href="http://www.pragmaticautomation.com/cgi-bin/pragauto.cgi/Monitor/Devices/BubbleBubbleBuildsInTrouble.rdoc"&gt;lava lamps&lt;/a&gt;, &lt;a href="http://www.hamang.net/index.php?option=com_content&amp;amp;task=view&amp;amp;id=16&amp;amp;Itemid=9"&gt;a big screen LCD&lt;/a&gt; and &lt;a href="http://blogs.msdn.com/mswanson/articles/169058.aspx"&gt;an ambient orb&lt;/a&gt;. &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Automate deployment&lt;/strong&gt; - Have scripts that allow you to automatically deploy into different environments, including production.&amp;#160; For web applications, consider deploying a trial build to a subset of users before deploying to the full user base. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Jeremy Miller adds the following advice [Miller]:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;strong&gt;Check in as often as you can - &lt;/strong&gt;Try breaking down your workload into meaningful chunks of code and integrate these pieces of code when you have a collection of code in a consistent state. Checking in once a week seriously compromises the effectiveness of a CI process. &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Don't leave the build broken overnight&lt;/strong&gt; - Developers need to be immediately notified upon a build breakage and make it a top priority to fix a broken build. &lt;/li&gt;    &lt;li&gt;Don't ever check into a busted build. &lt;/li&gt;    &lt;li&gt;If you are working on fixing the build, let the rest of the team know. &lt;/li&gt;    &lt;li&gt;Every developer needs to know how to execute a build locally and troubleshoot a broken build. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Paul Duvall also warns against some additional CI anti-patterns that tend to produce adverse effects [Duvall]. The ones that have not been covered above are: &lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;strong&gt;The cold shoulder of spam feedback&lt;/strong&gt; - Team members sometimes quickly become inundated with build status e-mails (success and failure and everything in between) to the point where they start to ignore messages. Try to make the feedback succinctly targeted so that people don't receive irrelevant information. &lt;/li&gt;    &lt;li&gt;D&lt;strong&gt;on't delay feedback with a slow machine&lt;/strong&gt; - Get a build machine that has optimal disk speed, processor, and RAM resources for speedy builds. &lt;/li&gt; &lt;/ul&gt;  &lt;h4&gt;Benefits&lt;/h4&gt;  &lt;p&gt;Numerous benefits result from integrating continuously [McConnell]: &lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;strong&gt;Errors are easier to locate&lt;/strong&gt; - New problems can be narrowed down to the small part that was recently integrated. &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Improved team morale&lt;/strong&gt; - Programmers see early results from their work. &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Better customer relations&lt;/strong&gt; - Customers like signs of progress and incremental builds provide signs of progress frequently. &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;More reliable schedule estimates &amp;amp; more accurate status reporting&lt;/strong&gt; - Management gets a better sense of progress than the typical &amp;quot;&lt;em&gt;coding is 99% percent complete&amp;quot;&lt;/em&gt; message. &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Units of the system are tested more fully&lt;/strong&gt; - As integration starts early in the project the code is exercised as part of the overall system more frequently. &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Work that sometimes surfaces unexpectedly at the end of a project&lt;/strong&gt; &lt;strong&gt;is exposed early on&lt;/strong&gt; &lt;/li&gt; &lt;/ul&gt;  &lt;h4&gt;Where do I start?&lt;/h4&gt;  &lt;p&gt;Here are some steps to consider for introducing a CI process [Fowler]:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;strong&gt;Get the build automated&lt;/strong&gt; - Get everything into source control and make sure you can build the whole system with a single command. &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Introduce automated testing in the build&lt;/strong&gt; - Identify major areas where things go wrong and start adding automated tests to expose these failures. &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Speed up the build&lt;/strong&gt; - Try aiming at creating a build that runs to completion within ten minutes.&amp;#160; Constantly monitor your build and take action as soon as your start going slower than the ten minute rule. &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Start all new projects with CI from the beginning&lt;/strong&gt; &lt;/li&gt; &lt;/ul&gt;  &lt;h4&gt;.NET Implementation &amp;amp; Tools&lt;/h4&gt;  &lt;p&gt;I have written a &lt;a href="http://fromthedevtrenches.blogspot.com/2009/11/continuous-integration-from-theory-to.html"&gt;set of articles&lt;/a&gt; that describe a complete setup of a .NET CI solution.&amp;#160; The CI process uses a wide variety of tools including CruiseControl.NET, Subversion, MSBuild, Visual Studio 2008, NUnit, FxCop, NCover, WiX and SandCastle.&amp;#160; You can &lt;a href="http://sites.google.com/site/fromthedevtrenches/downloads/ContinuousIntegration-FromTheorytoPractice%2C2ndEd.pdf?attredirects=0&amp;amp;d=1"&gt;download&lt;/a&gt; the series as a fully searchable PDF with PDF bookmarks and PDF links.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://msdn2.microsoft.com/en-us/teamsystem/aa718934.aspx"&gt;Team Foundation Server&lt;/a&gt; users can check out the &lt;a href="http://www.infoq.com/news/2007/08/tfs-2008-continuous-integration"&gt;new and improved out-of-the-box support&lt;/a&gt; for continuous integration provided by Team Foundation Server 2008.&amp;#160; This, coupled with the &lt;a href="http://blogs.msdn.com/bharry/archive/2007/11/23/tfs-licensing-change-for-tfs-2008.aspx"&gt;recent announcement&lt;/a&gt; on the TFS Licensing Change for TFS 2008, makes using Team Foundation Server less expensive and a more viable option to consider.&lt;/p&gt;  &lt;h4&gt;Recommended Reading&lt;/h4&gt;  &lt;ol&gt;   &lt;li&gt;&lt;a href="http://www.amazon.com/Continuous-Integration-Improving-Addison-Wesley-Signature/dp/0321336380/ref=pd_bbs_sr_1?ie=UTF8&amp;amp;s=books&amp;amp;qid=1196675506&amp;amp;sr=1-1"&gt;Continuous Integration: Improving Software Quality and Reducing Risk&lt;/a&gt; by Paul Duvall. &lt;/li&gt;    &lt;li&gt;&lt;a href="http://www.scmpatterns.com/book/"&gt;Software Configuration Management Patterns&lt;/a&gt; by Steve Berczuk and Brad Appleton. &lt;/li&gt;    &lt;li&gt;&lt;a href="http://www.amazon.com/exec/obidos/ASIN/0321293533/ambysoftinc"&gt;Refactoring Databases&lt;/a&gt; by Scott Ambler and Pramodkumar Sadalage. &lt;/li&gt;    &lt;li&gt;&lt;a href="http://www.amazon.com/gp/product/0321418506/ref=wl_it_dp?ie=UTF8&amp;amp;coliid=I3Q3LC4EPNMYT7&amp;amp;colid=16P4CZJ4SV1K"&gt;Visual Studio Team System: Better Software Development for Agile Teams&lt;/a&gt; by Will Stott and James Newkirk.&lt;/li&gt; &lt;/ol&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4775121157402872976-6109644880957140797?l=fromthedevtrenches.blogspot.com'/&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/FromTheSoftwareDevelopmentTrenches/~4/0cGOwOnc1dA" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://fromthedevtrenches.blogspot.com/feeds/6109644880957140797/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://fromthedevtrenches.blogspot.com/2009/11/continuous-integration-from-theory-to_01.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4775121157402872976/posts/default/6109644880957140797?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4775121157402872976/posts/default/6109644880957140797?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/FromTheSoftwareDevelopmentTrenches/~3/0cGOwOnc1dA/continuous-integration-from-theory-to_01.html" title="Continuous Integration: From Theory to Practice" /><author><name>Carel Lotz</name><uri>http://www.blogger.com/profile/13701537592037249529</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="05471999821481181728" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://fromthedevtrenches.blogspot.com/2009/11/continuous-integration-from-theory-to_01.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEMGQ3w4cCp7ImA9WxNUEEQ.&quot;"><id>tag:blogger.com,1999:blog-4775121157402872976.post-6920860119032252962</id><published>2009-11-01T19:27:00.001+02:00</published><updated>2009-11-01T19:27:02.238+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-11-01T19:27:02.238+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="ContinuousIntegration" /><title>Continuous Integration: From Theory to Practice 2nd Edition</title><content type="html">&lt;p&gt;&lt;strong&gt;NOTE: This is a repost of on old post as &lt;a href="http://fromthedevtrenches.blogspot.com/2009/10/migrating-blog-onto-blogger.html"&gt;I am moving&lt;/a&gt; onto the Blogger platform&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://dotnet.org.za/blogs/cjlotz/WindowsLiveWriter/365770d3f865_CC8D/image_2.png"&gt;&lt;img border="0" alt="image" align="right" src="http://dotnet.org.za/blogs/cjlotz/WindowsLiveWriter/365770d3f865_CC8D/image_thumb.png" width="240" height="180" /&gt;&lt;/a&gt; During last year I created a &lt;a href="http://dotnet.org.za/cjlotz/archive/2007/08/31/continuous-integration-for-net-2-0-development-environments-downloadable-booklet.aspx"&gt;guide&lt;/a&gt; on implementing &lt;a href="http://dotnet.org.za/cjlotz/archive/2007/12/03/continuous-integration-from-theory-to-practice.aspx"&gt;Continuous Integration&lt;/a&gt; (CI) for a .NET 2.0 development environment.&amp;#160; The guide illustrates how to create a complete CI setup using VS 2005 and MSBuild (no NAnt) together with tools like FxCop, NCover, TypeMock, NUnit, Subversion, InstallShield, QTP, NDepend, Sandcastle and CruiseControl.NET.&lt;/p&gt;  &lt;p&gt;The good news is that I spend some time during the last 2 weeks greatly improving the setup for use on a new VS 2008 project and I have decided to release a 2nd Edition of the guide covering the much improved setup.&amp;#160; Instead of creating another series of blog posts to cover the content, I'm releasing the 2nd edition &lt;b&gt;only&lt;/b&gt; as a downloadable PDF guide together with all the associated code and build artefacts.&amp;#160; This will allow new teams to get up and running with CI a lot quicker.&lt;/p&gt;  &lt;p&gt;For readers of the first edition of the guide, the most notable differences between the second edition and the first edition of the guide are:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Updated to use VS 2008, .NET 3.5 and MSBuild 3.5 (including new MSBuild features like parallel builds and multi-targeting). &lt;/li&gt;    &lt;li&gt;All tools (NUnit, NDepend, NCover etc.) are now stored in a separate &lt;b&gt;Tools&lt;/b&gt; folder and kept under source control. The only development tools a developer needs to install are VS 2008, SQL Server 2005 and Subversion. The rest of the tools are retrieved form the &lt;a href="http://www.scmpatterns.com/book/pattern-summary.html"&gt;mainline&lt;/a&gt; along with the latest version of the source code. &lt;/li&gt;    &lt;li&gt;Added the CruiseControl.NET configuration (custom style sheets, server setup etc.) to source control and created a &lt;b&gt;single step setup&lt;/b&gt; process for the build server. This &lt;b&gt;greatly&lt;/b&gt; simplifies the process of setting up a new build server. &lt;/li&gt;    &lt;li&gt;Changed from using InstallShield to Windows Installer XML (WiX) for creating a Windows installer (msi). &lt;/li&gt;    &lt;li&gt;Added support for running MbUnit tests in addition to the NUnit tests. &lt;/li&gt;    &lt;li&gt;Added support for running standalone FxCop in addition to running VS 2008 Managed Code Analysis. &lt;/li&gt;    &lt;li&gt;Added targets to test the install and uninstall of the Windows installer created. &lt;/li&gt;    &lt;li&gt;Consolidated the CodeDocumentationBuild to become part of the DeploymentBuild. &lt;/li&gt;    &lt;li&gt;Removed the QTP integration as this was not a requirement for the new project. If you want to integrate QTP, please refer to the QtpBuild of the &lt;a href="http://sites.google.com/site/fromthedevtrenches/downloads/ContinuousIntegration-FromTheorytoPractice.pdf?attredirects=0&amp;amp;d=1"&gt;first edition&lt;/a&gt; of the guide. &lt;/li&gt;    &lt;li&gt;Used the latest version of all the tools available.&amp;#160; The tools used in the guide are VS 2008, Subversion, CruiseControl.NET, MSBuild, MSBuild.Community.Tasks, NUnit/MbUnit, FxCop, TypeMock/Rhino.Mocks, WiX, Sandcastle, NCover, NCoverExplorer and NDepend. &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;I hope you find it to be a useful resource for assisting you with creating your own CI process by harnessing the power of MSBuild!&amp;#160; If you have any questions, additional remarks or any suggestions, feel free to drop me a comment.&lt;/p&gt;  &lt;h4&gt;Download&lt;/h4&gt;  &lt;p&gt;Here are the links:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;&lt;a href="http://sites.google.com/site/fromthedevtrenches/downloads/ContinuousIntegration-FromTheorytoPractice%2C2ndEd.pdf?attredirects=0&amp;amp;d=1"&gt;PDF Guide&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://sites.google.com/site/fromthedevtrenches/downloads/ContinuousIntegration-FromTheorytoPractice%2C2ndEd.zip?attredirects=0&amp;amp;d=1"&gt;Code and Build artifacts&lt;/a&gt; &lt;/li&gt; &lt;/ol&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4775121157402872976-6920860119032252962?l=fromthedevtrenches.blogspot.com'/&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/FromTheSoftwareDevelopmentTrenches/~4/Un8FywGEkf0" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://fromthedevtrenches.blogspot.com/feeds/6920860119032252962/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://fromthedevtrenches.blogspot.com/2009/11/continuous-integration-from-theory-to.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4775121157402872976/posts/default/6920860119032252962?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4775121157402872976/posts/default/6920860119032252962?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/FromTheSoftwareDevelopmentTrenches/~3/Un8FywGEkf0/continuous-integration-from-theory-to.html" title="Continuous Integration: From Theory to Practice 2nd Edition" /><author><name>Carel Lotz</name><uri>http://www.blogger.com/profile/13701537592037249529</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="05471999821481181728" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://fromthedevtrenches.blogspot.com/2009/11/continuous-integration-from-theory-to.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DkEBSX8yfCp7ImA9WxNUEE8.&quot;"><id>tag:blogger.com,1999:blog-4775121157402872976.post-8448212961511846417</id><published>2009-10-31T23:30:00.001+02:00</published><updated>2009-10-31T23:30:58.194+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-10-31T23:30:58.194+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Books" /><title>Serious Software Developer Reading List</title><content type="html">&lt;p&gt;&lt;img style="display: inline; margin-left: 0px; margin-right: 0px" border="0" alt="image" align="right" src="http://dotnet.org.za/blogs/cjlotz/WindowsLiveWriter/SeriousSoftwareDeveloperreadinglist_BD3E/image_thumb.png" width="215" height="150" /&gt; As software developers we constantly need to keep up with the latest technology to keep ourselves marketable.&amp;#160; Unfortunately we are sometimes so busy keeping up with the new stuff coming out of Redmond that I fear we are not spending enough time learning the craft of software development.&amp;#160; Here is a list of &lt;strong&gt;non-technology&lt;/strong&gt; books that I think every serious developer should at some stage read to become better at writing quality software.&amp;#160; As software development is a team discipline the list includes some books that highlight how to create and be part of effective software development teams:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;&lt;a href="http://www.amazon.com/Principles-Patterns-Practices-Robert-Martin/dp/0131857258/sr=8-2/qid=1166644781/ref=pd_bbs_sr_2/002-6018978-6555228?ie=UTF8&amp;amp;s=books"&gt;Agile Principles, Patterns and Practices in C#. Robert C. Martin&lt;/a&gt;: If you can only read one book out of the list, this is my number one. &lt;/li&gt;    &lt;li&gt;&lt;a href="http://www.amazon.com/Patterns-Enterprise-Application-Architecture-Martin/dp/0321127420/sr=8-1/qid=1166644748/ref=pd_bbs_sr_1/002-6018978-6555228?ie=UTF8&amp;amp;s=books"&gt;Patterns of Enterprise Application Architecture. Martin Fowler&lt;/a&gt;: Great read for getting into enterprise application architecture. &lt;/li&gt;    &lt;li&gt;&lt;a href="http://www.amazon.com/Domain-Driven-Design-Tackling-Complexity-Software/dp/0321125215/sr=8-1/qid=1166677771/ref=pd_bbs_sr_1/002-6018978-6555228?ie=UTF8&amp;amp;s=books"&gt;Domain Driven Design: Tackling complexity in the heart of software. Eric Evans.&lt;/a&gt;&amp;#160; Also see the &lt;a href="http://www.infoq.com/minibooks/domain-driven-design-quickly"&gt;shortened e-book&lt;/a&gt; provided by &lt;a href="http://www.infoq.com"&gt;InfoQ&lt;/a&gt;. &lt;/li&gt;    &lt;li&gt;&lt;a href="http://www.amazon.com/Applying-Domain-Driven-Design-Patterns-Examples/dp/0321268202/sr=11-1/qid=1166677605/ref=sr_11_1/002-6018978-6555228"&gt;Applying Domain Driven Design and Patterns: With Examples in C# and .NET.&lt;/a&gt; Jimmy Nillson. &lt;/li&gt;    &lt;li&gt;&lt;a href="http://www.amazon.com/Applying-UML-Patterns-Introduction-Object-Oriented/dp/0131489062/ref=sr_11_1?ie=UTF8&amp;amp;qid=1202298695&amp;amp;sr=11-1"&gt;Applying UML and Patterns: An Introduction to Object-Oriented Analysis and Design and Iterative Development, 3rd Edition&lt;/a&gt;. Craig Larman &lt;/li&gt;    &lt;li&gt;&lt;a href="http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672/sr=8-2/qid=1166644517/ref=pd_bbs_2/002-6018978-6555228?ie=UTF8&amp;amp;s=books"&gt;Refactoring. Martin Fowler&lt;/a&gt;&lt;/li&gt;    &lt;li&gt;&lt;a href="http://www.amazon.com/Refactoring-Patterns-Addison-Wesley-Signature-Kerievsky/dp/0321213351/sr=8-1/qid=1166644517/ref=pd_bbs_sr_1/002-6018978-6555228?ie=UTF8&amp;amp;s=books"&gt;Refactoring to Patterns. Joshua Kerievsky&lt;/a&gt;: A better way to learning OO patterns may be to start with existing code smells and refactor these using OO patterns. &lt;/li&gt;    &lt;li&gt;&lt;a href="http://www.amazon.com/Code-Complete-Second-Steve-McConnell/dp/0735619670/sr=8-1/qid=1166645062/ref=pd_bbs_sr_1/002-6018978-6555228?ie=UTF8&amp;amp;s=books"&gt;Code Complete, 2nd Edition. Steve McConnell&lt;/a&gt;:&amp;#160; Every thing on crafting quality software. &lt;/li&gt;    &lt;li&gt;&lt;a href="http://www.amazon.com/gp/product/0321246756/002-1808809-0882450?v=glance&amp;amp;n=283155&amp;amp;n=507846&amp;amp;s=books&amp;amp;v=glance"&gt;Framework Design Guidelines. Krzystof Cwalina, Brad Abrams&lt;/a&gt;: The book may be specific to the .NET framework but still contains a lot of excellent guidelines for any framework type of development.&amp;#160; Also see the &lt;a href="http://www.amazon.com/gp/product/0321545613"&gt;2nd Edition&lt;/a&gt;.&lt;/li&gt;    &lt;li&gt;&lt;a href="http://www.pragmaticprogrammer.com/titles/utc2/index.html"&gt;Pragmatic unit testing in C# using NUnit, 2nd Edition&lt;/a&gt;. Andy Hunt:&amp;#160; The nice thing about all the &lt;a href="http://www.pragmaticprogrammer.com/bookshelf/index.html"&gt;Pragmatic Programmers books&lt;/a&gt; are that they are short and to the point. Also see the excellent &lt;a href="http://www.artofunittesting.com/"&gt;Art of Unit Testing&lt;/a&gt; by Roy Osherove.&lt;/li&gt;    &lt;li&gt;&lt;a href="http://www.amazon.com/Peopleware-Productive-Projects-Teams-2nd/dp/0932633439/sr=8-1/qid=1166645705/ref=pd_bbs_sr_1/002-6018978-6555228?ie=UTF8&amp;amp;s=books"&gt;Peopleware: Productive Projects and Teams, 2nd Edition. Tom DeMarco and Timothy Lister&lt;/a&gt;: 20 years old but oh still so relevant. &lt;/li&gt;    &lt;li&gt;&lt;a href="http://www.amazon.com/Mythical-Man-Month-Software-Engineering-Anniversary/dp/0201835959/sr=8-2/qid=1166645705/ref=pd_bbs_2/002-6018978-6555228?ie=UTF8&amp;amp;s=books"&gt;The Mythical Man-Month: Essays on Software Engineering, 20 anniversary edition.&lt;/a&gt;&amp;#160; Frederick P. Brooks &lt;/li&gt;    &lt;li&gt;&lt;a href="http://www.amazon.com/Designing-Interfaces-Jenifer-Tidwell/dp/0596008031/sr=8-1/qid=1167893704/ref=pd_bbs_sr_1/105-6857822-0591639?ie=UTF8&amp;amp;s=books"&gt;Designing Interfaces&lt;/a&gt;. Jenifer Tidwell: My favourite book on designing user interfaces &lt;/li&gt;    &lt;li&gt;&lt;a href="http://www.amazon.com/o/ASIN/0131177052/105-6457019-6042003?SubscriptionId=0DEETVQGV87MTJA1QCR2&amp;amp;coliid=ILVQEKB02J7MP&amp;amp;colid=16P4CZJ4SV1K"&gt;Working Effectively with Legacy Code&lt;/a&gt;.&amp;#160; Michael C. Feathers. &lt;/li&gt;    &lt;li&gt;&lt;a href="http://www.amazon.com/gp/product/0131495054/ref=wl_it_dp/105-6457019-6042003?ie=UTF8&amp;amp;coliid=IJEYM5KU0FMBC&amp;amp;colid=16P4CZJ4SV1K"&gt;xUnit Test Patterns: Refactoring Test Code.&lt;/a&gt; Gerard Meszaros. &lt;/li&gt;    &lt;li&gt;&lt;a href="http://www.amazon.com/gp/product/0596527675/ref=wl_it_dp/105-6457019-6042003?ie=UTF8&amp;amp;coliid=IHYOU8NKKU2HF&amp;amp;colid=16P4CZJ4SV1K"&gt;The Art of Agile Development.&lt;/a&gt; James Shore. &lt;/li&gt;    &lt;li&gt;&lt;a href="http://www.scmpatterns.com/book/"&gt;Software Configuration Management Patterns&lt;/a&gt;. Steve Berczuk and Brad Appleton.&lt;/li&gt;    &lt;li&gt;&lt;a href="http://www.pragprog.com/titles/mnee/release-it"&gt;Release It! Design and Deploy Production-Ready Software&lt;/a&gt;. Michael T. Nygard: Another &lt;a href="http://www.pragprog.com/"&gt;Pragmatic Bookshelf&lt;/a&gt; gem.&lt;/li&gt; &lt;/ol&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4775121157402872976-8448212961511846417?l=fromthedevtrenches.blogspot.com'/&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/FromTheSoftwareDevelopmentTrenches/~4/P_enH6Wado4" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://fromthedevtrenches.blogspot.com/feeds/8448212961511846417/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://fromthedevtrenches.blogspot.com/2009/10/serious-software-developer-reading-list.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4775121157402872976/posts/default/8448212961511846417?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4775121157402872976/posts/default/8448212961511846417?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/FromTheSoftwareDevelopmentTrenches/~3/P_enH6Wado4/serious-software-developer-reading-list.html" title="Serious Software Developer Reading List" /><author><name>Carel Lotz</name><uri>http://www.blogger.com/profile/13701537592037249529</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="05471999821481181728" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://fromthedevtrenches.blogspot.com/2009/10/serious-software-developer-reading-list.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEUHR3s4eyp7ImA9WxNUEE8.&quot;"><id>tag:blogger.com,1999:blog-4775121157402872976.post-2950548967276587544</id><published>2009-10-31T22:50:00.001+02:00</published><updated>2009-10-31T22:50:36.533+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-10-31T22:50:36.533+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Tools" /><title>Ultimate .NET development tools</title><content type="html">&lt;p&gt;&lt;img style="border-right-width: 0px; margin: 0px 10px 0px 0px; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" border="0" alt="image" align="left" src="http://dotnet.org.za/blogs/cjlotz/WindowsLiveWriter/Ultimate.NETdevelopmenttools_6530/image_3.png" width="111" height="111" /&gt; I've been wanting to make a list for my own reference of all the best-of-breed tools that I prefer to use when doing .NET development.&amp;#160; I specifically decided to not include any third party control/report libraries.&amp;#160; I focus instead on the tools that assist me in crafting high-quality code quickly and effectively.&lt;/p&gt;  &lt;h4&gt;Categories&lt;/h4&gt;  &lt;ul&gt;   &lt;li&gt;IDE = Develop/generate/refactor code within the VS IDE or separate IDE &lt;/li&gt;    &lt;li&gt;SCM = Software Configuration Management (Source Control etc.) &lt;/li&gt;    &lt;li&gt;TDD = Test Driven Development &lt;/li&gt;    &lt;li&gt;DBMS = Database Management Systems &lt;/li&gt;    &lt;li&gt;CI = Continuous Integration &lt;/li&gt;    &lt;li&gt;FR = Frameworks (Persistence, AOP, Inversion of Control, Logging etc.) &lt;/li&gt;    &lt;li&gt;UT = Utility Tools &lt;/li&gt;    &lt;li&gt;CA = Code Analysis (Static + Dynamic) &lt;/li&gt;    &lt;li&gt;TC = Team Collaboration (Bug tracking, Project management etc.) &lt;/li&gt;    &lt;li&gt;MD = Modelling &lt;/li&gt;    &lt;li&gt;QA = Testing Tools &lt;/li&gt;    &lt;li&gt;DP = Deployment (Installations etc.) &lt;/li&gt; &lt;/ul&gt;  &lt;h4&gt;Tools&lt;/h4&gt;  &lt;p&gt;* = free/open source&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;[IDE] &lt;a href="http://msdn2.microsoft.com/en-us/vstudio/default.aspx"&gt;Visual Studio 2008 Team Edition for Software Developers&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;[IDE] &lt;a href="http://www.jetbrains.com/resharper"&gt;ReSharper&lt;/a&gt; for refactoring and to &amp;quot;develop with pleasure&amp;quot; &lt;/li&gt;    &lt;li&gt;[IDE] &lt;a href="http://www.codesmithtools.com/"&gt;CodeSmith&lt;/a&gt; for generating code.&amp;#160; Also consider T4 with &lt;a href="http://www.visualt4.com/" target="_blank"&gt;Clarius’s Visual T4&lt;/a&gt; Editor.&amp;#160;&amp;#160; &lt;/li&gt;    &lt;li&gt;[IDE]* &lt;a href="http://submain.com/products/ghostdoc.aspx"&gt;GhostDoc&lt;/a&gt; for inserting xml code comments &lt;/li&gt;    &lt;li&gt;[IDE] &lt;a href="http://www.altova.com/"&gt;Altova Xml Suite&lt;/a&gt; for any xml related work.&amp;#160; &lt;a href="http://www.wmhelp.com"&gt;XmlPad&lt;/a&gt; is the best, free alternative I know of. &lt;/li&gt;    &lt;li&gt;[DBMS] &lt;a href="http://www.microsoft.com/sql/"&gt;SqlServer 2008&lt;/a&gt; for DBMS &lt;/li&gt;    &lt;li&gt;[DBMS] &lt;a href="http://msdn2.microsoft.com/en-us/vstudio/default.aspx"&gt;Visual Studio 2008 Team Edition for Database Professionals&lt;/a&gt; for managing databases as code artifacts &lt;/li&gt;    &lt;li&gt;[SCM]* &lt;a href="http://subversion.tigris.org/"&gt;Subversion&lt;/a&gt; for source control &lt;/li&gt;    &lt;li&gt;[SCM]* &lt;a href="http://tortoisesvn.tigris.org/"&gt;TortoiseSVN&lt;/a&gt; as windows shell extension for Subversion &lt;/li&gt;    &lt;li&gt;[SCM] &lt;a href="http://tortoisesvn.tigris.org/"&gt;VisualSVN&lt;/a&gt; for integration of TortoiseSVN into VS.&amp;#160; &lt;a href="http://ankhsvn.tigris.org/"&gt;Ankh&lt;/a&gt; is the best, free alternative I know of. &lt;/li&gt;    &lt;li&gt;[SCM]* &lt;a href="http://kdiff3.sourceforge.net/"&gt;KDiff3&lt;/a&gt; for merging &lt;/li&gt;    &lt;li&gt;[TDD]* &lt;a href="http://www.nunit.com" target="_blank"&gt;NUnit&lt;/a&gt; as preferred xUnit testing framework &lt;/li&gt;    &lt;li&gt;[TDD] &lt;a href="http://www.testdriven.net/"&gt;TestDriven.NET&lt;/a&gt; as test runner for &amp;quot;zero-friction unit testing&amp;quot;!&amp;#160; &lt;/li&gt;    &lt;li&gt;[TDD]* &lt;a href="http://code.google.com/p/moq/" target="_blank"&gt;moq&lt;/a&gt; as mock framework. &lt;/li&gt;    &lt;li&gt;[TDD] &lt;a href="http://www.ncover.org/"&gt;NCover&lt;/a&gt; for code coverage stats &lt;/li&gt;    &lt;li&gt;[CI]* &lt;a href="http://www.jetbrains.com/teamcity"&gt;TeamCity&lt;/a&gt; as build server &lt;/li&gt;    &lt;li&gt;[CI]* &lt;a href="http://www.codeplex.com/MSBuildExtensionPack" target="_blank"&gt;MSBuild Extension Pack&lt;/a&gt; for additional MSBuild tasks.&amp;#160; Also see the &lt;a href="http://msbuildtasks.tigris.org/"&gt;MSBuild.Community.Tasks&lt;/a&gt;.&amp;#160; &lt;/li&gt;    &lt;li&gt;[FR]* &lt;a href="http://logging.apache.org/log4net/"&gt;log4net&lt;/a&gt; as logging framework.&amp;#160; Also see &lt;a href="http://www.log4view.com"&gt;Log4View&lt;/a&gt; for an excellent UI for the log files. &lt;/li&gt;    &lt;li&gt;[FR]* &lt;a href="http://www.postsharp.org/"&gt;PostSharp&lt;/a&gt; as Aspect Oriented Programming framework &lt;/li&gt;    &lt;li&gt;[FR]* &lt;a href="http://ninject.org/"&gt;Ninject&lt;/a&gt; as IoC container &lt;/li&gt;    &lt;li&gt;[FR]* &lt;a href="http://www.nhibernate.org/"&gt;NHibernate&lt;/a&gt; as Object Relational Mapper.&amp;#160; &lt;a href="http://www.mindscape.co.nz/" target="_blank"&gt;MindScape LightSpeed&lt;/a&gt; also seems to be maturing very nicely. &lt;/li&gt;    &lt;li&gt;[UT]* &lt;a href="http://www.aisto.com/roeder/dotnet/"&gt;Reflector&lt;/a&gt; to drill down to the guts of any code library (also check-out the &lt;a href="http://www.codeplex.com/reflectoraddins"&gt;nice plug-ins&lt;/a&gt;) &lt;/li&gt;    &lt;li&gt;[UT] &lt;a href="http://silverlightspy.com/SilverlightSpy/StartPage2/"&gt;Silverlight Spy&lt;/a&gt; to dissect any Silverlight application. &lt;/li&gt;    &lt;li&gt;[UT] &lt;a href="http://www.regexbuddy.com/"&gt;RegexBuddy&lt;/a&gt; for managing those difficult regular expressions.&amp;#160; &lt;a href="http://tools.osherove.com/CoolTools/Regulator/tabid/185/Default.aspx"&gt;Regulator&lt;/a&gt; is the best, free alternative I know of.&amp;#160; &lt;/li&gt;    &lt;li&gt;[UT]* &lt;a href="http://www.sliver.com/dotnet/SnippetCompiler/"&gt;SnippetCompiler&lt;/a&gt; to quickly test snippets of .NET code. &lt;/li&gt;    &lt;li&gt;[UT]* &lt;a href="http://www.linqpad.net/"&gt;LINQPad&lt;/a&gt; as a easy way to query SQL databases using LINQ. &lt;/li&gt;    &lt;li&gt;[UT]* &lt;a href="http://www.fiddlertool.com/"&gt;Fiddler&lt;/a&gt; to debug all your HTTP traffic in IE.&amp;#160;&amp;#160; Also see the &lt;a href="http://blogs.msdn.com/nexpert/" target="_blank"&gt;neXpert plugin&lt;/a&gt; for monitoring performance problems. &lt;/li&gt;    &lt;li&gt;[UT]* &lt;a href="http://www.nikhilk.net/Project.WebDevHelper.aspx"&gt;Web Development Helper&lt;/a&gt; to assist with testing ASP.NET applications running in IE.&amp;#160; Also see the &lt;a href="http://blogs.msdn.com/ie/archive/2007/05/10/Internet-Explorer-Developer-Toolbar-_2D00_-Get-It-Now_2100_.aspx"&gt;IE Developer Toolbar&lt;/a&gt; for additional IE web development tools. &lt;/li&gt;    &lt;li&gt;[UT]* &lt;a href="http://www.getfirebug.com/"&gt;Firebug&lt;/a&gt; to assist with testing web applications running in Firefox. Also see &lt;a href="http://developer.yahoo.com/yslow/"&gt;YSlow&lt;/a&gt; add-on for performance testing and &lt;a href="https://addons.mozilla.org/en-US/firefox/addon/60"&gt;Web Developer&lt;/a&gt; add-on for additional Firefox web development tools. &lt;/li&gt;    &lt;li&gt;[CA]* &lt;a href="http://www.google.co.za/url?sa=U&amp;amp;start=1&amp;amp;q=http://msdn.microsoft.com/en-us/library/bb429476.aspx&amp;amp;ei=U9BHSd6XOqKYxAGt5sRX&amp;amp;sig2=N9D4z3gzHOqK2vg7RWR3fg&amp;amp;usg=AFQjCNGJlgzqWLfbG6-EgF70_gLScoEWQA"&gt;FxCop&lt;/a&gt; to enforce .NET coding guidelines &lt;/li&gt;    &lt;li&gt;[CA] &lt;a href="http://www.ndepend.com"&gt;NDepend&lt;/a&gt; to get all the static code metrics I'd ever want &lt;/li&gt;    &lt;li&gt;[CA] &lt;a href="http://www.red-gate.com/products/ants_profiler/index.htm"&gt;ANTS Profiler&lt;/a&gt; for performance and memory profiling &lt;/li&gt;    &lt;li&gt;[MD] &lt;a href="http://www.sparxsystems.com/"&gt;Enterprise Architect&lt;/a&gt; to do UML Modelling and Model Driven Design if required. Alternatively use Visio with these &lt;a href="http://www.softwarestencils.com/uml/index.html"&gt;simple templates&lt;/a&gt;.&amp;#160; &lt;/li&gt;    &lt;li&gt;[MD]* &lt;a href="http://freemind.sourceforge.net"&gt;FreeMind&lt;/a&gt; as mind mapping tool &lt;/li&gt;    &lt;li&gt;[TC]* &lt;a href="http://www.screwturn.eu"&gt;ScrewTurn Wiki&lt;/a&gt; for team collaboration &lt;/li&gt;    &lt;li&gt;[QA]* &lt;a href="http://www.soapui.org"&gt;Eviware soapUI&lt;/a&gt; for testing of SOA web services &lt;/li&gt;    &lt;li&gt;[QA]* &lt;a href="http://www.artoftest.com/home.aspx"&gt;WebAii&lt;/a&gt; for automated regression testing of Web 2.0 apps &lt;/li&gt;    &lt;li&gt;[DP]* &lt;a href="http://wix.sourceforge.net/"&gt;Windows Installer XML (WiX)&lt;/a&gt; for creating Windows Installers &lt;/li&gt; &lt;/ol&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4775121157402872976-2950548967276587544?l=fromthedevtrenches.blogspot.com'/&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/FromTheSoftwareDevelopmentTrenches/~4/uN9lsyZVQcg" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://fromthedevtrenches.blogspot.com/feeds/2950548967276587544/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://fromthedevtrenches.blogspot.com/2009/10/ultimate-net-development-tools.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4775121157402872976/posts/default/2950548967276587544?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4775121157402872976/posts/default/2950548967276587544?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/FromTheSoftwareDevelopmentTrenches/~3/uN9lsyZVQcg/ultimate-net-development-tools.html" title="Ultimate .NET development tools" /><author><name>Carel Lotz</name><uri>http://www.blogger.com/profile/13701537592037249529</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="05471999821481181728" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://fromthedevtrenches.blogspot.com/2009/10/ultimate-net-development-tools.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEcMRHk8cSp7ImA9WxNUEE8.&quot;"><id>tag:blogger.com,1999:blog-4775121157402872976.post-6166389751475967969</id><published>2009-10-31T22:48:00.001+02:00</published><updated>2009-10-31T22:48:05.779+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-10-31T22:48:05.779+02:00</app:edited><title>Migrating blog onto Blogger</title><content type="html">&lt;p&gt;I am in the process of migrating my &lt;a href="http://dotnet.org.za/cjlotz"&gt;old blog&lt;/a&gt; onto blogger as the &lt;a href="http://dotnet.org.za/"&gt;current host&lt;/a&gt; seems to be extremely slow these days with a lot of spam information as well.&amp;#160; Those of you using my &lt;a href="http://feeds.feedburner.com/FromTheSoftwareDevelopmentTrenches"&gt;FeedBurner subscription&lt;/a&gt; won’t have to do a thing as I’ve rerouted it to my &lt;a href="http://fromthedevtrenches.blogspot.com/"&gt;new blogger site&lt;/a&gt;.&amp;#160; I’ll be re-posting some of the most popular content of my old blog just to ensure the continuity of the information going forward.&amp;#160; Sorry for the inconvenience :-|&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4775121157402872976-6166389751475967969?l=fromthedevtrenches.blogspot.com'/&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/FromTheSoftwareDevelopmentTrenches/~4/X87ZpwCFOXA" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://fromthedevtrenches.blogspot.com/feeds/6166389751475967969/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://fromthedevtrenches.blogspot.com/2009/10/migrating-blog-onto-blogger.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4775121157402872976/posts/default/6166389751475967969?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4775121157402872976/posts/default/6166389751475967969?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/FromTheSoftwareDevelopmentTrenches/~3/X87ZpwCFOXA/migrating-blog-onto-blogger.html" title="Migrating blog onto Blogger" /><author><name>Carel Lotz</name><uri>http://www.blogger.com/profile/13701537592037249529</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="05471999821481181728" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://fromthedevtrenches.blogspot.com/2009/10/migrating-blog-onto-blogger.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkUFRH09cCp7ImA9WxNUEUU.&quot;"><id>tag:blogger.com,1999:blog-4775121157402872976.post-3739806155228490080</id><published>2009-10-31T16:53:00.001+02:00</published><updated>2009-11-02T20:56:55.368+02:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-11-02T20:56:55.368+02:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="TeamCity" /><category scheme="http://www.blogger.com/atom/ns#" term="Silverlight" /><title>Integrating your Silverlight Test Run Results into TeamCity</title><content type="html">&lt;p&gt;We’ve &lt;a href="http://dotnet.org.za/cjlotz/archive/2008/08/01/net-continuous-integration-servers.aspx"&gt;been using&lt;/a&gt; &lt;a href="http://www.jetbrains.com/teamcity"&gt;TeamCity&lt;/a&gt; with great success &lt;a href="http://www.pragma.co.za/"&gt;at our company&lt;/a&gt; to do &lt;a href="http://dotnet.org.za/cjlotz/archive/2007/12/03/continuous-integration-from-theory-to-practice.aspx"&gt;continuous integration&lt;/a&gt;.&amp;#160; We have build configurations defined for building and deploying our On Key suite of software;&amp;#160; for running our suites of tests and also for generating our static code analysis metrics.&amp;#160; &lt;/p&gt;  &lt;h4&gt;Problem&lt;/h4&gt;  &lt;p&gt;One of the problems we faced was integrating the Silverlight UI test results generated using the Microsoft Silverlight Test Framework into TeamCity.&amp;#160; TeamCity comes with out-of-the-box support to automatically pick up and display the tests results generated by the NUnit and MSTest report formats.&amp;#160; However, the Microsoft Silverlight Test Framework works differently to NUnit and MSTest as it runs as a Silverlight application.&amp;#160; The same Silverlight security sandbox restrictions therefore also apply to the Silverlight Test Framework.&amp;#160; This makes it more difficult to get the test results out of the framework as the results are not written to a file like NUnit or MSTest.&amp;#160; Fortunately TeamCity allows you to integrate the test results of any framework by writing special ServiceMessage commands as part of your build output.&amp;#160; TeamCity will listen for these commands and interpret and display the information as part of your build results on the portal.&amp;#160; &lt;/p&gt;  &lt;h4&gt;A Solution That Works&lt;/h4&gt;  &lt;p&gt;So we initially solved the problem by automating the test run and screen scraping the results from the Silverlight Test run page.&amp;#160; From the screen scraped results we created TeamCity Service Messages and wrote these messages as part of our build output.&amp;#160; I got the screen scraping idea from &lt;a href="http://jonas.follesoe.no/Silverlight2ContinuousIntegrationTestingUsingWatiN.aspx"&gt;this blog post&lt;/a&gt; by Jonas Follesoe.&amp;#160; This worked, but it was a clumsy solution at its best as parsing the html, looking for specific div’s to find out whether the tests failed or not was very error prone.&amp;#160; We also had no guarantee that the HTML format for the test report would stay the same between subsequent releases of the Silverlight Test Framework.&amp;#160; However, the real show stopper was that we ran into an issue with TeamCity when the tests failed.&amp;#160; The problem occurred because the test exception would contain invalid XML characters.&amp;#160; When TeamCity tried to run the failed tests, the XML RPC communication between the build agent and TeamCity server would fail due to the invalid characters in the XML stream.&amp;#160; This resulted in the build going into a loop as the TeamCity Server was not able to pick up any response from the Build Agent it was trying to run the build on. &lt;/p&gt;  &lt;h4&gt;A Solution That Rocks&lt;/h4&gt;  &lt;p&gt;Instead of trying to panelbeat the existing solution, I decided to investigate alternatives and started by using trusty &lt;a href="http://www.red-gate.com/products/reflector/"&gt;Reflector&lt;/a&gt; to look at the source code of the Silverlight Test Framework.&amp;#160; I wanted to see whether there was not a more elegant way in which to report on the test results.&amp;#160; (Btw, you don’t need to use Reflector – you can &lt;a href="http://www.codeplex.com/Silverlight/Release/ProjectReleases.aspx"&gt;download&lt;/a&gt; the source code of the Silverlight Test Framework as it is included as part of the &lt;a href="http://www.google.co.za/url?sa=t&amp;amp;source=web&amp;amp;ct=res&amp;amp;cd=1&amp;amp;ved=0CAcQFjAA&amp;amp;url=http%3A%2F%2Fwww.codeplex.com%2FSilverlight&amp;amp;ei=jgDrSqXpEJ_LjAfVlZSYDQ&amp;amp;usg=AFQjCNE3KhqMXblrj8wG_r6LWyRosJ5xzw&amp;amp;sig2=3HC9-0WOm8BVGrveEZLVmw"&gt;Silverlight Toolkit&lt;/a&gt;).&amp;#160; Sure enough, I discovered that the framework already included the necessary extensibility points for plugging in your own reporting mechanism.&amp;#160;&amp;#160; The &lt;strong&gt;LogProvider&lt;/strong&gt; base class provides the core API for creating your own logger that the Silverlight Test Framework will then call into for you to process the test results.&amp;#160; There is also a &lt;strong&gt;TestReportService&lt;/strong&gt; that seems like the mechanism to use to write the log output by exporting it via a service call.&lt;/p&gt;  &lt;p&gt;So the idea was to implement my own TeamCityServiceMessageLogProvider that would write the Test results into ServiceMessages that TeamCity understands.&amp;#160; The implementation turned out to be quite straightforward (&lt;a href="http://sites.google.com/site/fromthedevtrenches/downloads/TeamCityServiceMessageLogProvider.cs?attredirects=0&amp;amp;d=1"&gt;download from here&lt;/a&gt;).&amp;#160; The Logger opens up an IsolatedStorageFileStream and just writes the test results received to the stream.&amp;#160; You plug the logger into the Silverlight Test Framework by adding it as an additional LogProvider in your App startup:&lt;/p&gt;  &lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:57F11A72-B0E5-49c7-9094-E3A15BD5B5E6:e7c79e9a-35bf-4f24-be31-f5ebdb0be45d" class="wlWriterEditableSmartContent"&gt;&lt;pre style="background-color:#FFFFFF;white-space:-moz-pre-wrap; white-space: -pre-wrap; white-space: -o-pre-wrap; white-space: pre-wrap; word-wrap: break-word;overflow: auto;;font-family:Consolas;font-size:12"&gt;&lt;span style="color: #0000FF;"&gt;private&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000FF;"&gt;void&lt;/span&gt;&lt;span style="color: #000000;"&gt; Application_Startup(&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;object&lt;/span&gt;&lt;span style="color: #000000;"&gt; sender, StartupEventArgs e)
{
   AppSettings.Initialize();

   UnitTestSettings settings &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; UnitTestSystem.CreateDefaultSettings();
   settings.LogProviders.Add(&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;new&lt;/span&gt;&lt;span style="color: #000000;"&gt; TeamCityServiceMessageLogProvider());

   RootVisual &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; UnitTestSystem.CreateTestPage(settings);
}&lt;/span&gt;&lt;/pre&gt;&lt;!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --&gt;&lt;/div&gt;
So this took care of getting the results in the right format, but I still had to figure out how to get the results out of the Silverlight Test Framework into TeamCity. 

&lt;p&gt;Some further reflectoring showed that these extensibility areas also seemed to already exist within the Silverlight Test Framework, but I was unable to get them wired up and working correctly.&amp;#160; So I resorted to implementing my own solution by using a WebClient to upload the streamed results onto our web server for reporting to TeamCity. The first thing I had to do was to hook into the Publishing event of the Test framework to allow my custom logger to upload the results.&amp;#160; For this I had to implement the ITestSettingsLogProvider interface that provides an Initialize method that will be invoked by the Silverlight Test Framework.&amp;#160; I then hooked into the Publishing event as follows:&lt;/p&gt;

&lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:57F11A72-B0E5-49c7-9094-E3A15BD5B5E6:1cde30d3-7937-405d-91d2-8855130e88c5" class="wlWriterEditableSmartContent"&gt;&lt;pre style="background-color:#FFFFFF;white-space:-moz-pre-wrap; white-space: -pre-wrap; white-space: -o-pre-wrap; white-space: pre-wrap; word-wrap: break-word;overflow: auto;;font-family:Consolas;font-size:12"&gt;&lt;span style="color: #0000FF;"&gt;public&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000FF;"&gt;void&lt;/span&gt;&lt;span style="color: #000000;"&gt; Initialize(TestHarnessSettings settings)
{
  Settings &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; settings;
  UnitTestHarness testHarness &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; Settings.TestHarness &lt;/span&gt;&lt;span style="color: #0000FF;"&gt;as&lt;/span&gt;&lt;span style="color: #000000;"&gt; UnitTestHarness;
  &lt;/span&gt;&lt;span style="color: #0000FF;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt; (testHarness &lt;/span&gt;&lt;span style="color: #000000;"&gt;!=&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000FF;"&gt;null&lt;/span&gt;&lt;span style="color: #000000;"&gt;)
  {
    testHarness.Publishing &lt;/span&gt;&lt;span style="color: #000000;"&gt;+=&lt;/span&gt;&lt;span style="color: #000000;"&gt; ((sender, e) &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt; PostTestResults());
  }
  
  Store &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; IsolatedStorageFile.GetUserStoreForApplication();
  Stream &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; Store.CreateFile(LogFile);
  Writer &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000FF;"&gt;new&lt;/span&gt;&lt;span style="color: #000000;"&gt; StreamWriter(Stream);
}&lt;/span&gt;&lt;/pre&gt;&lt;!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --&gt;&lt;/div&gt;
In the PostTestResults method, I upload the results on to the server: 

&lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:57F11A72-B0E5-49c7-9094-E3A15BD5B5E6:1cc43bb0-f6d8-4ce0-912b-4dc066832bd1" class="wlWriterEditableSmartContent"&gt;&lt;pre style="background-color:#FFFFFF;white-space:-moz-pre-wrap; white-space: -pre-wrap; white-space: -o-pre-wrap; white-space: pre-wrap; word-wrap: break-word;overflow: auto;;font-family:Consolas;font-size:12"&gt;&lt;span style="color: #0000FF;"&gt;private&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000FF;"&gt;void&lt;/span&gt;&lt;span style="color: #000000;"&gt; PostTestResults()
{
   WebClient client &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000FF;"&gt;new&lt;/span&gt;&lt;span style="color: #000000;"&gt; WebClient();
   client.OpenWriteCompleted &lt;/span&gt;&lt;span style="color: #000000;"&gt;+=&lt;/span&gt;&lt;span style="color: #000000;"&gt; (sender, e) &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt;
                                {
                                    Stream input &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; e.UserState &lt;/span&gt;&lt;span style="color: #0000FF;"&gt;as&lt;/span&gt;&lt;span style="color: #000000;"&gt; Stream;
                                    Stream output &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; e.Result;

                                    &lt;/span&gt;&lt;span style="color: #0000FF;"&gt;byte&lt;/span&gt;&lt;span style="color: #000000;"&gt;[] buffer &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt;  &lt;/span&gt;&lt;span style="color: #0000FF;"&gt;new&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000FF;"&gt;byte&lt;/span&gt;&lt;span style="color: #000000;"&gt;[&lt;/span&gt;&lt;span style="color: #800080;"&gt;4096&lt;/span&gt;&lt;span style="color: #000000;"&gt;];
                                    &lt;/span&gt;&lt;span style="color: #0000FF;"&gt;int&lt;/span&gt;&lt;span style="color: #000000;"&gt; bytesRead &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #800080;"&gt;0&lt;/span&gt;&lt;span style="color: #000000;"&gt;;
                                    input.Position &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #800080;"&gt;0&lt;/span&gt;&lt;span style="color: #000000;"&gt;;
                                    &lt;/span&gt;&lt;span style="color: #0000FF;"&gt;while&lt;/span&gt;&lt;span style="color: #000000;"&gt; ((bytesRead &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; input.Read(buffer, &lt;/span&gt;&lt;span style="color: #800080;"&gt;0&lt;/span&gt;&lt;span style="color: #000000;"&gt;, buffer.Length)) &lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #800080;"&gt;0&lt;/span&gt;&lt;span style="color: #000000;"&gt;)
                                    {
                                        output.Write(buffer, &lt;/span&gt;&lt;span style="color: #800080;"&gt;0&lt;/span&gt;&lt;span style="color: #000000;"&gt;, bytesRead);
                                    }
                                    output.Close();
                                    input.Close();
                                };

   Writer.Flush();
   client.OpenWriteAsync(&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;new&lt;/span&gt;&lt;span style="color: #000000;"&gt; Uri(&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;http://localhost/OK52/UnitTest.aspx?Results=true&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;, UriKind.Absolute), &lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;POST&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;, Stream);
}&lt;/span&gt;&lt;/pre&gt;&lt;!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --&gt;&lt;/div&gt;
Notice the use of the &lt;em&gt;Results=true&lt;/em&gt; query string parameter. 

&lt;p&gt;On the server side, we have a UnitTest.aspx web page that we use as the start page for our Silverlight Tests.&amp;#160; A nice feature that I picked up &lt;a href="http://jonas.follesoe.no/EfficientTestingInSilverlight2UsingTags.aspx"&gt;from another excellent Jonas Follesoe post&lt;/a&gt; is that you can pass query string parameters onto the test page and use these as initialization parameters for your Silverlight application.&amp;#160; We use this to restrict the suite of tests being run by using the Tag feature of the Silverlight Test Framework -&amp;#160; i.e. &lt;a href="http://localhost/OK52/UnitTest.aspx?Tag=Staff"&gt;http://localhost/OK52/UnitTest.aspx?Tag=Staff&lt;/a&gt; to only run the Staff tests.&amp;#160; We also use this to configure the user that is logging on to the system – i.e. &lt;a href="http://localhost/OK52/UnitTest.aspx?Tag=Staff&amp;amp;User=Carel&amp;amp;Password=secret"&gt;http://localhost/OK52/UnitTest.aspx?Tag=Staff&amp;amp;User=Carel&amp;amp;Password=secret&lt;/a&gt;.&amp;#160; When reporting the test results, we post to the same UnitTest.aspx page but send through the &lt;em&gt;Results=true&lt;/em&gt; query string parameter to indicate that we want to upload the test results onto the server.&amp;#160; The results are then written to a file on the server for further processing as illustrated below:&lt;/p&gt;

&lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:57F11A72-B0E5-49c7-9094-E3A15BD5B5E6:e11946a4-497e-4d71-a0b0-6abd36b38233" class="wlWriterEditableSmartContent"&gt;&lt;pre style="background-color:#FFFFFF;white-space:-moz-pre-wrap; white-space: -pre-wrap; white-space: -o-pre-wrap; white-space: pre-wrap; word-wrap: break-word;overflow: auto;;font-family:Consolas;font-size:12"&gt;&lt;span style="color: #0000FF;"&gt;public&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000FF;"&gt;void&lt;/span&gt;&lt;span style="color: #000000;"&gt; Page_Load(&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;object&lt;/span&gt;&lt;span style="color: #000000;"&gt; sender, EventArgs e)
{
  &lt;/span&gt;&lt;span style="color: #0000FF;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt; (&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;string&lt;/span&gt;&lt;span style="color: #000000;"&gt;.IsNullOrEmpty(Request.QueryString[&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Results&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;]))
  {
    &lt;/span&gt;&lt;span style="color: #0000FF;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt; (&lt;/span&gt;&lt;span style="color: #000000;"&gt;!&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;string&lt;/span&gt;&lt;span style="color: #000000;"&gt;.IsNullOrEmpty(Request.QueryString[&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Tag&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;]))
    {
      Tests.InitParameters &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Tag=&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #000000;"&gt;+&lt;/span&gt;&lt;span style="color: #000000;"&gt; Request.QueryString[&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Tag&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;] &lt;/span&gt;&lt;span style="color: #000000;"&gt;+&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;,&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;;
    }
    &lt;/span&gt;&lt;span style="color: #0000FF;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt; (&lt;/span&gt;&lt;span style="color: #000000;"&gt;!&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;string&lt;/span&gt;&lt;span style="color: #000000;"&gt;.IsNullOrEmpty(Request.QueryString[&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;UserName&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;]))
    {
      Tests.InitParameters &lt;/span&gt;&lt;span style="color: #000000;"&gt;+=&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;UserName=&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #000000;"&gt;+&lt;/span&gt;&lt;span style="color: #000000;"&gt; Request.QueryString[&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;UserName&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;] &lt;/span&gt;&lt;span style="color: #000000;"&gt;+&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;,&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;;
    }
    &lt;/span&gt;&lt;span style="color: #0000FF;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt; (&lt;/span&gt;&lt;span style="color: #000000;"&gt;!&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;string&lt;/span&gt;&lt;span style="color: #000000;"&gt;.IsNullOrEmpty(Request.QueryString[&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Password&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;]))
    {
      Tests.InitParameters &lt;/span&gt;&lt;span style="color: #000000;"&gt;+=&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Password=&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #000000;"&gt;+&lt;/span&gt;&lt;span style="color: #000000;"&gt; Request.QueryString[&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;Password&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;] &lt;/span&gt;&lt;span style="color: #000000;"&gt;+&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;,&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;;
    }
    &lt;/span&gt;&lt;span style="color: #0000FF;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt; (&lt;/span&gt;&lt;span style="color: #000000;"&gt;!&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;string&lt;/span&gt;&lt;span style="color: #000000;"&gt;.IsNullOrEmpty(Request.QueryString[&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;DB&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;]))
    {
      Tests.InitParameters &lt;/span&gt;&lt;span style="color: #000000;"&gt;+=&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;DB=&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #000000;"&gt;+&lt;/span&gt;&lt;span style="color: #000000;"&gt; Request.QueryString[&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;DB&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;] &lt;/span&gt;&lt;span style="color: #000000;"&gt;+&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;,&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;;
    }
  }
  &lt;/span&gt;&lt;span style="color: #0000FF;"&gt;else&lt;/span&gt;&lt;span style="color: #000000;"&gt;
  {
    StreamReader inStream &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000FF;"&gt;new&lt;/span&gt;&lt;span style="color: #000000;"&gt; StreamReader(Context.Request.InputStream);
  
    &lt;/span&gt;&lt;span style="color: #0000FF;"&gt;string&lt;/span&gt;&lt;span style="color: #000000;"&gt; filePath &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; Server.MapPath(&lt;/span&gt;&lt;span style="color: #800000;"&gt;@"&lt;/span&gt;&lt;span style="color: #800000;"&gt;~\Logs\SLTests.log&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;);
    FileStream outstream &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; File.Open(filePath, FileMode.Create, FileAccess.Write);
    
    &lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; Read from the input stream in 4K chunks and save to output stream&lt;/span&gt;&lt;span style="color: #008000;"&gt;
&lt;/span&gt;&lt;span style="color: #000000;"&gt;    &lt;/span&gt;&lt;span style="color: #0000FF;"&gt;const&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000FF;"&gt;int&lt;/span&gt;&lt;span style="color: #000000;"&gt; bufferLen &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #800080;"&gt;4096&lt;/span&gt;&lt;span style="color: #000000;"&gt;;
    &lt;/span&gt;&lt;span style="color: #0000FF;"&gt;char&lt;/span&gt;&lt;span style="color: #000000;"&gt;[] buffer &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000FF;"&gt;new&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000FF;"&gt;char&lt;/span&gt;&lt;span style="color: #000000;"&gt;[bufferLen];
    &lt;/span&gt;&lt;span style="color: #0000FF;"&gt;int&lt;/span&gt;&lt;span style="color: #000000;"&gt; bytesRead &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #800080;"&gt;0&lt;/span&gt;&lt;span style="color: #000000;"&gt;;
    &lt;/span&gt;&lt;span style="color: #0000FF;"&gt;while&lt;/span&gt;&lt;span style="color: #000000;"&gt; ((bytesRead &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; inStream.Read(buffer, &lt;/span&gt;&lt;span style="color: #800080;"&gt;0&lt;/span&gt;&lt;span style="color: #000000;"&gt;, bufferLen)) &lt;/span&gt;&lt;span style="color: #000000;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #800080;"&gt;0&lt;/span&gt;&lt;span style="color: #000000;"&gt;)
    {
      outstream.Write(Encoding.UTF8.GetBytes(buffer, &lt;/span&gt;&lt;span style="color: #800080;"&gt;0&lt;/span&gt;&lt;span style="color: #000000;"&gt;, bytesRead), &lt;/span&gt;&lt;span style="color: #800080;"&gt;0&lt;/span&gt;&lt;span style="color: #000000;"&gt;, bytesRead);
    }
    outstream.Close();
    inStream.Close();
  }
}          &lt;/span&gt;&lt;/pre&gt;&lt;!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --&gt;&lt;/div&gt;
Once the file has been uploaded, it is a simple matter of echoing the test results back to the TeamCity server by writing it to the NUnit TestContext:&amp;#160; &lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:57F11A72-B0E5-49c7-9094-E3A15BD5B5E6:389c5ca1-095e-414b-bd09-80acf0bff681" class="wlWriterEditableSmartContent"&gt;&lt;pre style="background-color:#FFFFFF;white-space:-moz-pre-wrap; white-space: -pre-wrap; white-space: -o-pre-wrap; white-space: pre-wrap; word-wrap: break-word;overflow: auto;;font-family:Consolas;font-size:12"&gt;&lt;span style="color: #000000;"&gt;[TestFixture]
[Category(&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;UI&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;)]
&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;public&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000FF;"&gt;class&lt;/span&gt;&lt;span style="color: #000000;"&gt; RunOnKey5ClientIntegrationTests : BaseTest
{
  &lt;/span&gt;&lt;span style="color: #0000FF;"&gt;private&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000FF;"&gt;const&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000FF;"&gt;string&lt;/span&gt;&lt;span style="color: #000000;"&gt; OnKeyUri &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;http://localhost:80/OK52/UnitTest.aspx&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;;
  &lt;/span&gt;&lt;span style="color: #0000FF;"&gt;private&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000FF;"&gt;const&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000FF;"&gt;string&lt;/span&gt;&lt;span style="color: #000000;"&gt; LogPath &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #800000;"&gt;@"&lt;/span&gt;&lt;span style="color: #800000;"&gt;..\..\..\Pragma.OnKey5.Server\Logs\&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;;
  &lt;/span&gt;&lt;span style="color: #0000FF;"&gt;private&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000FF;"&gt;const&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000FF;"&gt;string&lt;/span&gt;&lt;span style="color: #000000;"&gt; SilverlightTestsLog &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #800000;"&gt;SLTests.log&lt;/span&gt;&lt;span style="color: #800000;"&gt;"&lt;/span&gt;&lt;span style="color: #000000;"&gt;;
  
  [Test]
  &lt;/span&gt;&lt;span style="color: #0000FF;"&gt;public&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000FF;"&gt;void&lt;/span&gt;&lt;span style="color: #000000;"&gt; RunSilverlightTests_UsingTeamCityServiceMessageLogger_ToShowResultsOnTeamCityPortal()
  {
    &lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; Clear the old results&lt;/span&gt;&lt;span style="color: #008000;"&gt;
&lt;/span&gt;&lt;span style="color: #000000;"&gt;    &lt;/span&gt;&lt;span style="color: #0000FF;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt; (File.Exists(LogPath &lt;/span&gt;&lt;span style="color: #000000;"&gt;+&lt;/span&gt;&lt;span style="color: #000000;"&gt; SilverlightTestsLog))
    {
      File.Delete(LogPath &lt;/span&gt;&lt;span style="color: #000000;"&gt;+&lt;/span&gt;&lt;span style="color: #000000;"&gt; SilverlightTestsLog);
    }
  
    &lt;/span&gt;&lt;span style="color: #0000FF;"&gt;using&lt;/span&gt;&lt;span style="color: #000000;"&gt; (FileSystemWatcher watcher &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000FF;"&gt;new&lt;/span&gt;&lt;span style="color: #000000;"&gt; FileSystemWatcher(LogPath, SilverlightTestsLog))
    {
      Manager.LaunchNewBrowser();
  
      &lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; Navigate to the VDir hosting the tests&lt;/span&gt;&lt;span style="color: #008000;"&gt;
&lt;/span&gt;&lt;span style="color: #000000;"&gt;      ActiveBrowser.NavigateTo(&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;new&lt;/span&gt;&lt;span style="color: #000000;"&gt; Uri(OnKeyUri));
  
      watcher.EnableRaisingEvents &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; &lt;/span&gt;&lt;span style="color: #0000FF;"&gt;true&lt;/span&gt;&lt;span style="color: #000000;"&gt;;
      WaitForChangedResult result &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; watcher.WaitForChanged(WatcherChangeTypes.Created);
      &lt;/span&gt;&lt;span style="color: #0000FF;"&gt;if&lt;/span&gt;&lt;span style="color: #000000;"&gt; (&lt;/span&gt;&lt;span style="color: #000000;"&gt;!&lt;/span&gt;&lt;span style="color: #000000;"&gt;result.TimedOut)
      {
          &lt;/span&gt;&lt;span style="color: #008000;"&gt;//&lt;/span&gt;&lt;span style="color: #008000;"&gt; Echo the TeamCity ServiceMessages so that the test results can be picked by the Portal&lt;/span&gt;&lt;span style="color: #008000;"&gt;
&lt;/span&gt;&lt;span style="color: #000000;"&gt;          &lt;/span&gt;&lt;span style="color: #0000FF;"&gt;string&lt;/span&gt;&lt;span style="color: #000000;"&gt;[] lines &lt;/span&gt;&lt;span style="color: #000000;"&gt;=&lt;/span&gt;&lt;span style="color: #000000;"&gt; File.ReadAllLines(LogPath &lt;/span&gt;&lt;span style="color: #000000;"&gt;+&lt;/span&gt;&lt;span style="color: #000000;"&gt; SilverlightTestsLog, Encoding.UTF8);
          &lt;/span&gt;&lt;span style="color: #0000FF;"&gt;foreach&lt;/span&gt;&lt;span style="color: #000000;"&gt; (&lt;/span&gt;&lt;span style="color: #0000FF;"&gt;string&lt;/span&gt;&lt;span style="color: #000000;"&gt; line &lt;/span&gt;&lt;span style="color: #0000FF;"&gt;in&lt;/span&gt;&lt;span style="color: #000000;"&gt; lines)
          {
              TestContext.Out.WriteLine(line);
          }
      }
    }
  }
}&lt;/span&gt;&lt;/pre&gt;&lt;!-- Code inserted with Steve Dunn's Windows Live Writer Code Formatter Plugin.  http://dunnhq.com --&gt;&lt;/div&gt;
You’ll notice that the whole test run is managed as a NUnit test fixture that is flagged with “UI” as a Category.&amp;#160; This allows me to use the &lt;em&gt;nunit-console.exe&lt;/em&gt; to run the specific tests using the &lt;em&gt;/include=UI&lt;/em&gt; command line parameter.&amp;#160; I use the &lt;strong&gt;FileSystemWatcher&lt;/strong&gt; class to wait until the SLTests.log file has been published and them echo the results to TeamCity by writing it to the NUnit TestContext. 

&lt;h4&gt;Conclusion&lt;/h4&gt;

&lt;p&gt;I hope you’ll find this information useful for publishing the results of your own Silverlight Test Runs during your automated builds.&amp;#160; Jeff Wilcox has mentioned that more of the build automation extensibility points of the Silverlight Test Framework will be made known in future releases.&amp;#160; Until such time this is one way of doing it.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/4775121157402872976-3739806155228490080?l=fromthedevtrenches.blogspot.com'/&gt;&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/FromTheSoftwareDevelopmentTrenches/~4/Fu8A2IFjZyg" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://fromthedevtrenches.blogspot.com/feeds/3739806155228490080/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://fromthedevtrenches.blogspot.com/2009/10/integrating-your-silverlight-test-run.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/4775121157402872976/posts/default/3739806155228490080?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/4775121157402872976/posts/default/3739806155228490080?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/FromTheSoftwareDevelopmentTrenches/~3/Fu8A2IFjZyg/integrating-your-silverlight-test-run.html" title="Integrating your Silverlight Test Run Results into TeamCity" /><author><name>Carel Lotz</name><uri>http://www.blogger.com/profile/13701537592037249529</uri><email>noreply@blogger.com</email><gd:extendedProperty name="OpenSocialUserId" value="05471999821481181728" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total><feedburner:origLink>http://fromthedevtrenches.blogspot.com/2009/10/integrating-your-silverlight-test-run.html</feedburner:origLink></entry></feed>
