How to write to Console.Out during execution of an MSTest test - c#

Context:
We have some users reporting issues with a file upload feature in our web application. It only happens occasionally and without any special pattern. We have been trying to figure it out for a long time, adding debug information anywhere we can think it might help, crawling the logs etc, but we have not been able to reproduce or figure it out.
Problem:
I'm now trying to reproduce this by using MSTest and WatiN to repeat the operation that is supposed to fail a large number of times (several hundreds). Just to have a clue about how far in the loop the test has gotten, I want to print something like:
Console.WriteLine(String.Format("Uploaded file, attempt {0} of {1}", i, maxUploads));
This does however not appear in the Output window. Now I know that you'll get the console output in the test results (as well as what you output from Debug.Writeline etc), but this is not available until after the test has finished. And since my test with hundreds of repetitions could take quite some time, I'd like to know how far it has gotten.
Question:
Is there a way I can get the console output in the Output window during test execution?

The Console output is not appearing is because the backend code is not running in the context of the test.
You're probably better off using Trace.WriteLine (In System.Diagnostics) and then adding a trace listener which writes to a file.
This topic from MSDN shows a way of doing this.
According to Marty Neal's and Dave Anderson's comments:
using System;
using System.Diagnostics;
...
Trace.Listeners.Add(new TextWriterTraceListener(Console.Out));
// or Trace.Listeners.Add(new ConsoleTraceListener());
Trace.WriteLine("Hello World");

Use the Debug.WriteLine. This will display your message in the Output window immediately. The only restriction is that you must run your test in Debug mode.
[TestMethod]
public void TestMethod1()
{
Debug.WriteLine("Time {0}", DateTime.Now);
System.Threading.Thread.Sleep(30000);
Debug.WriteLine("Time {0}", DateTime.Now);
}
Output

I found a solution of my own. I know that Andras answer is probably the most consistent with MSTEST, but I didn't feel like refactoring my code.
[TestMethod]
public void OneIsOne()
{
using (ConsoleRedirector cr = new ConsoleRedirector())
{
Assert.IsFalse(cr.ToString().Contains("New text"));
/* call some method that writes "New text" to stdout */
Assert.IsTrue(cr.ToString().Contains("New text"));
}
}
The disposable ConsoleRedirector is defined as:
internal class ConsoleRedirector : IDisposable
{
private StringWriter _consoleOutput = new StringWriter();
private TextWriter _originalConsoleOutput;
public ConsoleRedirector()
{
this._originalConsoleOutput = Console.Out;
Console.SetOut(_consoleOutput);
}
public void Dispose()
{
Console.SetOut(_originalConsoleOutput);
Console.Write(this.ToString());
this._consoleOutput.Dispose();
}
public override string ToString()
{
return this._consoleOutput.ToString();
}
}

I had the same issue and I was "Running" the tests. If I instead "Debug" the tests the Debug output shows just fine like all others Trace and Console.
I don't know though how to see the output if you "Run" the tests.

It's not the console, but it is in the output panel.
public class Test
{
public TestContext TestContext { get; set; }
[TestMethod]
public void Foo()
{
TestContext.WriteLine("Hello World");
}
}

You better setup a single test and create a performance test from this test. This way you can monitor the progress using the default tool set.

Related

How to get output from unit test [duplicate]

