The TestContext.TestName property NEVER changes - c#

GOAL:
I want to use the TestContext.TestName property to extract the name of the test being ran so that my [TestCleanup] function can log the outcome to our bespoke results repository, automatically when every test completes.
PROBLEM:
Even in my basic 'sanity check' test project that contains 5 tests that are similar to the structure below:
[TestMethod]
public void TestMethodX()
{
Console.WriteLine(String.Format("In Test '{0}'",_ctx.TestName));
Assert.IsTrue(true);
}
With a Class 'initializer' like below which sets _ctx for me:
[ClassInitialize]
public static void ClassInit(TestContext Context)
{
_ctx = Context;
Console.WriteLine("In ClassInit()");
}
[[NOTE: the Console.WriteLines are purely there for me to hover the mouse over and inspect value/properties, etc.]]
The _ctx.TestName NEVER changes from the name of the first test in the run of tests, i.e. If I was to run all five tests ('TestMethod1', 'TestMethod2', 'TestMethod3', etc.) they all log 'TestMethod1' as their testname in my results repository.
Running the tests individually it works fine, but that is of no use to me as I need to be able to run 10's/100's/1000's of tests against my application and have the testContext handle the testname or me.
I have tried this several times now and searched the internet loads and haven't anyone else with this problem, so i'm either: unique with this problem, have poor 'Google-Fu' skills, or am doing something REAL stupid. Hopefully this makes sense and someone has the answer.
Thanks in advance,
Andy

This is happening because the [ClassInitialize] is executed only once for the whole test run and you initialize the _ctx in there. Use the [TestInitialize] instead, which is executed before each test method and override the TestContext Class :
[TestClass]
public class TestClass
{
public TestContext TestContext { get; set; }
[TestInitialize]
public void Initialize()
{
// Runs once before each test method and logs the method's name
Console.WriteLine(TestContext.TestName);
}
[TestMethod]
public void TestMethod1()
{
// Logs the method name inside the method
Console.WriteLine(String.Format("In Test '{0}'", TestContext.TestName));
}
// ... Your rest test methods here
}

MSTest.exe outputs can be configured to output a .trx (xml)file with the complete results of you test, names , passed or failed and output from any of those test, there is also a tool to convert the TRX file to HTML http://trxtohtml.codeplex.com/
Hope this helps

Related

Selenium doesn't close any browsers until ALL tests are complete

I'm doing something like this (below) with multiple Test Classes but [ClassCleanup] is not called until ALL tests run.
Because of this each class starts up a browser and ALL of the browsers remain open until ALL of the tests are completed, and then they ALL close down.
Is this expected?
Could someone comment if their tests do the same thing?
Is there a way to force a browser to close when the test class is done?
[ClassCleanup]
public static void ClassCleanup()
{
driver.Quit();
I dont know if this is just how Selenium is supposed to work, or if I have some sort of hanging resource that doesn't allow the browser to close until the end?
I cannot use [TestCleanup] because then I cannot have multiple tests in the same test class (as it will close before the 2nd test will run)
I finally found an example that works :)
Simply replaced
[ClassCleanup]
with
[ClassCleanup(ClassCleanupBehavior.EndOfClass)]
you can use [TestInitialize] as setUp and [TestCleanup] as Teardown of each test case.
In your code, it runs after class(all test cases)
So full code:
Setup:
[TestInitialize()]
public void InitializeTest() {
//your driver initilazation code
}
and, Teardown:
[TestCleanup]
public void Cleanup() {
driver.Quit();
}

Load testing Visual Studio, start up script / setup

I was wondering if it was possible to have a start-up script before running any load tests? For example, perhaps to seed some data or clear anything down prior to the tests executing.
In my instance I have a mixed bag of designer and coded tests. Put it simply, I have:
Two coded tests
A designer created web test which points to these coded tests
A load test which runs the designer
I have tried adding a class and decorating with the attributes [TestInitialize()], [ClassInitialize()] but this code doesn't seem to get run.
Some basic code to show this in practice (see below). Is there a way of doing this whereby I can have something run only the once before test run?
[TestClass]
public class Setup : WebTest
{
[TestInitialize()]
public static void Hello()
{
// Run some code
}
public override IEnumerator<WebTestRequest> GetRequestEnumerator()
{
return null;
}
}
Probably should also mention that on my coded tests I have added these attributes and they get ignored. I have come across a workaround which is to create a Plugin.
EDIT
Having done a little more browsing around I found this article on SO which shows how to implement a LoadTestPlugin.
Visual Studio provides a way of running a script before and also after a test run. They are intended for use in deploying data for a test and cleaning up after a test. The scripts are specified on the "Setup and cleanup" page in the ".testsettings" file.
A load test plugin can contain code to run before and after any test cases are executed, also at various stages during test execution. The interface is that events are raised at various points during the execution of a load test. User code can be called when these events occur. The LoadTestStarting event is raised before any test cases run. See here for more info.
If you are willing to use NUnit you have SetUp/TearDown for a per test scope and TestFixtureSetUp/TestFixtureTearDown to do something similar for a class (TestFixture)
Maybe a bit of a hack, but you can place your code inside the static constructor of your test class as it will automatically run exactly once before the first instance is created or any static members are referenced:
[TestClass]
public class Setup : WebTest
{
static Setup()
{
// prepare data for test
}
public override IEnumerator<WebTestRequest> GetRequestEnumerator()
{
return null;
}
}

