Use attribute to omit code from coverage analysis in Visual Studio - visual-studio

I have some classes that, for one reason or another, cannot be or need not be unit tested. I'd like to exclude these classes from my coverage metrics so that I can get a better feel for the coverage on the classes I actually care about. Right now I have to exclude the results after the fact. What I would like to do is use an attribute to mark those classes as excluded so that they aren't included to begin with. Is there any way to decorate a class with an attribute that will automatically exclude it from coverage analysis? Either VS coverage analysis or nCover will work.
FWIW, these are classes that I can assure myself by inspection that the code is correct. Mostly they are wrapper classes around existing framework classes that I've introduced in order to be able to mock the framework class out. Since the wrapper's get mocked out they don't get tested. That's ok because all they do is wrap the framework class' methods that I care about.

Starting with VS2010 we have ExcludeFromCodeCoverageAttribute. Commenters have noted this to work in NCover as well as DotCover + NUnit. Example usage:
[ExcludeFromCodeCoverage]
public class myUntestableClass
{ }
Also see this link. They suggest using VSInstr as command line tool, it have /EXCLUDE options (it's not as handy).

I've found some information on a couple of Diagnostics attributes DebuggerNonUserCodeAttribute and DebuggerHiddenAttribute that indicates that using these attributes will cause the coverage analyzer in VS to leave these out of its results. I've tried it with the DebuggerNonUserCodeAttribute and it seems to work. I can probably live with this for most of the classes that I'm thinking of, though I don't like the side effect of not being able to step into these classes. That shouldn't be a problem for the wrapper classes, but it may end up being so with classes that are inherently hard to test and I need debugger access to.
I'm still looking for alternatives, though.

With NCover you can create an attribute and then tell NCover to ignore that attribute.
In our projects, we have defined this attribute (no namespace, so it is easy to use):
public class CoverageExcludeAttribute : Attribute { }
We use NAnt, so we have a target that looks like this:
<target name="unittests" description="run nunit tests" >
<ncover
....
excludeAttributes="CoverageExcludeAttribute"
/>
</target>
Question 9 in the NCover FAQ describes this method. We based our solution on this.
Alternatively, you can use the exclude feature of the NCoverExplorer to exclude namespaces and assemblies from the final report. This merely removes the data from the report, but the end result is the same.
We use both techniques.

This work for me! 👍
use in .csproj: sonar keys
<ItemGroup>
<SonarQubeSetting Include="sonar.issue.ignore.allfile">
<Value>ExcludeFromCodeCoverage</Value>
</SonarQubeSetting>
</ItemGroup>
or
<ItemGroup>
<SonarQubeSetting Include="sonar.coverage.exclusions">
<Value>**/FileClassToExclude.cs</Value>
</SonarQubeSetting>
</ItemGroup>
And then use in your class file .cs by ExcludeFromCodeCoverage from microsoft
[ExcludeFromCodeCoverage]
public class ExcludeMeFromSonarCoverage
{
public ExcludeMeFromSonarCoverage()
{
}
}

Related

TFS/C#: Logging a custom warning during the build process

I am hacking around a problem we've created for ourselves. What I would like to do is log a warning in our TFS builds for any code that is instantiating a specific class. I don't want a run time warning (I've got one in place already), I want a build time warning that ProjectX is using BadClass.cs. The idea being it will give us an additional place to see things that need to be fixed once our hack is no longer needed.
So something like this:
public class BadClass
{}
public class OkClass
{}
public class MyBadService
{
var a = new BadClass(); <-- Logs a warning to the build output
}
public class MyOkService
{
var a = new OkClass(); <-- Does not log a warning
}
Edit:
I do not like the idea of using Obsolete; its a misnomer. We've already got code with Obsolete attributes and this would get lost in the noise. I don't want a generic warning that I can't control the message for. I want bright neon signs with klaxons firing and a thousand exclamation points in the message. Basically everything I can do short of failing the build. I'm using the #warning precompiler directive right now and its mostly doing what I want but it requires a human to remember to add the warning. I'm looking for something more automagic. I've seen third party libraries do stuff like this so I know its possible.
Why not just use the Obsolete attribute? It can generate a build warning for you:
https://learn.microsoft.com/en-us/dotnet/api/system.obsoleteattribute?view=netframework-4.8
You can even make it emit an error too if you want.
The answer could be negative I think.
It seems that you use or call msbuild.exe to build your C# projects. But as far as I know, MSBuild in fact calls csc.exe to build C# projects in build time.
So actually what you want is logging a warning when the compiler compile the C# code if it recognize somewhere in your code uses the BadClass in build time.
If you have the source code of BadClass in the same solution, add a project reference format to the xx.csproj which contains BadClass, and set a #warning in the BadClass it may generate the warning in build time.
But I think the scenario you're in is something like: You developed one Assembly and distribute it to your user, so you want it generates a warning when the user calls one BadClass in your assembly and builds his own project to remind him of taking care when using this bad class. If so, this is impossible for msbuild AFAIK. If I misunderstand anything, feel free to know me know :)
Update:
As Daniel and Johnson said, ObsoleteAttribute is enough to do this. Though no valid way to generate warnings from msbuild aspect directly, but msbuild will call C# compiler during build process, so generates a compiler warning can output to build output window.

NUnit Not Utilizing Paramaters and Settings in .runsettings File

I'm trying to switch over an existing Selenium solution to use NUnit due to it's support of parallelization of tests within the same class. The problem I'm having is that it doesn't seem to be using the selected .runsettings file, despite the fact that it's supported by NUnit. By this, I mean that TestContext.Parameters.Count is always 0, and it doesn't store results in the path specified in the <ResultDirectory> node of my .runsettings file.
I've looked over the documentation and the reference to AdapterSettings (which has logic for parsing the .runsettings file) and I can't f figure out why my TestContext.Paramaters are never populated in my test when I use a .runsettings file.
I created a bare-bones test solution just as a sanity check and POC and it's still not populating.
I have
-NUnit 3.7.1
-NUnit3TestAdapter 3.7.0
-VisualStudio Professional 2017
My .runsettings file is:
<?xml version="1.0" encoding="utf-8"?>
<RunSettings>
<!-- Parameters used by tests at runtime -->
<TestRunParameters>
<Parameter name ="testParameter1" value="value1" />
<Parameter name ="testParameter2" value="value2" />
</TestRunParameters>
</RunSettings>
All I'm trying to do in the test:
using System;
using NUnit.Framework;
namespace ClassLibrary1
{
[TestFixture]
public class UnitTestClass1
{
[Test]
[Parallelizable(ParallelScope.All)]
public void Class1TestMethod1()
{
// Below always returns 0
Console.WriteLine(TestContext.Parameters.Count);
// Below returns null
Console.WriteLine(TestContext.Parameters["testParameter1"]);
}
}
}
I could really use some other suggestions on how to troubleshoot. We use .runsettings files extensively for our test suite with the built-in Visual Studio Unit Testing tools (and with vstest.console.exe), so I'm pretty confident I'm using it correctly.
Update:
I replaced all references to Visual Studios test attributes in my actual test solution to use NUnits attributes. Now I'm getting the parameters! However, that leaves me still baffled as to why it doesn't work in my other bare-bones solution (with files shown above).
I really only care about my real solution obviously, but I still want to understand why it's not working in my dummy solution.
Also - I still am not sure where to find the TestResultDirectory path in NUnit.

How does NCover coverage report handle MSTest accessors?

MSTest + Visual Studio generates accessors which appear on the NCover coverage report. They usually have a low coverage in my case. I wonder if I use them in my tests if the method I'm testing will appear as covered in the Accessor but not in the original source code.
If this is the case, it is a problem and I need a solution.
The dev team was interested in this issue and created an MSTest private accessor project in VS 2010.
I ran coverage on it in NCover 3 with MSTest, and it appears that these accessors are reflecting the source code, not a generated version of it, at least in our test.
If you'd like to get the test project and try it out, just contact us at support#ncover.com.
Thanks!
If I understand your scenario, then any method called by your test will be shown as covered in the source code.
If the test adds accessors, those will also be shown as covered where they appear, but you can filter them out by excluding the get and set methods that are generated.
Here's a link to the syntax for the method exclude:
http://docs.ncover.com/ref/3-0/ncover-console/command-line/profiling-options#em
We've been successful here with the regex .*.get_.*, just as an example.
NCover Support

Building a Visual Studio Package based on another one

I want to add my own project type based on IronStudio. So,
I downloaded the source for and compiled the latest version of IronPython, then
I created a new Visual Studio Package.
I added the Templates\Projects\MyProject folders, and added a file to it, and set its property "Include in VSIX" to true.
Then modified the main Package class to be derived from IronStudio's PythonProjectPackage instead, and set the ProvideProjectFactory property:
[ProvideProjectFactory(
typeof(PythonProjectFactory),
"Django Project",
"Django Project Files (*.myproj);*.myproj",
"myproj", "myproj",
#"Templates\Projects\MyProject",
LanguageVsTemplate="MyProject")]
public sealed class MyPackage : PythonProjectPackage
And ran it. But MyProject isn't showing up in the project templates. Why not?
The generated .pkgdef file looks like this:
[$RootKey$\InstalledProducts\VSPackage3Package]
#="#110"
"Package"="{5cd7435c-7461-459f-80bc-c0c79e9d462f}"
"PID"="1.0"
"ProductDetails"="#112"
"LogoID"="#400"
[$RootKey$\Packages\{5cd7435c-7461-459f-80bc-c0c79e9d462f}]
#="Microsoft.VSPackage3.VSPackage3Package, VSPackage3, Version=1.0.0.0, Culture=neutral, PublicKeyToken=a4f1577d825253f8"
"InprocServer32"="$WinDir$\SYSTEM32\MSCOREE.DLL"
"Class"="Microsoft.VSPackage3.VSPackage3Package"
"CodeBase"="$PackageFolder$\VSPackage3.dll"
[$RootKey$\Editors\{888888c4-36f9-4453-90aa-29fa4d2e5706}]
"Package"="{5cd7435c-7461-459f-80bc-c0c79e9d462f}"
[$RootKey$\Editors\{888888c4-36f9-4453-90aa-29fa4d2e5706}\Extensions]
"py"=dword:00000020
[$RootKey$\Editors\{888888c4-36f9-4453-90aa-29fa4d2e5706}\LogicalViews]
"{7651a701-06e5-11d1-8ebd-00a0c90f26ea}"=""
[$RootKey$\Editors\{888888c4-36f9-4453-90aa-29fa4d2e5706}\LogicalViews]
"{7651a702-06e5-11d1-8ebd-00a0c90f26ea}"=""
[$RootKey$\Editors\{888888c4-36f9-4453-90aa-29fa4d2e5706}\LogicalViews]
"{7651a703-06e5-11d1-8ebd-00a0c90f26ea}"=""
[$RootKey$\CLSID\{888888fd-3c4a-40da-aefb-5ac10f5e8b30}]
#="Microsoft.IronPythonTools.Project.PythonGeneralPropertyPage"
"InprocServer32"="$WinDir$\SYSTEM32\MSCOREE.DLL"
"Class"="Microsoft.IronPythonTools.Project.PythonGeneralPropertyPage"
"CodeBase"="$PackageFolder$\VSPackage3.dll"
"ThreadingModel"="Both"
[$RootKey$\Projects\{888888a0-9f3d-457c-b088-3a5042f75d52}]
#="PythonProjectFactory"
"DisplayName"="My Project"
"DisplayProjectFileExtensions"="My Project Files (*.myproj);*.myproj"
"Package"="{5cd7435c-7461-459f-80bc-c0c79e9d462f}"
"DefaultProjectExtension"="myproj"
"PossibleProjectExtensions"="myproj"
"ProjectTemplatesDir"="$PackageFolder$\Templates\Projects\MyProject"
"Language(VsTemplate)"="MyProject"
[$RootKey$\NewProjectTemplates\TemplateDirs\{5cd7435c-7461-459f-80bc-c0c79e9d462f}\/1]
#="My Project"
"SortPriority"=dword:00000064
"TemplatesDir"="$PackageFolder$\Templates\Projects\MyProject"
[$RootKey$\Projects\{888888a0-9f3d-457c-b088-3a5042f75d52}]
#="PythonProjectFactory"
"DisplayName"="IronPython"
"DisplayProjectFileExtensions"="IronPython Project Files (*.pyproj);*.pyproj"
"Package"="{5cd7435c-7461-459f-80bc-c0c79e9d462f}"
"DefaultProjectExtension"="pyproj"
"PossibleProjectExtensions"="pyproj"
"ProjectTemplatesDir"="$PackageFolder$\.\NullPath"
"Language(VsTemplate)"="IronPython"
[$RootKey$\NewProjectTemplates\TemplateDirs\{5cd7435c-7461-459f-80bc-c0c79e9d462f}\/1]
#="IronPython"
"SortPriority"=dword:00000064
"TemplatesDir"="$PackageFolder$\.\NullPath"
[$RootKey$\Services\{b98e41c4-581e-3532-beee-06829b683d39}]
#="{5cd7435c-7461-459f-80bc-c0c79e9d462f}"
"Name"="IPythonStarter"
I just want to get the bare bones up and running so I can start overriding some functionality (like the Add New Item dialog).
Update:
Reading my initial analysis once again increases my impression that some of the required components are missing (e.g. a dedicated ProjectFactory) and/or wired up incorrectly - from the MSDN documentation of the ProvideProjectFactoryAttribute Class:
ProvideProjectFactoryAttribute declares that a package provides a project factory.
And further:
If a VSPackage declares that it provides a project factory, it should create the factory and offer it to Visual Studio in the Initialize method of the Package-derived class.
You package is declaring to provide PythonProjectFactory, but (likely) doesn't offer it to VS, rather it is offered by the IronPython package. In turn you are providing arguments within the ProvideProjectFactory attribute list which PythonProjectFactory won't know about when asked for by VS.
Consequently you should at least provide a dedicated ProjectFactory yourself as per the walkthrough, wire up the classes accordingly and see how this turns out regarding the issues outlined below.
Initial analysis:
There appear to be several issues here at first sight - have you followed any tutorial on how to do this? In case, please note that some of those easily discoverable via search engines are outdated still. Either way I'd try working through and/or comparing your result with Walkthrough: Part 1 - Creating a Basic Project System from the MSDN documentation for VS 2010; please note that even this one is claimed to be outdated a bit according to the Community Content section on the bottom of the page.
Here is what I'd look into myself given the code you present, comparing with the walkthrough on the fly for more insights:
You realized already that the duplicate fragment starting with the GUID above PythonProjectFactory doesn't make sense - this is essentially trying to register two packages at once, which, even if allowed at all syntactically (which I doubt), can't possibly work like so due to both being registered with the same GUID [cross checking with the sample file in section Examining the Template Registration confirms this suspicion, as expected there is only one such fragment].
Please note that the GUID in question is the one identifying PythonProjectFactory (as per the respective source code), see below for more on this.
[Guid(PythonConstants.ProjectFactoryGuid)]
public class PythonProjectFactory : ProjectFactory {
Given .pkgdef is a generated file the next question is where this duplication/violation stems from. When two generated artifacts end up with the same GUID the respective definition in the sources is most likely messed up somehow, usually due to copy&paste duplication. Consequently you should verify whether {5cd7435c-7461-459f-80bc-c0c79e9d462f} is defined and referenced as intended, though here might be one or two other causes as well for this, see below.
A Package class needs to be identified by a GUID and the VS wizard generates some already in Guids.cs and references it accordingly on the class definition, however, the following is missing in your fragment [cross checking with the sample fragment in section To register the project template confirms this omission as well]:
[Guid(GuidList.guidMyPackagePkgString)]
public sealed class MyPackage : Package
Likewise it appears incorrect to derive MyPackage from PythonProjectPackage but reference PythonProjectFactory still rather than providing MyFactory as well (including a dedicated GUID), because the latter tells Visual Studio the location of your project template folder [see section Creating a Skeletal Project Factory]:
While it might well be possible to simply reuse all functionality from the base class PythonProjectFactory, inheriting is likely required simply because the factory must have a dedicated GUID too (as outlined in the walkthrough) in order to properly wire up the attribute specified data.
Likely unrelated, but still suspicious is that your two code blocks don't relate, as the Package class definition specifies Django Project Files (*.myproj);*.myproj, yet the result shows My Project Files (*.myproj);*.myproj.
Have you by chance mixed this from different builds or is this really a result of a clean one?
Good luck!
This stackoverflow posting might be helpful: VS2010: VSIX installation doesn't deploy item templates inside it
If this is not what you're looking for, try to see if you're missing something around the creation of custom project templates, I believe that's where the "missing link" is:
For VS 2008:
http://blogs.msdn.com/b/webdevelopertips/archive/2008/12/02/tip-32-did-you-know-how-to-easily-create-your-own-project-templates.aspx
For VS 2010:
http://blog.reybango.com/2010/09/21/how-to-create-html5-website-and-page-templates-for-visual-studio-2010/
and on MSDN:
http://msdn.microsoft.com/en-us/library/s365byhx.aspx
and here is how to create a project
template manually:
http://msdn.microsoft.com/en-us/library/ms185291.aspx
and here is how to create a new item template in VS 2010: http://msdn.microsoft.com/en-us/library/ms247113.aspx
Hope this helps
$PackageFolder$.\NullPath may have something to do with it.

Visual Studio and root namespaces

I am using VS2010, is there a way, to disable full root namespaces, when VS is autogenerating code? From this:
{
global::System.ComponentModel.CollectionChangeEventHandler schemaChangedHandler = new global::System.ComponentModel.CollectionChangeEventHandler(this.SchemaChanged);
}
to this:
using System.ComponentModel;
{
CollectionChangeEventHandler schemaChangedHandler = new CollectionChangeEventHandler(this.SchemaChanged);
}
I don't know if there is, however doing so is a VERY BAD idea.
VERY BAD.
VERY BAD.
VERY VERY BAD.
First, it suggests you are editing generated code. If you are, see above. The solution is to use partial classes, if you aren't already. Almost all generated code is done using partial classes. If not, open a Connect.
Second, it is there for a reason--it prevents generated code class names and namespaces from clashing with yours. When generated code isn't globally scoped and it does clash, you only have two choices: Either rename your code or edit the generated code every time you regenerate it. This is the definition of a Pain in the Ass.
I know it doesn't look pretty, but the fact is you should NEVER be looking at it.
NEVER.
etc.
Here's a connect I opened because the EF4 T4 templates didn't globally scope their variables, so the generated code clashed with my Debug namespace.

Resources