巡航控制 .net 将输出重定向到文件

3

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

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

我想将输出重定向到文本文件中,并将其包含在我的报告文件中。我尝试了以下方法来将输出重定向到 NativeUtilsTestReport.txt(就像在命令行中一样 somefile.exe > file.txt):

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

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

我如何从这个"exec"部分获得输出?

3个回答

2

在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

>不起作用。输出仍然没有文件。它真的对你有用吗? - cmd
请查看此链接:https://dev59.com/_XNA5IYBdhLWcg3wGJwV。 - Matt Slagle
如果这个方法不行的话,你能否修改.exe文件来将日志保存到文件中,而不是捕获输出? - Matt Slagle

0
我最终编写了自己的ExecutableTask用于cruise control,它从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>

0

我得用一个比喻。

NUnit是一个测试程序。

所以当你运行

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

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

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

您可以使用CC.NET文件合并任务将NUnitTest_RESULTS.xml合并到“ThisBuildCCNet_SuperDuperXmlFile.xml”中。(那不是名称,那是概念)。

但实际上这并没有什么作用。

CC.NET安装了“NUnit”,这是一个指向xsl文件的链接。

因此,在创建NUnitTest_RESULTS.xml并将NUnitTest_RESULTS.xml“吸入”超级duper.xml文件并启用NUnit-Xsl后,当您单击项目网页上的NUnit菜单项时,CC.NET将采用nunit.xsl并将其应用于现在存在于超级duper.xml文件中的xml。也就是说,进行基本的xsl-xml转换。

所以回答您的问题,如果您想让控制台应用程序运行测试,它应该能够将XML输出到文件中。如果无法做到这一点,那么您就会陷入困境。

如果你得到了XML文件,那么你需要使用file-merge任务来“吸收”它,并且你需要编写或查找一个XSL文件来进行转换。

.......

编辑

如果您无法生成XML或HTML(通过htmlReportPlugin)

那么我建议阅读这篇文章:

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


请参考以下链接:http://stackoverflow.com/questions/20002531/how-does-cruise-control-net-use-build-test-tools - granadaCoder
谢谢回复,但 tests.exe 没有使用 nUnit 并且它产生纯文本输出。它是本地的 Windows 应用程序,而不是 .net。有没有办法重定向输出?我有一些想法,可以将我的自定义 exec 处理程序作为插件写入 ccnet 并尝试在那里读取输出。这可行吗? - cmd
我意识到你的.exe文件没有使用nunit,这就是为什么我提到了“隐喻”的原因。既然你似乎无法生成xml或html,我会编辑我的答案。 - granadaCoder

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接