Terje Sandstrom

------ Chief Software Geek at Inmeta Consulting in Scandinavia ----- and a Visual Studio ALM MVP

  Home  |   Contact  |   Syndication    |   Login
  59 Posts | 1 Stories | 95 Comments | 0 Trackbacks

News

Subscribe

Delicious Save this on Delicious Visual Studio Feeds

¨

Tag Cloud


Article Categories

Archives

Post Categories

Image Galleries

Company stuff

Interesting bloggers

Interesting companies

Microsoft

Microsoft Norge

Microsoft Regional Directors

Microsoft Test

MSFT Blogs

MVP

NNUG

Other interesting stuff

TFS

Visual Studio

When I do either Code Analysis, Code Metrics or looking at Code Coverage results, I don't want to have any generated code affecting the results.  It just confuses the numbers, and I do not really care how generated code looks - it should just be invisible. 

Generated code appears several places, code is generated by any of the multitude of wizards and designers in Visual Studio, or it may be generated by a 3rd part tool or generated by a self-written tool.

There exist an attribute which, if attached to the class or method, is intended to hide the code from these analyses. However, it fails to do so for the Code Coverage.  The attribute is the GeneratedCodeAttribute, and it is intended to be used for any tools generated code.  See http://blogs.msdn.com/fxcop/archive/2007/04/27/correct-usage-of-the-compilergeneratedattribute-and-the-generatedcodeattribute.aspx for more information on the correct usage.  It can be used both at class level and method level.

However, the Code Coverage doesn't abide by these rules, as also reported in a two bug reports http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=338895 and http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=349243.  The latter indicate they will not fix this bug,  so please go in a vote for a fix!

As a workaround there are two more attributes which can be used, the DebuggerNonUserCode and DebuggerHidden attributes. The former is a combination of the latter and the DebuggerStepThrough attribute.  The DebuggerNonUserCode attribute can be used on both class and method level.

By using this attribute in addition on generated code, it will not show up in the Code Coverage either.

The table below summarizes this:

  GeneratedCodeAttribute DebuggerNonUserCode

DebuggerHidden

Code Metrics Excludes code No Effect
Code Analysis Excludes code No Effect
Code Coverage No Effect Excludes code

 

 

Further, Microsoft seems to have "forgotten" to add these attributes to some of their own generated code, among them is the Winform generated code. The MSDataSetGenerator adds the GeneratedCode attrbute, but not the DebuggerNonUserCode attribute. (If the Code Coverage had abided by the rules, this would not have been a problem)

For Winform generated code, it is safe to add these attributes afterwards. The generated file will not be rewritten, just changed, when you add more or edit the controls. Just add them as shown below:

 

        [DebuggerNonUserCode]
        [GeneratedCode("Winform Designer","VS2008 SP1")]
        private void InitializeComponent()
 

The MSDataSetGenerator is not so forgiving, since the file easily can be rewritten. However, all the classes are partial, so by adding another manual file, and using the attributes there, most of the DataSet can be removed from the Code Coverage.  Adding one dataset with one table generates a lot of classes, the code below shows what is needed to eliminate a dataset and its tableadapter for a table named ErrorLog.

namespace WindowsFormsApplication10
{
    [DebuggerNonUserCode]
    public partial class DataSet1
    {
        [DebuggerNonUserCode]
        public partial class ErrorLogDataTable
        {
        }
 
        [DebuggerNonUserCode]
        public partial class ErrorLogRow
        {
        }
 
    }
 
    namespace DataSet1TableAdapters
    {
        [DebuggerNonUserCode]
        public partial class ErrorLogTableAdapter
        {
        }
 
        [DebuggerNonUserCode]
        public partial class TableAdapterManager
        {
        }
    }
}

 

In my little test case, code coverage changed from 2,54% to 10% just by removing the DataSet1 alone.

Under the Properties folder (for a WinForm app), the Resources class is decorated with both attributes (Hurrah!) (luckily since it's not partial....) whereas the Settings class only have the GeneratedCode attribute. (Why are these two different ?).  The Settings.Designer.cs file is regenerated each time you change anything in the settings designer, but it is partial, so the same trick as above with the DataSet can be used - create a new file, with the same partial class declaration, and add the DebuggerNonUserCode to it.

 

In a later post I'll try to make an even more comprehensive list of which generators work and which doesn't, in this respect, and outline the workarounds for these.

Hopefully - all of these will be fixed in Visual Studio 2010.

posted on Monday, November 10, 2008 3:09 AM