The Five Minute Guide to FxCopUnit
By Roy Osherove
Blog: www.Iserializable.com
Email: Roy@Osherove.com

Writing Integration Tests with FxCopUnit:

  1. Create your custom rule library with the rules you would like to test. It should already have the Rule manifest XML file in it compiled as embedded resource, with the rule IDs and Categories defined. They will be required when you write your integration tests to specify which rule you would like to test. See the TeamAgile.FxCopRuleTesting.SampleRules project in the source download for a sample on how to do this.
    1. Caveat : A custom rule must call it’s base class in the constructor with it’s exact class name. That is why I have created a generic base rule that you can use to easily and automatically do this. See CustomRuleBase class on usage.
    2. Caveat: A custom rule must reference the XML rule file that is associated with the project as a resource. See the CustomRuleBase class to see how it’s done and make sure you implement this in your tests.
  2. Create a new Class library project to hold your unit tests
  3. Build the library once, and then go to the bin\debug folder under that library.
    1. Create a folder named “Engines” under Bin\Debug
    2. copy the file IntrospectionAnalysisEngine.dll from the folder C:\Program Files\Microsoft Visual Studio 8\Team Tools\Static Analysis Tools\FxCop\Engines .
    3. Your tests will not run without this step!

 

  1. Add the following references:

5.      Create a new test fixture class

6.      Inherit  your class from FxCopTestFixture

Add the attribute to the top of the class to specify the location of your custom rules: [FxCopCustomRuleLocation("TeamAgile.FxCopRuleTesting.SampleRules.dll")]

7.      Create a new test:

[Test]

        [FxCopRuleToTest("Rule0001", "FxCopCustomRules.CustomRules",true)]

        public void RunRuleAgainstMethod()

        {

        }

Note the  FxCopRuleToTest attribute on the test. Specify the rule ID and Rule category as written in the Rule XML file manifest located inside your custom rules library (in the sample source it is RuleManifest.Xml – complied as Embedded resource).

The third parameter setup up FxCop engine so that the current test library will also be the main target to test the rules against.

Alternatively, you can specify the name of the target assembly to test against.

You can also specify the specific type that your rule will run against (all other types in the assembly will be ignored by the rules engine) .

 

Here’s a test that specifies a rule, and a specific method to test against.

It then tells FxCop to analyze the targets and does some simple asserts against the resulting FxCop report.

 

[Test]

        [FxCopRuleToTest("Rule0001", "FxCopCustomRules.CustomRules",true)]

        public void RunRuleAgainstMethod()

        {

            MethodInfo methodInfo = MethodBase.GetCurrentMethod() as MethodInfo;

            FxRunner.EnableMethodToCheck(methodInfo);

            FxRunner.Analyze();

 

            FxReport.Assert.AtLeastOneAnalysisProblem();

            Console.WriteLine(FxReport.Document.InnerXml);

        }

 

The test uses two objects which are available once you inhering from FxCopTestFixture:

FxRunner:

Helper used to specify rules, types and other logic, as well as to start the analysis process by FxCop.

FxReport:

A report object that is generated only after calling FxRunner.Analyze(). It will be null before that.

 

Asserting against output:

Most of the asserts should be performed against the FxReport object, which already has a property named “Assert”. It is an AssertFxCop object which has some very simple asserts in it. It can be extended though- it’s a partial class. (so is the FxCopReport class).

 

 

Writing real Unit Tests with FxCop, not Integration Tests

It’s possible to create elegant small tests which require little to no configuration whatsoever that test out your custom rule’s ability to verify problems.

It’s so simple in fact, that there’s no need to use FxCopUnit , unless you absolutely want to test your rule as part of a fully integrated rules framework.

 

To achieve simple FxCop unit tests, take a look at FxCopUnitTests.cs file in teamAgile.FxCopRuleTesting.csproj.

 

Here’s a sample unit test:

[Test]

        public void InvokeMyRuleWithMethodInfo()

        {

            MethodInfo someMethodInfo = MethodBase.GetCurrentMethod() as MethodInfo;

            Microsoft.Cci.Method methodData = Microsoft.Cci.Method.GetMethod(someMethodInfo);

            MyRule ruleUnderTest = new MyRule();

            ProblemCollection problems = ruleUnderTest.Check(methodData);

 

            Assert.Greater(0,problems.Count);

        }

 

A custom rule can accept many kinds of inputs, but ultimately the most important ones are “Member” and “TypeNode”.

 

 

Here’s the hiearchy for Member these:

 (see the hiearchy image in the solution items)

 

So the only question remains: how to you transform a simple reflection MethodInfo or EventInfo or FieldInfo or Type into the corresponding Member type in Mcirosoft.Cci?

 

It’s pretty simple: For each type. There’s a static method on the counter type to get that transformation. In the test above to get a Method object, I used the static Method.GetMethod(MethodInfo) to get what I need.

You’ll find the same thing for Event, TypeNode and many others.All that’s left is to create a new instance o fyour custom rule (without needing FxCop engine at all), and invoking it’s check method with the data you have specified.

All that’s left is to check stuff on the problem collection that you need to get back.

Voila! You have yourself a true unit test with FxCop custom rules (or as close as possible to one..).