Search code examples
unit-testingxunit.net

Is Assert.Fail() considered bad practice?


I use Assert.Fail a lot when doing TDD. I'm usually working on one test at a time but when I get ideas for things I want to implement later I quickly write an empty test where the name of the test method indicates what I want to implement as sort of a todo-list. To make sure I don't forget I put an Assert.Fail() in the body.

When trying out xUnit.Net I found they hadn't implemented Assert.Fail. Of course you can always Assert.IsTrue(false) but this doesn't communicate my intention as well. I got the impression Assert.Fail wasn't implemented on purpose. Is this considered bad practice? If so why?


@Martin Meredith That's not exactly what I do. I do write a test first and then implement code to make it work. Usually I think of several tests at once. Or I think about a test to write when I'm working on something else. That's when I write an empty failing test to remember. By the time I get to writing the test I neatly work test-first.

@Jimmeh That looks like a good idea. Ignored tests don't fail but they still show up in a separate list. Have to try that out.

@Matt Howells Great Idea. NotImplementedException communicates intention better than assert.Fail() in this case

@Mitch Wheat That's what I was looking for. It seems it was left out to prevent it being abused in another way I abuse it.


Solution

  • For this scenario, rather than calling Assert.Fail, I do the following (in C# / NUnit)

    [Test]
    public void MyClassDoesSomething()
    {
        throw new NotImplementedException();
    }
    

    It is more explicit than an Assert.Fail.

    There seems to be general agreement that it is preferable to use more explicit assertions than Assert.Fail(). Most frameworks have to include it though because they don't offer a better alternative. For example, NUnit (and others) provide an ExpectedExceptionAttribute to test that some code throws a particular class of exception. However in order to test that a property on the exception is set to a particular value, one cannot use it. Instead you have to resort to Assert.Fail:

    [Test]
    public void ThrowsExceptionCorrectly()
    {
        const string BAD_INPUT = "bad input";
        try
        {
            new MyClass().DoSomething(BAD_INPUT);
            Assert.Fail("No exception was thrown");
        }
        catch (MyCustomException ex)
        {
             Assert.AreEqual(BAD_INPUT, ex.InputString); 
        }
    }
    

    The xUnit.Net method Assert.Throws (or variances ThrowsAsync, ThrowsAny) makes this a lot neater without requiring an Assert.Fail method. By not including an Assert.Fail() method xUnit.Net encourages developers to find and use more explicit alternatives, and to support the creation of new assertions where necessary.