Reputation: 34309
I have a bunch of automated UI tests running with selenium and NUnit.
After every nunit test I want to check the browser for any JS errors that have occurred. If there are any JS errors the test that caused them should fail. I want this to run for all tests I write without having to copy the check into each test.
I also take screenshots on any failure.
[TearDown]
public void TearDown()
{
Assert.Fail("Some JS error occurred"); //This is to simulate a JS error assertion
if (TestContext.CurrentContext.Result.Status != TestStatus.Passed)
{
Driver.TakeScreenshot(TestContext.CurrentContext.Test.Name, "Failed");
}
}
If I fail an assertion inside teardown it will never execute the screenshot code (as the assert is an exception).
Is there a better way to fail the test here so that I can carry on with my logic?
Upvotes: 3
Views: 3816
Reputation: 763
You could extend your own TestActionAttribute
that runs your JS tests. If an assertion failure is thrown in AfterTest()
, NUnit seems to report the test as being failed.
E.g. this:
[CheckForJSErrors] // your custom attribute - applies to all tests
public class ClassTest
{
[Test]
public void MyTest()
{
// Your test case
}
}
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class)]
public class CheckForJSErrorsAttribute : TestActionAttribute
{
public override void AfterTest(TestDetails testDetails)
{
// if you only want to check for JS errors if the test passed, then:
if(TestContext.CurrentContext.Result.Status == TestStatus.Passed)
{
Driver.TakeScreenshot(testDetails.FullName, "Failed");
Assert.Fail("Some JS error occurred"); //This is to simulate a JS error assertion
}
}
public override ActionTargets Targets
{
// explicitly says to run this after each test, even if attr is defined on the entire test fixture
get { return ActionTargets.Test; }
}
}
Produces this failure in NUnit:
SO_34306757.ClassTest.MyTest:
TearDown : NUnit.Framework.AssertionException : Some JS error occurred
I've declared the [CheckForJSErrors]
attribute for the entire test fixture to avoid having to declare it on every test case, but you could declare it per test method if you want.
Upvotes: 2
Reputation: 9603
If you want to check the same thing after every test, you could just right a common method that you call in each test itself. That way you're not duplicating the test code and you are keeping the fail assert out of the tear down.
Eg.
[Test]
public void Test1()
{
// sometest code
TestJS();
}
[Test]
public void Test2()
{
// some other test code
TestJS();
}
public void TestJS()
{
Assert.Fail("Or whatever to test the JS");
}
[TearDown]
public void TearDown()
{
if (TestContext.CurrentContext.Result.Status != TestStatus.Passed)
{
Driver.TakeScreenshot(TestContext.CurrentContext.Test.Name, "Failed");
}
}
Upvotes: 0