Context:
We have some users reporting issues with a file upload feature in our web application. It only happens occasionally and without any special pattern. We have been trying to figure it out for a long time, adding debug information anywhere we can think it might help, crawling the logs etc, but we have not been able to reproduce or figure it out.
Problem:
I'm now trying to reproduce this by using MSTest and WatiN to repeat the operation that is supposed to fail a large number of times (several hundreds). Just to have a clue about how far in the loop the test has gotten, I want to print something like:
Console.WriteLine(String.Format("Uploaded file, attempt {0} of {1}", i, maxUploads));
This does however not appear in the Output window. Now I know that you'll get the console output in the test results (as well as what you output from Debug.Writeline etc), but this is not available until after the test has finished. And since my test with hundreds of repetitions could take quite some time, I'd like to know how far it has gotten.
Question:
Is there a way I can get the console output in the Output window during test execution?
The Console output is not appearing is because the backend code is not running in the context of the test.
You're probably better off using Trace.WriteLine (In System.Diagnostics) and then adding a trace listener which writes to a file.
This topic from MSDN shows a way of doing this.
According to Marty Neal's and Dave Anderson's comments:
using System;
using System.Diagnostics;
...
Trace.Listeners.Add(new TextWriterTraceListener(Console.Out));
// or Trace.Listeners.Add(new ConsoleTraceListener());
Trace.WriteLine("Hello World");
Use the Debug.WriteLine. This will display your message in the Output window immediately. The only restriction is that you must run your test in Debug mode.
[TestMethod]
public void TestMethod1()
{
Debug.WriteLine("Time {0}", DateTime.Now);
System.Threading.Thread.Sleep(30000);
Debug.WriteLine("Time {0}", DateTime.Now);
}
Output
I found a solution of my own. I know that Andras answer is probably the most consistent with MSTEST, but I didn't feel like refactoring my code.
[TestMethod]
public void OneIsOne()
{
using (ConsoleRedirector cr = new ConsoleRedirector())
{
Assert.IsFalse(cr.ToString().Contains("New text"));
/* call some method that writes "New text" to stdout */
Assert.IsTrue(cr.ToString().Contains("New text"));
}
}
The disposable ConsoleRedirector is defined as:
internal class ConsoleRedirector : IDisposable
{
private StringWriter _consoleOutput = new StringWriter();
private TextWriter _originalConsoleOutput;
public ConsoleRedirector()
{
this._originalConsoleOutput = Console.Out;
Console.SetOut(_consoleOutput);
}
public void Dispose()
{
Console.SetOut(_originalConsoleOutput);
Console.Write(this.ToString());
this._consoleOutput.Dispose();
}
public override string ToString()
{
return this._consoleOutput.ToString();
}
}
I had the same issue and I was "Running" the tests. If I instead "Debug" the tests the Debug output shows just fine like all others Trace and Console.
I don't know though how to see the output if you "Run" the tests.
It's not the console, but it is in the output panel.
public class Test
{
public TestContext TestContext { get; set; }
[TestMethod]
public void Foo()
{
TestContext.WriteLine("Hello World");
}
}
You better setup a single test and create a performance test from this test. This way you can monitor the progress using the default tool set.

Visual Studio Code Cant get output from a C# code

