在使用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
注意这段:
对于我们现在要编写的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
AvoidNUnitTestCase.cs实现
编译成一个dll..加入到FxCop的Rules中,这样我们就可以很方便的每日Build后检测Release版本是否存在TestCase:)
All Happy~:)
但是由于在开发过程中是边写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
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>
<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;
}
}
{
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~:)