Have you ever had to take over a project, fix a bug, or code a feature? How often have you felt uncertain, lost, or upset? How many times have you wanted to find the guy who wrote the piece of code you’re working on and … thank him warmly? See figure 1. If you’re living in the same world as we are, it’s happened to you at least few times.
|This article is based on Continuous Integration in .NET, published October, 2009. It is being reproduced here by permission from Manning Publications. Manning early access books and ebooks are sold exclusively through Manning. Visit the book’s page for more information.
Developer Tutorial readers can get 30% off any version (ebook or print book) of Continuous Integration in .NET. Simply use the code “devtut30” at checkout. Offer expires March 31, 2010.
Do you ever wonder why you felt like this? Is it because the code didn’t do what it was supposed to do? If it wasn’t a bug, it was probably something else. The software smelled. And nothing is worse than smelly code. The good news is you’re not the first one who thought about it. There are static code analysis tools that help to ensure your code doesn’t smell. FxCop analyzes the IL code, StyleCop does the same with C#, and NDepend goes over IL using special code-query language. FxCop is the most popular of the three, so let’s look at how to use it and how to do a continuous code analysis with it.
Analyzing object code with FxCop
FxCop is a free Microsoft tool for code analysis. It examines the compiled .NET assemblies for things like performance, naming conventions, library design, globalization, and security. Oftentimes these types of issues aren’t found until either your customer tries to run the application or you attempt to maintain or enhance the code.
FxCop started as a standalone program that enforced the rules from â€œDesign Guidelines for Class Library Developers,â€1 a document that contains good coding practices for developers writing .NET code. FxCop was incorporated into Visual Studio Team System 2008 and Visual Studio Premium 2010 as Code Analysis. The good news is, it’s still available as a standalone program, which will be helpful in our CI scenario. Let’s have a look at FxCop in action.
Using Visual Studio Code Analysis
If you have an edition of Visual Studio 2010 that includes Code Analysis, using Code Analysis is quite straightforward. Go to Project Properties, switch to the Code Analysis tab, and switch on the flag Enable Code Analysis on Build. See Figure 2.
Figure 2. FxCop is built into Visual Studio 2010 Premium and Ultimate Editions as Code Analysis.
The good folks at Microsoft suggest that by default you use the Microsoft Minimum Recommended Rules. But it’s up to you what set of rules to use. You can even define your own. Keep in mind that the rules come from a document that contains the word Guidelines in its title. It’s your choice as to which rules you use and which ones you ignore. What’s important is that you’re making a conscious decision about this. You can see the rules that are working if you click Open. You can modify the list according to your needs and save the output file for future use in other projects (figure 3).
Figure 3 When you define a set of Code Analysis rules in Visual Studio 2010, you need to save them to a rule set file so they can be applied to the project.
You can decide which rules will break your build and which will only be compiler warnings. Unfortunately, at the time of writing this article with Visual Studio 2010, Beta 2, the Treat Warnings as Errors project property wasn’t working with Code Analysis. Once you turn on Code Analysis, every time your project compiles, the analysis will be run.
But what about situations where you want to generally check some rule, but in some particular place you’re sure you’ve broken it? To do this you can use suppressions. FxCop messages can be suppressed directly in the code where they occur or in a global suppression file. Visual Studio comes with a neat functionality to make is easier. To suppress a particular issue, right-click it in the Error List window and select Suppress Message(s) (figure 4).
Figure 4 Suppressing a Code Analysis message right out of the Error List window in Visual Studio 2010.
Using Code Analysis is all fine and good, but what if it isn’t included in your edition of Visual Studio or you need to have it running automatically on the CI server? The answer is to use FxCop.
Setting up continuous FxCop code analysis
As you’ve seen, FxCop was dressed up nicely as Code Analysis and migrated to Visual Studio. Fortunately, the FxCop source project didn’t die; it’s still actively supported. Even if you don’t have the full-blown Visual Studio, you can still use FxCop, but you’ll have to download2 and install it. It won’t be as friction free as Visual Studio Code Analysis, but it’s still doable. Using standalone FxCop you can customize your CI process as you wish. And using the FxCop GUI (figure 5), you can do just everything that’s possible with Code Analysis in Visual Studio.
FxCop stores information about the assemblies that it needs to analyze in an FxCop project. You’ll recognize the file by its .FxCop extension. It’s created automatically as you add your .NET assemblies into the FxCop GUI. You need to remember to save the FxCop project into the same directory as your .NET solution so that it can be checked into your source code repository, where the CI process can grab it.
Let’s configure our CI server to analyze our code. First, take the standalone FxCop tool and copy it to the tools subdirectory. You should copy only the files that are needed on the CI server. One important file is the FxCop command-line tool, FxCopCmd.exe.
Next, you need to extend the MSBuild project file with a new Code Analysis task; then you can directly use the MSBuild Exec task with FxCopCmd.exe. An MSBuild community task automates the use of command-line FxCop (see http://msbuildtasks.tigris.org/).
When running FxCop as part of your CI process, you need to consider two issues with FxCop. First, if you’re picky about the rules you’re using, it’s better to manage them visually in the FxCop GUI. Second, getting information about the rules violations isn’t as straightforward as it could be.
The command-line tool, FxCopCmd, is able to take either the list of assemblies to analyze and the list of rules to be checked or the FxCop project as an input parameter. If you’re not picky about the rules you want to check, the command to check your assembly is pretty clear:
tools\FxCop\FxCopCmd.exe /f:CiDotNet.Calc/bin/Debug/CiDotNet.Calc.dll [CA]/r:tools/FxCop/Rules /console
This will take any library (CiDotNet.Calc.dll in this case) and run it through FxCop using all the rules from the tools/FxCop/Rules directory. The /console switch tells FxCopCmd to output everything to the console. If you want to write the output to a file, you need to specify the filename with
If you’re more picky about which rules to use and which to leave out, you can use the /ruleid parameter along a the +/- notation to indicate which rules to include (put a + sign in front of them) or ignore (put a â€“ sign in front of them). For example, to ignore some rules put a – sign before their category and ID number (written Category#Id), like this:
tools\FxCop\FxCopCmd.exe /f:CiDotNet.Calc/bin/Debug/CiDotNet [CA].Calc.dll /r:tools/FxCop/Rules /ruleid:-Microsoft.Design#CA2210 [CA]/console
This will turn off the rule that says you have to assign a strong name for your assembly. You can customize this call as you wish, but it’ll require a bit of work. It’s a lot easier to take the FxCop GUI and filter the assemblies visually, as shown in figure 6.
Figure 6. Filtering FxCop rules. If you feel the need to follow only some of the FxCop rules, it’s easier to choose them visually and use the FxCop project file with command line than to write a long FxCopCmd command.
Let’s say you’ve configured your FxCop project and saved it as CiDotNet.FxCop. You can now use it with FxCopCmd.exe:
tools\FxCop\FxCopCmd.exe /project:CiDotNet.FxCop /out:FxCopReport.xml
Unfortunately, the assemblies you want to analyze are hard-coded to the FxCop project file. It doesn’t matter whether you choose to have the relative or the absolute path to the targets or whether you’re using the standard Debug or Release scenario; you’ll end up with one of the output directories being written into the FxCop project file:
[CA]Analyze="True" AnalyzeAllChildren="True" />
One way to resolve this is to have two FxCop project files, one for Debug and one for Release. If you want to vary the analysis for both scenarios (not recommended from our experience because Release tends to be neglected by developers), it should work for you. If not, you’ll have to think about a different solution.
MSBuild comes with a possible solution: the Community Tasks FileUpdate. You can use it to change the assembly directory in the FxCop project file in a CI scenario, as shown in listing 1.
Replace #1, #2, and #3 in the following paragraph with cueballs
First, we import the Community Task #1 to use to update the paths #2 according to the current configuration. We then call FxCopCmd #3 to perform the analysis.
We generally recommend that you incorporate all the rules provided and then exclude specific rules that you think aren’t important. Nevertheless, if you’re picky, you can incorporate our solution.
But as you’ll see by starting the MSBuild script, it’ll end up without an error or a warning even if there are rules violations in your code. This isn’t acceptable because you can bet that if the rules violations don’t break the build, no one will bother to obey the rules at all. You can’t expect the developer to check the FxCop results for a working build. You have to break the build in order for the rules to be obeyed. Unfortunately, FxCopCmd doesn’t provide a straightforward way to do it. The
ContinueOnError property in the Exec task reacts only to exceptions during the ExCopCmd run and not to the broken rules. One of the options is to read the XML output of FxCopCmd to find the violations. But there’s an easier way. FxCopCmd produces an output file only if there’s something to report, such as broken rules. If the file exists, you can safely break the build, like this:
<Exec Command=”tools\FxCop\FxCopCmd.exe /project:CiDotNet.FxCop
Text=”FxCop found some broken rules!” />
You’re now fully prepared to integrate Code Analysis with your CI server of choice. Let’s find out how to do it.
Integrating FxCop with CI servers
CruiseControl.NET takes XML files and shows them on the Dashboard page. Fortunately, it comes with an XSD file to perform the transformation to HTML format. Make sure you have this line in your dashboard.config file in order to include the FxCop XSD file:
<xslReportBuildPlugin description="FxCop Report"
You also need to merge the FxCopCmd output report file into the Dashboard, as follows:
After you check everything into your source code repository, it should all work fine and you’ll be able to see the FxCop report, as shown in figure 7.
Figure 7 An FxCop analysis report on the CCNet Dashboard page. The output from FxCopCmd is formatted using the XSD file supplied by CCNet to provide an easily readable report.
Integration with TeamCity required an HTML file to merge with the TeamCity web page. FxCopCmd can produce an HTML file instead of the standard XML file. You only need to modify the call:
tools\FxCop\FxCopCmd.exe /project:CiDotNet.FxCop /out:FxCopReport.html [CA]/axsl
The axsl parameter tells FxCopCmd to apply the XSL style sheet right away and produce HTML output. When that’s done, you’re ready to add a new tab to the TeamCity website. You’ll have to define a new artifact FxCopReport.html file and a new tab server configuration. You’ll end up with this page being a part of the TeamCity build report (figure 8).
Figure 8 An FxCop analysis report in TeamCity
If you’re using TFS 2010 as your CI server, you’re probably using the built-in Code Analysis tools. You can turn on Code Analysis even without the Visual Studio 2010 Premium Edition. It’s a matter of adding a line to the project file:
You can also optionally specify the rule set to use:
You won’t be able to benefit from Code Analysis right away on your development machine, but TFS 2010 will snap in and perform the check for you when it performs a build. In the end, you’ll get what you need. Figure 8.9 shows the TFS build report.
Figure 9 The TFS build report with Code Analysis output on the Build summary page. If you want to break the build on a given violation, change the action to Error.
FxCop does a great job of checking the conformance of your assemblies to the Microsoft .NET Framework Design Guidelines.
From our experience, we know that projects tend to grow. Developers have a tendency to add new lines of code to their projects. They sometimes even change the old lines of code to fix something. Some projects live many years and are modified by many developers. Developers usually want to know what’s going on in the project, but when they change the code, they’re contributing to project growth.
But what if they’re coming to a project that looks like a great ball of mud? One class may be developed with great Cobol influence and look like functional programming. There may be lines of 1,000 characters, or a previous developer may have used one-character-long variable names. It’s a pain to work with smelly code. The only way out of it is to enforce some rules. Many software shops have written coding guidelines. But having the rules doesn’t mean they’ll be obeyed. Developers are only human. They’re working under time pressure, and sometimes they neglect or don’t even understand the rules. Only if the coding rules are enforced on project will they be obeyed.
There’s nothing better than static code analysis to check the rules. Tools like FxCop are great guards against bad coding habits. Using static code analysis as part of your CI process will effectively fight any smell in the code you choose, even the code only you can smell. You have to write your own rules; you need to guard against that violent psychopath.