Is it Ok to ignore exceptions in TearDown or cleanup code - c#

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.

Related

How to test Program.Main in TestMethod in MSTest project

I have a simple test method so far just to call the static method Main in Program.cs on a netcore mvc app.
My assert is never hit and the test just keeps running in the test explorer, even after 5 or 10min. Is it because the Program needs termination or is my implementation wrong for the test?
Advice appreciated
Thanks
Rob
[TestClass]
public class ProgramTests
{
[TestMethod]
public void ExecMain()
{
var args = new string[] { };
Program.Main(args);
// never hits test condition and test keeps running
Assert.IsTrue(true);
}
}
Your implementation is not wrong since you are following the AAA practice (Arrange, Act, Assert).
It seems, however, that you have not figured out what is to be tested. Are you expecting Program.Main to run forever? or should it terminate in some point? (something or someone should probably cause termination.)
If you can find out how to cause termination, you should do it in your test and then make the assertion (which obviously reflects your expectations from termination.)

Resharper if Unit Test Fails Always Run Specific Code

This may or may not be the correct way to do it. I am running unit tests that create an object via COM and runs some tests on the object. I have set the tests thus far to use:
[ClassInitialize]
public static void Setup()
{
// Code to create object
}
[TestMethod()]
public void SomeMethod()
{
// Run the tests on object
}
[ClassCleanup]
public static void UnSetup()
{
// Dispose of object
}
The problem is sometimes while I am debugging or some other unit test fails, the UnSetup() function does not run because the unit tests end prematurely. This leaves me with an object that should have been deleted, thus throwing in error in the unit test. What is the best way to tackle this?
p.s. Other tests also use the object which is why I use [ClassCleanup] not [TestCleanup]

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].

The TestContext.TestName property NEVER changes

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

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.

Categories