hBifTs

山自高兮水自深!當塵霧消散,唯事實留傳.荣辱不惊, 看庭前花开花落; 去留随意, 望天上云展云舒.

导航

定制FxCop规则--检测Release版本中的TestCase

Posted on 2005-04-04 22:20  hbiftsaa  阅读(3052)  评论(4编辑  收藏  举报
在使用NUnit进行开发的时候,TestCase是不可省的.通过TestCase,我们才可以保证所撰写的代码的正确性:)

但是由于在开发过程中是边写TestCase,边实现功能代码的,如果不注意的话,在最终的Release版本中可能会出现曾经写过的TestCase...这应该是在程序开发过程中尽量避免的:)
解决这个问题的方法有以下几种:
1,使用 #if DEBUG XXX #endif 标签.将所有的TestCase放到此标签中.这样当以Debug方式编译的时候,可以使用NUNit进行测试.当以Release方式编译的时候,其中的所有代码将会被忽略掉(相当于注释掉).这样就不会产生多余的代码了:)
2,将所有的TestCase放到单独的工程中.这样,功能代码将不可能包括测试代码,这样也可以避免上述问题..

在一个项目中,为了对所有的代码进行上述检查,如果用人工的方式来检查,那显然是不现实的.即然大家都是玩电脑的,那何不用电脑来检查了:)呵呵,对了,使用.NET下面的FxCop...

FxCop自带的Rules里面没有这样的规则,那我们得自定义一个Rule了:)

此Rule的工作流程如下:
1,得到此程序中所有的Class.
2,对每一个Class,得到其Attribute.
3,对每一个Attribute,判断是不是NUnit.Framework.TestFixtureAttribute.如果是,返回错误.

注:一定要是Release版本的程序,才可以起到真正的检测目的.

通过 定制FxCop规则示例之一:AvoidICloneableImplementation 这篇文章,我们可以学会怎么编写一个基本的FxCop的Rule...但只是文章中的东西是不能解决我们的这个问题的..我们来Google一下,看看有没有别的信息..
找到了这个:
Writing custom rules [using introspection] for FxCop 1.312 (from: James Geurts)
FxCop Custom Rule - Introspection Engine 3.12

注意这段:
The BaseIntrospectionRule class provides some overloaded versions of the Check() method. The available methods are: 

Check(Member member)
   
- Useful for checking members of a class. (Methods, Properties, Events, Delegates, etc)
Check(Module module)
   
- Useful for checking assemblies.
Check(Parameter parameter)
   
- Checks all parameters
Check(Resource resource)
   
- Checks all resources (from .resx files)
Check(TypeNode type)
   
- Checks types
Check(
string namespaceName, TypeNodeList types) 
   
- Checks types 

对于我们现在要编写的Rule而言,我们要使用第5个函数,即: Check(TypeNode type)
通过对TypeNode类的使用,我们可以发现他有 Attributes 这样一个属性,即可以获得此Class上的所有Attribute.
其类型是 AttributeList..
AttributeList中存放的是AttributeNode,不同于.NET FX中带的Attribute.即不能直接判断AttributeNode == Attribute.
幸好TypeNode提供了FullName属性.这个属性中存放的是实际类的全名.
即NUnit.Framework.TestFixtureAttribute类的TypeNode的FullName是 "NUnit.Framework.TestFixtureAttribute"

到这里,技术上的工作都搞定了..下面是代码实现
RuleInfo.xml
<?xml version="1.0" encoding="utf-8" ?> 
<Rules FriendlyName="Avoid NUnit TestCase in Release Version">
  
<Rule TypeName="AvoidNUnitTestCase" Category="Cnblogs.Rules" CheckId="hbifts000001">
    
<Name>Avoid NUnit TestCases Implementation in Release Version</Name>
    
<Description>NUnit TestCases must never be included in release versions.</Description>
    
<Url>http://www.cnblogs.com/hbifts</Url>
    
<Resolution>Type '{0}' Implements NUnit TestCases, which should avoid in release version.You should add #if DEGUG XXX #endif.</Resolution>
    
<Email />
    
<MessageLevel Certainty="99">Error</MessageLevel>
    
<FixCategories>Breaking</FixCategories>
    
<Owner />
  
</Rule>
</Rules>

AvoidNUnitTestCase.cs实现
    public class AvoidNUnitTestCase : BaseIntrospectionRule
    
{
        
public AvoidNUnitTestCase() : base("AvoidNUnitTestCase","Cnblogs.Rules.RuleInfo",typeof(AvoidNUnitTestCase).Assembly)
        
{
        }


        
public override ProblemCollection Check(TypeNode type)
        
{
            
if( DoesImplementConditionAttribute(type.Attributes)){
                Resolution resolution 
= GetResolution(RuleUtilities.Format(type));
                Problem problem 
= new Problem(resolution,type);
                Problems.Add(problem);
                
return Problems;
            }

            
return null;
        }


        
private bool DoesImplementConditionAttribute( AttributeList Lists )
        
{
            Log.WriteFile( Lists.Length.ToString());
            
for(int i=0;i<Lists.Length;i++){
                
if( Lists[i].Type.FullName.Equals("NUnit.Framework.TestFixtureAttribute")){
                    
return true;
                }

            }

            
return false;
        }

    }

编译成一个dll..加入到FxCop的Rules中,这样我们就可以很方便的每日Build后检测Release版本是否存在TestCase:)

All Happy~:)