-
Notifications
You must be signed in to change notification settings - Fork 3.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Tests expecting AssumptionViolatedException should be marked as passed, not skipped #1291
Conversation
Tests annotated with `@Test(expected = AssumptionViolatedException.class)` which throw AssumptionViolatedException should be marked as passing, not skipped.
If the AssumptionVaiolatedException is thrown, the unit test should fail, instead it would have been marked as skipped!
😎 |
|
||
@Test | ||
public void givenWeAreExpectingAssumptionViolatedExceptionAndAStatementThrowingAssumptionViolatedException() { | ||
ExpectException sut = new ExpectException(new StatementThrowingAssumptionViolatedException(), AssumptionViolatedException.class); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we instead test this in org.junit.tests.running.methods.ExpectedTest
in the same way we test the expected attributes? We get a bit more confidence if when test features like this by writing tests that run specific tests and verify JUnit gives the proper result for those test runs.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure I'll do that. But I also would like to keep this unit test, which is really a unit test, small.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, having both kinds of tests is fine. The integration test is necessary to verify the bug is fixed; the unit test verifies the contract of the ExpectException
class.
If we keep this test class, please have the class Javadoc say where the integration tests are (using@link
)
A few suggested changes:
- Could you update this test to use https://github.com/junit-team/junit4/blob/master/src/main/java/org/junit/internal/runners/statements/Fail.java ? That way, you can see what exception the
Statement
is throwing by looking at the test method. - Extract a local variable for the expression you pass to the
ExpectException
constructor and call that variabledelegate
. - I don't think we use
sut
as a variable name very often. If we don't, I suggest naming itexpectException
so future readers wont be confused by the name.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, if you are adding unit tests, please add a test that makes sure that tests that expect AssumptionViolatedException
but do not throw it should fail
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you update this test to use https://github.com/junit-team/junit4/blob/master/src/main/java/org/junit/internal/runners/statements/Fail.java ?
done
Extract a local variable for the expression you pass to the ExpectException constructor and call that variable delegate
Done, but I gave it a more meaningful name, although a bit longer: statementThrowingAssumptionViolatedException
I don't think we use sut as a variable name very often. If we don't, I suggest naming it expectException so future readers wont be confused by the name
Done but I would suggest to consider adopting it.
I think I took it from xunitpatterns, see e.g. http://xunitpatterns.com/Test%20Stub.html (scroll to "Motivating Example"):
public void testDisplayCurrentTime_AtMidnight() {
// fixture setup
TimeDisplay sut = new TimeDisplay();
// exercise sut
String result = sut.getCurrentTimeAsHtmlFragment();
// verify direct output
String expectedTimeString = "<span class=\"tinyBoldText\">Midnight</span>";
assertEquals( expectedTimeString, result);
}
I find it a great name as it clearly stands out among the many variables (the DOCs, following Meszaros's terminology) which may be defined in a unit test.
It also makes it extremely easy to distinguish the "when" step: it's the one (and only, in theory) of the form sut.method(inputs)
. In the example above, sut.getCurrentTimeAsHtmlFragment();
Also, if you are adding unit tests, please add a test that makes sure that tests that expect AssumptionViolatedException but do not throw it should fail
Done. I've also added a couple more scenarios:
- scenario where the given statement passes
- scenario where the statement throws subclass of AssumptionViolatedEx
This fix looks fine. However, I'm not sure this use case makes sense. @alb-i986 You had a test in your codebase that used |
sut.evaluate(); | ||
// then no exception should be thrown | ||
} catch (Throwable e) { | ||
fail("should not throw anything, but was thrown: " + e); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No need to catch unexpected exceptions; if evaluate
throws an exception then the test would fail.
Edit: Woops! I see why you need to do an explicit catch; without your fix this test would not fail because of the assumption failure exception being thrown.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ya right! Tricky uh? :) Testing JUnit with JUnit is tricky itself
@marcphilipp we have tests like this in JUnit. See #1290 |
As Kevin said, no I don't, I've found one in JUnit itself: I share your concern in #1290, where I was commenting
However, I think the scenario may happen outside as well, although rare. |
I agree that no one should ever expect This change seems safe. The tests were previously marked as skipped, and now they will be marked as passing. Then again, some users might expect that any test method with a violated assumption should be marked as skipped. Another option is to have tests annotated with |
- var name: sut -> expectException - rename test method name - class javadoc linking to the integration tests - add a test verifying that tests that expect AssumptionViolatedException but do not throw should fail - add scenario where the given statement passes - add scenario where the statement throws subclass
I tend to think that we should mark them as passing. @junit-team/junit-committers Opinions? |
@Test | ||
public void whenExpectingAssumptionViolatedExceptionStatementsThrowingItShouldPass() { | ||
Statement statementThrowingAssumptionViolatedException = new Fail(new AssumptionViolatedException("expected")); | ||
ExpectException expectException = new ExpectException(statementThrowingAssumptionViolatedException, AssumptionViolatedException.class); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you want to keep the long variable name for the Statement arg then please wrap this line to make it readable:
ExpectException expectException = new ExpectException(
statementThrowingAssumptionViolatedException,
AssumptionViolatedException.class);
But I really prefer delegate
or delegateStatement
because that is what the role of the Statement is for the sut. The variable is declared one line up, so the long name isn't needed and makes the code harder to scan IMHO.
Sorry for nit-picking about the tests, but I found the original unit tests to be hard to understand |
Marc, I agree that this is a good fix. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the changes!
I'll leave this open a bit to see if any of the other maintainers have concerns.
Merged @alb-i986 would you please update the release notes? |
@kcooney |
…d, not skipped (junit-team#1291) Tests annotated with `@Test(expected = AssumptionViolatedException.class)` which throw AssumptionViolatedException should be marked as passing, not skipped. Fixes junit-team#1290
…d, not skipped (junit-team#1291) Tests annotated with `@Test(expected = AssumptionViolatedException.class)` which throw AssumptionViolatedException should be marked as passing, not skipped. Fixes junit-team#1290
Tests annotated with
@Test(expected = AssumptionViolatedException.class)
which throw AssumptionViolatedException should be marked as passing, not skipped.
Fixes #1290