undefined
undefined

Reputation: 34309

Failing an NUnit test inside teardown

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

Answers (2)

Jeff P
Jeff P

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

Steve
Steve

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

Related Questions