I'm trying to run a simple Hello World code in VSC 1.13.1.
using System;
public class Hello1
{
public static void Main()
{
Console.WriteLine("Hello, World!");
}
}
It successfully completes execution but doesnt produce any output ie - Hello, World!
Any help please!
Using Code Runner.
Add Console.ReadKey() , so the output will be there until the key is pressed
public static void Main()
{
Console.WriteLine("Hello, World!");
Console.ReadKey();
}
There currently seems to be a problem with VSCode (or the C# extension). Other StackOverflow answers show that this didn't work a few years ago, then it started working, and now (2018) it doesn't work once again.
I'm having the same problem. The workaround I found is this: If I run my code in the debugger (Debug > Start Debugging), it shows the output. But if I just run it normally, it doesn't. That's the only workaround I've found or read about that works for me.
Another option is to start the project with ctrl + F5 instead of just F5, it will keep the terminal open until you press a key as well
How to keep the console window open in Visual C++?
It have come to my attention that Using Code Runner, at this time, indeed produces some inconsistent behavior for JS as well.
However, on a first look you have not installed the proper supporting addons (which may be the cause for your particular problem):
Code Runner requires : "To run C# script, you need to install scriptcs"
Which is said to use Chocolatey - package manager for Windows.
For the moment, disabling the extension, restarting VSCode and then enabling it - fixed the current common problem for JS (not always producing an output). Which may be preceding with C#, as well.
NB! Make sure you save your files manually before you run them using Code Run
I will test this today and add the results.
Test Results: After installing scriptcs and Chocolatey your HelloWorld.cs file can run, BUT will not produce result.The reason: the code is treated as a script. Meaning that there is nothing invoking the Main() method. Meaning, you have to do it. Example:
using System;
public class Hello
{
public static void Main()
{
var message = "hiiii inside => Works" ;
Console.WriteLine(message);
HW();
}
public static void HW(){
Console.WriteLine("Hello, World!");
// the ReadLine will not work because it is only one way solution : ouptut only
// var a = Console.ReadLine();
// Console.WriteLine("key pressed: " + a + "Doesn't work");
}
}
Hello.Main();
//can be used like this as well
var message= "Hey helloooo outside WORKS";
Console.WriteLine(message);
Use Ctrl+Alt+N to start and Ctrl+Alt+M to stop(if hung). And it will hung, if you use Console.ReadLine(); - check(uncomment) the example code in the HW() method.
P.S. Namespaces can't be used in scripts - will be the error message you get, if you try to use them with Code Runner
Well, Code Runner is a tool to run C# script. It will treat the main method as a normal method and will not call it.
You should just write the Main method:
System.Console.WriteLine("hello, world");
or
static class Test
{
public static void Main()
{
System.Console.WriteLine("hello, world");
}
}
Test.Main();

CodedUI : The Browser gets closed as finish testing without keeping for testing further steps

I'm working on a CodedUI project to check on a Web Solution.
There, when Im testing for launching the site (as in launching the web URL), I am facing an issue with closing the browser as it finish testing, where it wont allow to use the same browser instance for further testing, Unless if I keep open a instance of a browser (IE) prior manually before running the test.
Can anyone please assist me with this, where I was unable to find a suitable solution. I even went through articles in MSDN where I posted regarding this issue as a comment which I'm facing, since I tried various ways of Code Snippets so far.
(MSDN : http://blogs.msdn.com/b/visualstudioalm/archive/2012/11/08/using-same-applicationundertest-browserwindow-across-multiple-tests.aspx)
My written code is provided below.
---
-- common.cs
[TestMethod]
public void LoadLocalHost()
{
this.UIMap.LoadLocalHost();
}
---
-- UIMap.Designer.cs
public void LoadLocalHost()
{
this.UIMsnInternetExplorerWindow.LaunchUrl(new System.Uri("http://localhost:5500/"));
Console.WriteLine(UIMsnInternetExplorerWindow.CloseOnPlaybackCleanup);
UIMsnInternetExplorerWindow.CloseOnPlaybackCleanup = false;
}
Highly appreciate an assistance from some one who can.
If you launch the browser in a class Initialize method rather than a test initialize method, and don't close it in your test or in a test cleanup, it should remain open for the duration of your tests, provided they are all executed within the same test class.
[ClassInitialize]
public void classInitialize()
{
// Do some stuff, including launch the browser
// This is executed once per class.
}
[TestInitialize]
public void testInitialize()
{
// This is where you'd get the test back to a specific
// state, like bring your browser back to a home page or something.
// It would be executed at the beginning of each test.
}
....
[TestMethod]
public void myFirstTest()
{
// Do some more stuff specific to your test.
}
[TestMethod]
public void mySecondTest()
{
// Do things after the last test.
}
....
[ClassCleanup]
public void classCleanup()
{
// Finalize everything and close the browser.
}

Why do my tests fail when run together, but pass individually?

When I write a test in Visual Studio, I check that it works by saving, building and then running the test it in Nunit (right click on the test then run).
The test works yay...
so I Move on...
Now I have written another test and it works as I have saved and tested it like above. But, they dont work when they are run together.
Here are my two tests that work when run as individuals but fail when run together:
using System;
using NUnit.Framework;
using OpenQA.Selenium.Support.UI;
using OpenQA.Selenium;
namespace Fixtures.Users.Page1
{
[TestFixture]
public class AdminNavigateToPage1 : SeleniumTestBase
{
[Test]
public void AdminNavigateToPage1()
{
NavigateTo<LogonPage>().LogonAsCustomerAdministrator();
NavigateTo<Page1>();
var headerelement = Driver.FindElement(By.ClassName("header"));
Assert.That(headerelement.Text, Is.EqualTo("Page Title"));
Assert.That(Driver.Url, Is.EqualTo("http://localhost/Page Title"));
}
[Test]
public void AdminNavigateToPage1ViaMenu()
{
NavigateTo<LogonPage>().LogonAsCustomerAdministrator();
Driver.FindElement(By.Id("menuitem1")).Click();
Driver.FindElement(By.Id("submenuitem4")).Click();
var headerelement = Driver.FindElement(By.ClassName("header"));
Assert.That(headerelement.Text, Is.EqualTo("Page Title"));
Assert.That(Driver.Url, Is.EqualTo("http://localhost/Page Title"));
}
}
}
When the second test fails because they have been run together
Nunit presents this:
Sse.Bec.Web.Tests.Fixtures.ManageSitesAndUsers.ChangeOfPremises.AdminNavigateToChangeOfPremises.AdminNavigateToPageChangeOfPremisesViaMenu:
OpenQA.Selenium.NoSuchElementException : The element could not be found
And this line is highlighted:
var headerelement = Driver.FindElement(By.ClassName("header"));
Does anyone know why my code fails when run together, but passes when run alone?
Any answer would be greatly appreciated!
Such a situation normally occurs when the unit tests are using shared resources/data in some way.
It can also happen if your system under test has static fields/properties which are being leveraged to compute the output on which you are asserting.
It can happen if the system under test is being shared (static) dependencies.
Two things you can try
put the break point between the following two lines. And see which page are you in when the second line is hit
Introduce a slight delay between these two lines via Thread.Sleep
Driver.FindElement(By.Id("submenuitem4")).Click();
var headerelement = Driver.FindElement(By.ClassName("header"));
If none of the answers above worked for you, i solved this issue by adding Thread.Sleep(1) before the assertion in the failing test...
Looks like tests synchronization is missed somewhere... Please note that my tests were not order dependant, that i haven't any static member nor external dependency.
look into the TestFixtureSetup, Setup, TestFixtureTearDown and TearDown.
These attributes allow you to setup the testenvironment once, instead of once per test.
Without knowing how Selenium works, my bet is on Driver which seems to be a static class so the 2 tests are sharing state. One example of shared state is Driver.Url. Because the tests are run in parallel, there is a race condition to set the state of this object.
That said, I do not have a solution for you :)
Are you sure that after running one of the tests the method
NavigateTo<LogonPage>().LogonAsCustomerAdministrator();
is taking you back to where you should be? It'd seem that the failure is due to improper navigation handler (supposing that the header element is present and found in both tests).
I think you need to ensure, that you can log on for the second test, this might fail, because you are logged on already?
-> putting the logon in a set up method or (because it seems you are using the same user for both tests) even up to the fixture setup
-> the logoff (if needed) might be put in the tear down method
[SetUp]
public void LaunchTest()
{
NavigateTo<LogonPage>().LogonAsCustomerAdministrator();
}
[TearDown]
public void StopTest()
{
// logoff
}
[Test]
public void Test1()
{...}
[Test]
public void Test2()
{...}
If there are delays in the DOM instead of a thread.sleep I recommend to use webdriver.wait in combination with conditions. The sleep might work in 80% and in others not. The wait polls until a timeout is reached which is more reliable and also readable. Here an example how I usually approach this:
var webDriverWait = new WebDriverWait(webDriver, ..);
webDriverWait.Until(d => d.FindElement(By.CssSelector(".."))
.Displayed))
I realize this is an extremely old question but I just ran into it today and none of the answers addressed my particular case.
Using Selenium with NUnit for front end automation tests.
For my case I was using in my startup [OneTimeSetUp] and [OneTimeTearDown] trying to be more efficient.
This however has the problem of using shared resources, in my case the driver itself and the helper I use to validate/get elements.
Maybe a strange edge case - but took me a few hours to figure it out.

