利用NAnt进行NUnit自动化测试

        最近做的项目是.NET的,准确来说,是一个ASP.NET的项目,项目要求采用NUnit测试,在每日的版本构建的时候,需要自动运行全体的测试任务。在Java中,用的最多的每日构建工具应该就是Ant了,当然,Maven也是个好东西。在.NET有个类似的工具,叫做NAnt,不过好像已经有1年左右没有更新了,不知道是不是这个NAnt没人维护了呢。

        首先在SourceForge上下载了NAnt的安装包,还有,Nant-Contrib的也需要下载,否则很多扩展功能不能自动实现。把Nant解压缩,并且把Contrib的东西也一起解压缩在Nant的bin目录下。然后你再把Nant的bin目录添加到你的环境变量的Path下,这样就可以在命令行中运行nant命令了。

        如果要进行NUnit测试,首先需要编译NUnit的测试代码。采用csc命令进行编译,如下所示

< csc  target ="library"  
    output
="${nunit_dll}/Test.Isid.ResonaIB.Web.dll"
    optimize
="true"
    failonerror
="true"
    rebuild
="true"
    verbose
="${debug}" >
    
< sources >
        
< include  name ="${src.path} /trunk/Test.Isid.ResonaIB.Web/Test.Isid.ResonaIB.Web/**/*.cs"   />
    
</ sources >
    
< references >
        
< include  name ="System.dll"   />
        
< include  name ="System.Data.dll"   />
        
< include  name ="System.Xml.dll"   />
        
< include  name ="${nunit_lib}/nunit.framework.dll"   />
        
< include  name ="${nunit_lib}/NMock2.dll"   />
        
< include  name ="${lib}/Isid.Copera.Web.FC.dll"   />
        
< include  name ="${lib}/Isid.Copera.Web.Parameters.dll"   />
        
< include  name ="${lib}/Isid.Dance.Web.FC.dll"   />
        
< include  name ="${lib}/Isid.Dance.Web.Parameters.dll"   />
        
< include  name ="${lib}/Isid.ResonaIB.Web.BC.Certification.dll"   />
        
< include  name ="${lib}/Isid.ResonaIB.Web.BC.External.dll"   />
        
< include  name ="${lib}/Isid.ResonaIB.Web.BC.Resource.dll"   />
        
< include  name ="${lib}/Isid.ResonaIB.Web.BC.SystemCommon.dll"   />
        
< include  name ="${lib}/Isid.ResonaIB.Web.BC.Utility.dll"   />
        
< include  name ="${build_dll}/Isid.ResonaIB.Web.DAC.dll"   />
        
< include  name ="${build_dll}/Isid.ResonaIB.Web.FC.dll"   />
        
< include  name ="${build_dll}/Isid.ResonaIB.Web.PARAM.dll"   />
        
< include  name ="${build_dll}/Isid.ResonaIB.Web.BC.dll"   />
        
< include  name ="${build_dll}/Isid.ResonaIB.Web.Utils.dll"   />
    
</ references >
</ csc >

        编译好了以后,记得吧编译的文件和你测试时候需要的dll文件放在同一个目录下,.NET程序运行的时候不像Java程序,Java程序只要你指定ClassPath就OK了,而.NET需要在同目录下寻找dll文件。然后就可以运行nunit任务了,代码如下所示。

< nunit2  verbose ="${debug}" >
    
< formatter  type ="Xml"  usefile ="true"   extension =".xml"  outputdir ="${target.path}/report"   />
        
< test 
            
assemblyname ="${nunit_dll}/Test.Isid.ResonaIB.Web.dll"  
            haltonfailure
="false"  
            appconfig
="${root}/nunit.config" />
</ nunit2 >

        在这里要注意设置appconfig的属性,因为默认Nunit的版本是2.2的,如果你不是这个版本,需要自己Mapping上来,在这里我们来看一下nunit.config文件如何编写,如下所示

< configuration >
    
< runtime >
        
< assemblyBinding  xmlns ="urn:schemas-microsoft-com:asm.v1" >
            
< dependentAssembly >
                
< assemblyIdentity  name ="nunit.framework"  publicKeyToken ="96d09a1eb7f44a77"  culture ="Neutral"   />
                
< bindingRedirect  oldVersion ="2.4.1.0"  newVersion ="2.2.8.0"   />
            
</ dependentAssembly >
            
< dependentAssembly >
                
< assemblyIdentity  name ="NMock2"  publicKeyToken =""  culture ="Neutral"   />  
                
< bindingRedirect  oldVersion ="1.0.2313.18049"  newVersion ="1.0.2313.18049"   />
            
</ dependentAssembly >
        
</ assemblyBinding >
    