Is it Ok to ignore exceptions in TearDown or cleanup code

I have a test suite running in Automation. All of these tests are functional UI tests. It looks like below
[SetUp]
public void Setup()
{
CreatePolicy();
}
[Test]
public void Test1()
{
EditPolicyAndValidateResults();
}
[Test]
public void Test2()
{
EditPolicyAndValidateResults();
}
[TearDown]
public void TearDown()
{
DeletePolicy();
}
Now, the problem is DeletePolicy() is failing sometimes (randomly for one or two of the tests) and because of which the corresponding tests are failing.
To circumvent the failure if have added a try catch block to DeletePolicy() and it looks like the following:
[TearDown]
public void TearDown()
{
try
{
DeletePolicy();
}
catch(Exception ex)
{
// Do nothing
}
}
Since testing DeletePolicy() function is not the intent of my test cases, the approach looks fine to me. Is this correct or I am missing something here?
The general pattern of Unit Testing is: Arrange, Act then Assert: AAA.
Setup is just a designated method to Arrange the test in a better way (for example by re-setting any previously mocked/stubbed objects to save time and to avoid code duplication). It is by no means mandatory and is just a way to help test coder to code better.
TearDown again and in the same way is a helper and it is even farther to the generic concept of AAA than Setup. It is because in AAA nothing regarding destructing or cleaning up is mentioned.
So, feel free to ignore any failure in TearDown unless it is somehow important. Maybe there is something hidden from your eyes and you haven't taken into account yet. It may be important to make another unit test on failure point, but it totally depends on your case.

How can I isolate unit tests by class?

I have a number of 'unit tests' (they're really integration tests) in several classes that access a shared resource, and I want each test class to only acquire the resource once (for performance reasons).
However, I'm getting issues when I release the resource in [ClassCleanup], because that isn't running until all tests are completed.
Here's a simplified example:
using Microsoft.VisualStudio.TestTools.UnitTesting;
static class State
{
public static string Thing;
}
[TestClass]
public class ClassA
{
[ClassInitialize]
public static void Initialize(TestContext ctx)
{
State.Thing = "Hello, World!";
}
[ClassCleanup]
public static void Cleanup()
{
State.Thing = null;
}
[TestMethod]
public void TestA()
{
Assert.IsNotNull(State.Thing); // Verify we have a good state
}
}
[TestClass]
public class ClassB
{
[TestMethod]
public void TestB()
{
Assert.IsNull(State.Thing); // Verify we have an uninitialized state
// Initialize state, do stuff with it
}
}
On my machine at least, TestB fails because it runs before ClassA has been cleaned up.
I read ClassCleanup May Run Later Than You Think, but that doesn't explain any way to change the behaviour. And I realize I shouldn't depend on test ordering, but it's too expensive to re-acquire the resource for every test, so I want to group them by class.
How can I fix this? Is there a way to force each test class to run as a unit, and make the cleanup occur immediately?
Although ClassCleanup might be unreliable in terms of when it is run, ClassInitialize is not; why not give each testclass that relies on this shared resource a ClassInitialize that cleans up the shared resource of the previous test class (if any), right before acquiring the resource itself?
The only time the shared resource isn't released is for the last test class, but you could handle that with the ClassCleanup because then it doesn't matter anymore when it is run (since there won't be any more test classes following it).
Is there any reason that you cannot make this resource shared by the entire assembly all at once? Make it an internal or public static variable in one of the test classes (or a separate designated class), and refer to it directly from all the test classes. The initialization of the resource will take place in the [AssemblyInitialize] method and the cleanup will take place at the [AssemblyCleanup].

What is the scope of a test class when running unit tests?

When Visual Studio is running unit tests, it runs many tests simultaneously. What exactly is the scope of the test class while these are running. Are they all run in separate app domains or is data shared at all?
For instance if I have the following test class:
[TestClass]
public class FooTests
{
Mock<ISomeInterface1> _complexMock1;
Mock<ISomeInterface2> _complexMock2;
public void CreateComplexMocks()
{
//set up _complexMock1 & _complexMock2
}
[TestMethod]
public void Test1()
{
CreateComplexMocks();
//use _complexMock1 & _complexMock2 in test
}
[TestMethod]
public void Test2()
{
CreateComplexMocks();
//use _complexMock1 & _complexMock2 in test
}
}
The tests utilise the CreateComplexMocks() helper to construct some mocks. These are exposed as members rather than being passed back to the test (there would probably be many more in a real world example)
My question is, if both tests run at the same time, will they be sharing the state of _complexMock1 and _complexMock2?
What if the complexMocks were static?
Having found this blog, it would appear that a separate test class is instantiated for every test, on a different thread.
So instance members will not be shared, but static members will.
In your example you should create your mocks in the [TestInitialize] method.
By this every time a test would run your mocks would be created again.
[TestInitialize]
public void TestInit()
{
CreateComplexMocks();
}

Categories