COM exceptions on exit with WPF

After execution both of the following test cases, a COM execution is printed to the console. What am I doing wrong?
If I run either test singly, or if I run both tests together, the exception is written to the console exactly once. This makes me suspect that there's some sort of a per-AppDomain resource that I'm not cleaning up.
I have tried the tests with NUnit and with MSTest, with the same behavior in both environments. (Actually, I'm not sure if running both tests in MSTest results in a single exception printout or two.)
Exception:
System.Runtime.InteropServices.InvalidComObjectException: COM object that has been separated from its underlying RCW cannot be used.
at System.Windows.Input.TextServicesContext.StopTransitoryExtension()
at System.Windows.Input.TextServicesContext.Uninitialize(Boolean appDomainShutdown)
at System.Windows.Input.TextServicesContext.TextServicesContextShutDownListener.OnShutDown(Object target)
at MS.Internal.ShutDownListener.HandleShutDown(Object sender, EventArgs e)
Test code:
using NUnit.Framework;
namespace TaskdockSidebarTests.Client
{
[TestFixture, RequiresSTA]
public class ElementHostRCWError
{
[Test]
public void WinForms()
{
var form = new System.Windows.Forms.Form();
var elementHost = new System.Windows.Forms.Integration.ElementHost();
form.Controls.Add(elementHost);
// If the form is not shown, the exception is not printed.
form.Show();
// These lines are optional. The exception is printed with or without
form.Close();
form.Controls.Remove(elementHost);
elementHost.Dispose();
form.Dispose();
}
[Test]
public void WPF()
{
var window = new Window();
// If the window is not shown, the exception is not printed.
window.Show();
window.Close();
}
}
}
Looking at my own code again, the following line might help for the WPF test, right at the end.
Dispatcher.CurrentDispatcher.InvokeShutdown();
You probably can't unit test the Window and Form classes at all. Both WinForms applications and WPF applications have an Application class used to start the underlying plumbing (message pumps and whatnot). I bet it's the key to avoiding that exception.
You're not doing that there and may not be able to.
Every recommendation for unit testing I've ever read is that you refactor so that the Form classes and Window classes don't do anything you need to unit test (like the M-V-VM pattern in WPF). Could have something to do with not being able to show the UI.
There are other ways to test a UI. This answer discusses unit testing UI.

Categories