</ runtime >
</ configuration >

        在这里,就可以发现NUnit测试可以顺利运行了,生成一个xml的报告文件。我们当然希望看到一个更容易看懂的报告文件,这个时候,就需要用到nunit2report任务了。不过contrib所带的nunit2report任务稍微有一点缺陷,就是采用的字符集是ISO-8859-1,如果是欧洲人,美国人的话,自然没有问题,不过对于中国人来说,就会有问题了,因为如果程序出错,错误信息是汉语或者日语的话,是无法在ISO-8859-1这个字符集下显示的,经过转换后,生成的HTML中的中文或者日文都是问号了,那么如何去解决呢。在原来的contrib下基本上是没指望了,那么我们就自己模仿contrib的nunit2report任务来写一个UTF-8格式的。C#的代码如下所示。

using  System;
using  System.Xml;
using  System.Xml.Xsl;
using  System.Xml.XPath;
using  System.Text;
using  System.Reflection;
using  System.IO;
using  System.Globalization;
using  System.Collections;
using  System.Collections.Generic;
using  NAnt.Core;
using  NAnt.Core.Util;
using  NAnt.Core.Types;
using  NAnt.Core.Attributes;
using  NAnt.Contrib.Types.NUnit2ReportMul;

namespace  NAnt.Contrib.Tasks.NUnit2ReportMul
{
    [TaskName(
"nunit2reportmul")]
    
public class NUnit2ReportMulTask : Task
    
{
        
// Fields
        private FileSet _fileset = new FileSet();
        
private XmlDocument _fileSetSummary;
        
private ReportFormat _format = ReportFormat.NoFrames;
        
private string _language = "";
        
private string _openDescription = "no";
        
private static readonly ArrayList _resFiles = new ArrayList(new string[] "toolkit.xsl""Traductions.xml""NUnit-Frame.xsl" });
        
private FileSet _summaries = new FileSet();
        
private string _tempXmlFileSummarie = "";
        
private DirectoryInfo _toDir;
        
private FileInfo _xslFile;
        
private XsltArgumentList _xsltArgs;

        
// Methods
        private XmlDocument CreateSummaryXmlDoc()
        
{
            XmlDocument document 
= new XmlDocument();
            XmlElement newChild 
= document.CreateElement("testsummary");
            newChild.SetAttribute(
"created", DateTime.Now.ToString());
            document.AppendChild(newChild);
            
return document;
        }


        
protected override void ExecuteTask()
        
{
            
this._fileSetSummary = this.CreateSummaryXmlDoc();
            
foreach (string text in this.XmlFileSet.FileNames)
            
{
                XmlDocument document 
= new XmlDocument();
                document.Load(text);
                XmlNode newChild 
= this._fileSetSummary.ImportNode(document.DocumentElement, true);
                
this._fileSetSummary.DocumentElement.AppendChild(newChild);
            }

            
this.Log(Level.Info, "Generating report...");
            
try
            
{
                
if (!this.ToDir.Exists)
                
{
                    
this.ToDir.Create();
                    
this.ToDir.Refresh();
                }

                
if (this.Format == ReportFormat.NoFrames)
                
{
                    XslTransform transform 
= new XslTransform();
                    XmlResolver resolver 
= new LocalResXmlResolver();
                    
if (this.XslFile != null)
                    
{
                        transform.Load(
this.LoadStyleSheet(this.XslFile), resolver);
                    }

                    
else
                    
{
                        transform.Load(
this.LoadStyleSheet("NUnit-NoFrame.xsl"), resolver);
                    }

                    XmlReader reader 
= transform.Transform(this._fileSetSummary, this._xsltArgs);
                    XsltArgumentList args 
= new XsltArgumentList();
                    args.AddParam(
"lang"""this.Language);
                    XslTransform transform2 
= new XslTransform();
                    transform2.Load(
this.LoadStyleSheet("i18n.xsl"), resolver);
                    XPathDocument document2 
= new XPathDocument(reader);
                    XmlTextWriter writer 
= new XmlTextWriter(Path.Combine(this.ToDir.FullName, "index.html"), Encoding.GetEncoding("UTF-8"));
                    transform2.Transform((IXPathNavigable)document2, args, (XmlWriter)writer);
                    reader.Close();
                    writer.Close();
                }

                
else
                
{
                    XmlTextReader reader2 
= null;
                    
try
                    
{
                        StringReader stream 
= new StringReader("<xsl:stylesheet xmlns:xsl='http://www.w3.org/1999/XSL/Transform' version='1.0' ><xsl:output method='html' indent='yes' encoding='UTF-8'/><xsl:include href="NUnit-Frame.xsl"/><xsl:template match="test-results">   <xsl:call-template name="index.html"/> </xsl:template> </xsl:stylesheet>");
                        
this.Write(stream, Path.Combine(this.ToDir.FullName, "index.html"));
                        stream 
= new StringReader("<xsl:stylesheet xmlns:xsl='http://www.w3.org/1999/XSL/Transform' version='1.0' ><xsl:output method='html' indent='yes' encoding='UTF-8'/><xsl:include href="NUnit-Frame.xsl"/><xsl:template match="test-results">   <xsl:call-template name="stylesheet.css"/> </xsl:template> </xsl:stylesheet>");
                        
this.Write(stream, Path.Combine(this.ToDir.FullName, "stylesheet.css"));
                        stream 
= new StringReader("<xsl:stylesheet xmlns:xsl='http://www.w3.org/1999/XSL/Transform' version='1.0' ><xsl:output method='html' indent='yes' encoding='UTF-8'/><xsl:include href="NUnit-Frame.xsl"/><xsl:template match="test-results">    <xsl:call-template name="overview.packages"/> </xsl:template> </xsl:stylesheet>");
                        
this.Write(stream, Path.Combine(this.ToDir.FullName, "overview-summary.html"));
                        stream 
= new StringReader("<xsl:stylesheet xmlns:xsl='http://www.w3.org/1999/XSL/Transform' version='1.0' ><xsl:output method='html' indent='yes' encoding='UTF-8'/><xsl:include href="NUnit-Frame.xsl"/><xsl:template match="test-results">    <xsl:call-template name="all.classes"/> </xsl:template> </xsl:stylesheet>");
                        
this.Write(stream, Path.Combine(this.ToDir.FullName, "allclasses-frame.html"));
                        stream 
= new StringReader("<xsl:stylesheet xmlns:xsl='http://www.w3.org/1999/XSL/Transform' version='1.0' ><xsl:output method='html' indent='yes' encoding='UTF-8'/><xsl:include href="NUnit-Frame.xsl"/><xsl:template match="test-results">    <xsl:call-template name="all.packages"/> </xsl:template> </xsl:stylesheet>");
                        
this.Write(stream, Path.Combine(this.ToDir.FullName, "overview-frame.html"));
                        XPathNavigator navigator 
= this._fileSetSummary.CreateNavigator();
                        XPathExpression expr 
= navigator.Compile("//test-suite[(child::results/test-case)]");
                        XPathNodeIterator iterator 
= navigator.Select(expr);
                        
while (iterator.MoveNext())
                        
{
                            
string text2 = "";
                            XPathNavigator current 
= iterator.Current;
                            
string attribute = iterator.Current.GetAttribute("name""");
                            XPathNodeIterator iterator2 
= current.SelectAncestors(""""true);
                            
string text4 = "";
                            
for (int i = -1; iterator2.MoveNext(); i++)
                            
{
                                
string text5 = iterator2.Current.GetAttribute("name""");
                                
if ((text5 != ""&& (text5.IndexOf(".dll"< 0))
                                
{
                                    text2 
= text5 + "/" + text2;
                                }

                                
if (i == 1)
                                
{
                                    text4 
= text5;
                                }

                            }

                            text2 
= Path.Combine(this.ToDir.FullName, text2);
                            
if (!Directory.Exists(text2))
                            
{
                                Directory.CreateDirectory(text2);
                            }

                            stream 
= new StringReader("<xsl:stylesheet xmlns:xsl='http://www.w3.org/1999/XSL/Transform' version='1.0' ><xsl:output method='html' indent='yes' encoding='UTF-8'/><xsl:include href="NUnit-Frame.xsl"/><xsl:template match="/">    <xsl:for-each select="//test-suite[@name='" + attribute + "' and ancestor::test-suite[@name='" + text4 + "'][position()=last()]]">        <xsl:call-template name="test-case">            <xsl:with-param name="dir.test">" + string.Join(".", text2.Split(new char[] '/' })) + "</xsl:with-param>        </xsl:call-template>    </xsl:for-each> </xsl:template> </xsl:stylesheet>");
                            
this.Write(stream, Path.Combine(text2, attribute + ".html"));
                            
this.Log(Level.Debug, "dir={0} Generating {1}.html"new object[] { text2, attribute });
                        }

                    }

                    
finally
                    
{
                        
this.Log(Level.Debug, "Processing of stream complete.");
                        
if (reader2 != null)
                        
{
                            reader2.Close();
                        }

                    }

                }

            }

            
catch (Exception exception)
            
{
                
throw new BuildException("Failure generating report."this.Location, exception);
            }

        }


        
private XsltArgumentList GetPropertyList()
        
{
            XsltArgumentList list 
= new XsltArgumentList();
            
this.Log(Level.Verbose, "Processing XsltArgumentList");
            
foreach (DictionaryEntry entry in this.Project.Properties)
            
{
                
string parameter = entry.Value as string;
                
if (parameter != null)
                
{
                    list.AddParam((
string)entry.Key, "", parameter);
                }

            }

            list.AddParam(
"summary.xml"""this._tempXmlFileSummarie);
            list.AddParam(
"open.description"""this.OpenDescription);
            
return list;
        }


        
protected override void InitializeTask(XmlNode taskNode)
        
{
            
if (((this.Format == ReportFormat.NoFrames) && (this.XslFile != null)) && !this.XslFile.Exists)
            
{
                
throw new BuildException(string.Format(CultureInfo.InvariantCulture, "The XSLT file "{0}" could not be found."new object[] <
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值