102

I'm running JUnit tests on a large code base, and I've been realizing that sometimes I get "Errors" while other times I get "Failures". What's the difference?

froadie
  • 79,995
  • 75
  • 166
  • 235

9 Answers9

121

Failures are when your test cases fail – i.e. your assertions are incorrect.

Errors are when unexpected errors/exceptions occur - i.e. while trying to actually run the test and an unexpected exception is thrown like FileNotFound, etc`.

Ahmed Nabil
  • 17,392
  • 11
  • 61
  • 88
froadie
  • 79,995
  • 75
  • 166
  • 235
  • 5
    Though if anything extending `java.lang.AssertionError` is thrown it will be shown as a test failure instead of a test error. You should consider accepting your own answer because it is correct. – ponzao Aug 12 '10 at 14:15
  • Yes, that's exactly the difference. And from a pragmatic perspective there is "no difference" -- in that if you get an error or a failure, then you need to fix it. So it was probably a mistake to count "failures" and "errors" separately in JUnit. JUnit 4 combines the two (as explained in an answer below). – Jeff Grigg May 15 '13 at 01:04
  • And if the exception is expected, you should annotated the `@Test` with `expected = SomeException.class`. – Downhillski Aug 03 '17 at 17:10
  • @JeffGrigg there is a pragmatic difference. If one behavior is being relied on in multiple test cases, I can still write only one test case that asserts that behavior, while throwing uncaught, likely run time exceptions in all the rest. This is saying that the rest of the test cases are testing something else even though they still depend on that particular behavior in order to run. When that behavior is broken, only one test case will report failure while the rest reports error, and from this I can see that I have exactly one bug to fix even though many test cases did not pass. – RonJRH Mar 19 '18 at 18:01
  • org.junit.Assert.assertEquals() if fails is considered ERROR by JUnit4 HTML report. This contradicts your statement(which i was aware of till now). Can you please put more light on this? – Krishnom May 13 '19 at 09:55
16

If your test throws an exception which does not get bubbled up through the Assertion framework in Junit, it gets reported as an error. For example, a NullPointer, or a ClassNotFound exception will report an error:

String s = null;
s.trim();

or,

try {

    // your code
} catch(Exception e) {
    // log the exception
    throw new MyException(e);
}

Having said that, the following will report a failure:

Assert.fail("Failure here");

or,

Assert.assertEquals(1, 2);

or even:

throw new AssertionException(e);

It depends on the Junit version you are using. Junit 4- will make the distinction between a failure and an error, but Junit 4 simplifies it as failures only.

Following link provides more interesting inputs:

http://www.devx.com/Java/Article/31983/1763/page/2

Neel
  • 2,100
  • 5
  • 24
  • 47
  • This is not accurate. The distinction between test failure and test error is not gone in JUnit 4. I have just tested it. The linked article was misleading. It said "JUnit 4 makes it simpler by only using failures" but it should emphasize that JUnit 4 turns java.lang.AssertionError into test failures so you don't have to use junit.framework.AssertionFailedError. The benefit is that you can start writing test assertions in the production code without the project linking to JUnit. Distinction between test error and test failure is also immensely useful and would be a step backwards if removed. – RonJRH Mar 19 '18 at 17:46
  • RonJRH, are you able to see the errors in your default junit report? – Neel Mar 19 '18 at 17:49
  • Yes Neel. I just tried it. Not exactly sure the etique of linking image here but this shows the result of my test: http://imagebucket.net/abpxucddkvn1/Capture.PNG – RonJRH Mar 19 '18 at 17:51
7

From "Pragmatic Unit Testing in Java 8 with JUnit":

Assertions (or asserts) in JUnit are static method calls that you drop into your tests. Each assertion is an opportunity to verify that some condition holds true. If an asserted condition does not hold true, the test stops right there, and JUnit reports a test failure.

(It’s also possible that when JUnit runs your test, an exception is thrown and not caught. In this case, JUnit reports a test error.)

Matias Elorriaga
  • 8,880
  • 5
  • 40
  • 58
6

Below test explains the difference between Test Error vs Test failure.

I have commented the line which throws test error and test failure.

    @Test
    public void testErrorVsTestFailure() {

        final String sampleString = null;

        assertEquals('j', sampleString.charAt(0) );
        //above line throws test error as you are trying to access charAt() method on null reference

        assertEquals(sampleString, "jacob");
        //above line throws Test failure as the actual value-a null , is not equal to expected value-string "jacob"
        }

So Junit shows test error whenever you get an exception , and test failure when your expected result value doesn't match your actual value

Vombat
  • 1,156
  • 1
  • 15
  • 27
Deen John
  • 3,522
  • 4
  • 29
  • 32
2

Source class : JUnitReportReporter.java

public void generateReport(List<XmlSuite> xmlSuites, List<ISuite> suites, String defaultOutputDirectory) {
//......

            for (ITestResult tr : (Set) entry.getValue()) {
                TestTag testTag = new TestTag();

                boolean isSuccess = tr.getStatus() == 1;
                if (!(isSuccess)) {
                    if (tr.getThrowable() instanceof AssertionError)
                        ++errors;
                    else {
                        ++failures;
                    }
                }
}

As you can see below line in above method

tr.getThrowable() instanceof AssertionError

errors count is increased when it is instance of AssertionError otherwise(any Throwable) is counted as failures.

Roushan
  • 4,074
  • 3
  • 21
  • 38
2

You are right that failures come from the AssertionErrors thrown by the JUnit assertion methods, or by throwing an AssertionError, or by throwing an exception that you declared in your @Test annotation, and Errors come from other, unexpected Exceptions. But there's an important distinction between them:

A failure means your test ran correctly, and identified a defect in your code.

An error could mean a bug in your code, but one that you weren't even testing for. It could also mean that the bug is in the test itself.

In short, a failure means you need to rewrite the code that is being tested. An error means that it may be the unit test that you need to rewrite. It may mean this even if the failure was in your code, such as a NullPointerException, because you detected a flaw that you weren't even testing for, so it might be wise to test for that.

BuZZ-dEE
  • 6,075
  • 12
  • 66
  • 96
MiguelMunoz
  • 4,548
  • 3
  • 34
  • 51
  • Great response. Think that the ultimate goal for a unit test is to answer the question : There is a bug in the code tested? If a test returns "pass", that means that answer is "No, this test cannot reveal a bug in the code under test". If a test returns "fail", that means that the answer is: "Yes, there is a bug in your code under test"but, If a test returns "error", that means that answer is "I don't know if the code under test has a bug" Therefore, "errors" must be avoided if possible, in that maybe the bug is in the test code, and not in the code under test. – dora Apr 09 '21 at 15:51
2
Test Method Throws Test Outcome
java.lang.AssertionError failure
org.junit.AssumptionViolatedException skipped
an expected exception OK
any other exception error
no exception OK
exception outside of a test method error
  • The assert methods just throw AssertionExceptions.
  • An exception is declared expected in the @Test annotation.
  • Code outside of test methods can be stuff annotated with @Before, @BeforeClass and so on.
  • The counts in the IDE reports count tests (test methods), not assertions, because the first failed assertion terminates the test.
  • As a rule of thumb, if the test method terminates abnormally (not with a return statement), it is unsuccessful, and vice versa.
hobgoblin
  • 107
  • 1
  • 4
1

Ironically, junit and other testing related frameworks (testng, hamcrest) provide assert operations which verify condition and if it fails then "under-the-hood" a java.lang.AssertionError is being thrown, which btw extends java.lang.Error.

But it no way contradicts with answers above which are fully valid of course. So in order to mark specific test flow as failure one can throw AssertionError, however I'm not sure it's really documented in corresponding manuals, because more appropriate to use dedicated fail() API. Other kinds of Throwable will be considered as errors, not failures.

agolubev81
  • 41
  • 4
0

Basically, failures refer to unfulfilled assertions while errors are due to abnormal test execution. and I think each IDE has symbolic icons with different colors for passed, failed, and with error tests.

For more information, check this.

Soufiane Roui
  • 660
  • 6
  • 19