Cruise control .net将输出重定向到文件

时间:2013-12-12 14:59:01

标签: c# cruisecontrol.net

我有控制台应用程序,它在构建期间启动一些测试。

<exec>
   <executable>Tests.exe</executable>
   <baseDirectory>Q:\Software\Platform\</baseDirectory>
   <buildTimeoutSeconds>100</buildTimeoutSeconds>
</exec>

我想将其输出重定向到文本文件,然后将其包含在我的报告文件中。 我尝试了以下方法将输出重定向到NativeUtilsTestReport.txt(如命令行somefile.exe&gt; file.txt):

<exec>
   <executable>Tests.exe</executable>
   <baseDirectory>Q:\Software\Platform\</baseDirectory>
   <buildArgs> > NativeUtilsTestReport.txt</buildArgs>
   <buildTimeoutSeconds>100</buildTimeoutSeconds>
</exec>

但它似乎不起作用。测试工作正常,但没有包含报告的文本文件。

如何从这个“exec”部分获得输出?

3 个答案:

答案 0 :(得分:2)

你不能使用&lt;或者&gt;在xml中。我可以像这样重定向输出。

<exec>
   <executable>Tests.exe</executable>
   <baseDirectory>Q:\Software\Platform\</baseDirectory>
   <buildArgs> &gt; NativeUtilsTestReport.txt</buildArgs>
   <buildTimeoutSeconds>100</buildTimeoutSeconds>
</exec>

然后,您可以使用合并任务将输出包含到日志中。

<merge>
  <files>
    <file>NativeUtilsTestReport.txt</file>
  </files>
</merge>

我还建议您将输出保存到工件目录。

$(ArtifactDirectory)\ NativeUtilsTestReport.txt

答案 1 :(得分:0)

我将不得不使用一个比喻。

NUnit它是一个测试程序。

所以当你运行

nunit-console.exe SomeDll.dll "c:\somefolder\NUnitTest_RESULTS.xml"

控制台应用程序本身将超出一些具有特定名称的XML ....

因此即使获得输出xml文件,这对CC.NET也没有任何作用。

使用CC.NET文件合并任务将NUnitTest_RESULTS.xml“suck”到“ThisBuildCCNet_SuperDuperXmlFile.xml”中。 (那不是名字,这就是概念)。

这并没有做任何事情。

CC.NET安装了“NUnit”,它是xsl文件的链接。

因此,在创建NUnitTest_RESULTS.xml并将NUnitTest_RESULTS.xml“sucked”到super-duper.xml文件中并启用NUnit-Xsl后,单击NUnit菜单项(在您的网页上)项目),CC.NET将获取nunit.xsl并将其应用于现在super-duper.xml文件中的xml。 Aka,一个基本的xsl-xml转换。

因此,对于您的问题,如果您希望控制台应用程序运行测试,它应该能够将XML输出到文件。如果它不能那样做,那么你就在水中了。

如果你得到xml,那么你必须使用文件合并任务来“搞砸”,你必须创作或找到一个xsl文件来进行转换。

.......

修改

如果无法生成xml或hmtl(通过htmlReportPlugin)

然后我建议这篇文章:

http://testquest.docs.bsquare.com/Integration_Samples_CCNet/Configuring_CCNet_dashboard_to_Display_Test_Execution_Logs.htm

答案 2 :(得分:0)

我最终编写了自己的ExecutableTask用于巡航控制,它从CCnet IIntegrationResult.TaskResults读取输出并将其写入文件。 应用程序写入输出纯文本,但CCnet将其转换为以下XML:

<buildresults>
<task><buildArgs />
   <buildTimeoutSeconds>100</buildTimeoutSeconds>
   <baseDirectory>Q:\software\Platform\</baseDirectory>
   <dynamicValues />
   <environment />
   <executable>NativeUtils.Tests.exe</executable>
   <OutputFilePath>Q:\software\NativeUtilsTestReport.txt</OutputFilePath>
   <priority>Normal</priority>
   <successExitCodes />
</task>
      <message>Running 50 test cases...</message>
</buildresults>


<buildresults>
    <task><buildArgs />
    <buildTimeoutSeconds>100</buildTimeoutSeconds>
    <baseDirectory>Q:\software\Platform\</baseDirectory>
    <dynamicValues />
    <environment />
    <executable>NativeUtils.Tests.exe</executable>
    <OutputFilePath>Q:\software\NativeUtilsTestReport.txt</OutputFilePath>
    <priority>Normal</priority>
    <successExitCodes />
</task>
  <message level="Error">*** No errors detected</message>
</buildresults>

这是代码:

[ReflectorType("execWithOutput")]
class ExecutableTestTask:ExecutableTask
{
    [ReflectorProperty("OutputFilePath", Required = false)]
    public string OutputFilePath { get; set; }

    protected override bool Execute(ThoughtWorks.CruiseControl.Core.IIntegrationResult result)
    {
        bool rez = base.Execute(result);

        if (!string.IsNullOrEmpty(OutputFilePath))
        {
            using (FileStream fs = new FileStream(OutputFilePath, FileMode.Create, FileAccess.Write, FileShare.Read))
            {
                using (StreamWriter sw = new StreamWriter(fs))
                {
                    var lastIndex = result.TaskResults.Count-1;
                    // read output from last executed task
                    var output = ((ProcessTaskResult)result.TaskResults[lastIndex]).Data;

                    string parsedOutput = readMessagesFromXml(output);

                    sw.Write(parsedOutput);
                }
            }
        }
        return rez;
    }

    // parse xml
    private string readMessagesFromXml(string xml)
    {
        StringBuilder sb = new StringBuilder();

        try
        {
            // wrap output to into single root node
            var xmlWithRootNode = string.Format("<report>{0}</report>", xml);
            XmlDocument doc = new XmlDocument();
            doc.LoadXml(xmlWithRootNode);
            var nodes = doc.SelectNodes("//report/buildresults/message");

            if (nodes.Count > 0)
            {
                foreach (XmlNode node in nodes)
                {
                    sb.AppendLine("<div>" + node.InnerText + "</div>");
                }
            }
            else
            {
                sb.AppendLine("Xml output does not contain valid data or there are no messages");
            }
        }
        catch (Exception ex)
        {
            sb.AppendLine("Exception during parsing XML task output. "+ex.ToString());
        }

        return sb.ToString();
    }

}

然后我在构建期间调用它:

<execWithOutput>
        <executable>NativeUtils.Tests.exe</executable>
        <baseDirectory>Q:\software\Platform\</baseDirectory>
        <OutputFilePath>Q:\software\NativeUtilsTestReport.txt</OutputFilePath>
        <buildTimeoutSeconds>100</buildTimeoutSeconds>
</execWithOutput>