Search code examples
c#nunitprocessstartinforedirectstandardoutput

How do I get 'RedirectStandardOutput' to work in NUnit?


I am working on an automation strategy for our QA group and need to be able to capture the output of scripts and EXE files. When I run this code as a console application, I am able to successfully capture the output of plink.exe:

class Program
{
    static void Main(string[] args)
    {
        Process process = new Process();
        process.StartInfo.FileName = @"C:\Tools\plink.exe";
        process.StartInfo.Arguments = @"10.10.9.27 -l root -pw PASSWORD -m C:\test.sh";
        process.StartInfo.UseShellExecute = false;
        process.StartInfo.RedirectStandardOutput = true;
        process.Start();

        string output = process.StandardOutput.ReadToEnd();
        process.WaitForExit();

        output = output.Trim().ToLower(); // Output is successfully captured here

        if (output == "pass")
        {
            Console.WriteLine("Passed!");
        }
    }
}

This command takes about a minute to execute and I successfully capture the results to the output variable.

However, when I compile the same code as a DLL and run through NUnit, the code completes immediately and fails with the value of output == NULL:

[TestFixture]
public class InstallTest
{
    [Test]
    public void InstallAgentNix()
    {
        Process process = new Process();
        process.StartInfo.FileName = @"C:\Tools\plink.exe";
        process.StartInfo.Arguments = @"10.10.9.27 -l root -pw PASSWORD -m C:\test.sh";
        process.StartInfo.UseShellExecute = false;
        process.StartInfo.RedirectStandardOutput = true;
        process.Start();

        string output = process.StandardOutput.ReadToEnd();

        process.WaitForExit();

        output = output.Trim().ToLower();

        Assert.AreEqual("pass", output, "Agent did not get installed");
    }
}

I have narrowed the problem down to the line string output = process.StandardOutput.ReadToEnd(). If I comment the line out, execution time is around a minute and the operation is successfully executed on the remote machine (test.sh gets executed on a remote Linux box).

I hope I'm missing something simple - I don't want to have to find a different test harness.

It looks similar to the (unsolved) question here: Why does a process started in a DLL file work when tested using console application, but not when called by another DLL file?


Solution

  • OK, it took me all night but I figured it out. I have to RedirectStandardInput in addition to redirecting standard output for this to work.

    Here is the fixed code that works in a DLL file. As an FYI, this fix resolves the problem in a Windows Forms application as well:

    [TestFixture]
    public class InstallTest
    {
        [Test]
        public void InstallAgentNix()
        {
            Process process = new Process();
            process.StartInfo.FileName = @"C:\Tools\plink.exe";
            process.StartInfo.Arguments = @"10.10.9.27 -l root -pw PASSWORD -m C:\test.sh";
            process.StartInfo.UseShellExecute = false;
            process.StartInfo.RedirectStandardOutput = true;
            process.StartInfo.RedirectStandardInput = true;
            process.Start();
    
            string output = process.StandardOutput.ReadToEnd();
    
            process.WaitForExit();
    
            output = output.Trim().ToLower();
    
            Assert.AreEqual("pass", output, "Agent did not get installed");
        }
    }