Should the JUnit message state the condition of success or failure? - java

I can write an assertion message one of two ways. Stating success:
assertEquals( "objects should be identical", expected, actual );
Or stating the condition of being broken:
assertEquals( "objects aren't identical", expected, actual );
Is there a standard for this in JUnit specifically? If not, what are the arguments for each side?
P.S. I've seen articles on the web demonstrating both of these without explanation, so just saying "search Google" is not an answer!
[UPDATE]
Everyone is getting hung up on the fact that I used assertEquals and therefore the message is probably useless. But of course that's just because I wanted to illustrate the question simply.
So imagine instead it's:
assertTrue( ... big long multi-line expression ... );
Where a message is useful.

I rarely even bother with a message, at least for assertEquals. Any sensible test runner will explain that you were using assertEquals and the two things which were meant to be equal. Neither of your messages give more information than that.
I usually find that unit test failures are transient things - I'll rapidly find out what's wrong and fix it. The "finding out what's wrong" usually involves enough detail that a single message isn't going to make much difference. Consider "time saved by having a message" vs "time spent thinking of messages" :)
EDIT: Okay, one case where I might use a message: when there's a compact description in text which isn't obvious from the string representation of the object.
For example: "Expected date to be December 1st" when comparing dates stored as milliseconds.
I wouldn't worry about how you express it exactly though: just make sure it's obvious from the message which way you mean. Either "should be" or "wasn't" is fine - just "December 1st" wouldn't be obvious.

According to the junit API the message is the "the identifying message for the AssertionError" so its not a message describing the condition that should be met but a message describing what's wrong if the condition isn't met. So in your example "objects aren't identical" seems to be more conformant.

Unlike many others I feel that using a message is extremely helpful for many reasons:
The person looking at the logs of a failed test may not be the person who wrote the test. It can take time to read through the code and understand what case the assertion is meant to address. A helpful message will save time.
Even in the event it is the developer of the test who is looking at the logs it may have been days or months since the test was written and, again, a message can save time.
My advice would be to write the message with a statement of the expected behavior. For example:
assertEquals("The method should be invoked 3 times", 3, invocationCount);

I don't think it matters at all - You already know that a failure happened, and therefore it doesn't matter if the message states what should have happened, or what shouldn't happen.
The goal of the message is to help you when it can, not to obtain some completeness.
Obviously, in the case of assertEquals this is less important, but the message is important in the case of general asserts. The message should help you obtain enough context to understand right away what exactly failed.
However, the amount of needed context (and thus the details in the message) should depend on how you get the report. For example, if you get it in Eclipse, you can easily go and interact and see what happened, so the message is less imporrtant. However, if you get your reports emailed to you (e.g., from a continuous build server) then you want the message to provide enough information so that you will have an idea of what is going on before you even go to the corresponding source code.

I would like to answer the question without considering, if a message in generel is useful.
If a test fails, something is wrong. I know this. I want to know why it is broken. That's very easy to find out because I just have to open the test case and the SUT.
Like Jon said, it's very easy to fix it (hopefully ;-) ).
But what about the message? The message is for me an advice, what could be done to turn it into a green test case. So I would appreciate if there's an advice given in the message text, how to fix this problem or where to search for the problem.
Another interesting aspect would be the usage of positive expressions. It's worth a consideration to use positive text messages. In your example, I would use Objects should be identical. But that's a small reason.

I see this question from two perspectives,
First and the most common perspective, which is already being discussed by most of us here: From the perspective of someone who is seeing the logs and trying to fix the error:
I believe that both the messages provides equal information.
Second perspective is that of someone who is reading/ maintaining/ reviewing the code: As we have been talking since ages about the readability and simplicity of code. So, it is also equally important as well.
We have been made to believe that my code should be simple and self explanatory so that no explicit comments are needed and I strongly agree with it.
From this perspective:
These messages make it a lot easier to read and go through the code as they serve the dual purpose of documentation as well as error reporting:
assertEquals( "objects should be identical", expected, actual );
assertTrue( "flag should have been set", flag );
assertNotNull( "object must not be null", object );
These messages are not so reader friendly as they talk about the unexpected condition:
assertEquals( "objects aren't identical", expected, actual );
assertTrue( "flag is not set", flag );
assertNotNull( "object is null", object );

According to specs, the message is to describe the error when it occurs.
And is useful when you build your application in a CI environment, like Jenkins, and using plugins to analyze error results.
http://junit.sourceforge.net/javadoc/org/junit/Assert.html#assertTrue(java.lang.String,%20boolean)
message - the identifying message for the AssertionError (null okay)

Vote me down too (like Jon), but the only time I've ever use a message like this (on assert equals) is when building a single test with a matrix of values and one of the test elements fails: I use the message to indicate which test case failed. Otherwise, the text is totally redundant.

From the javadocs of JUnit:
Asserts that two objects are equal. If
they are not an AssertionFailedError
is thrown with the given message.
According to the API, the message can be whatever you want. I would argue that the two options you have are both the same and both superfluous. The success or failure of the assert already provides all the information you are providing in the message.
It follows for me that you should have either nothing (there is an assert that doesn't take a string on purpose) OR include a message with meaning beyond what is already there.
So I guess this is a reiteration of Jon's answer, but too verbose to be a comment.

Those messages are particularly important when a test fails. And when it fails, you don't only want to know that the objects should be equal, you want to know why they should be equal.
So instead of
assertEquals( "objects should be identical", expected, actual );
use
assertEquals( "Status code should be 403 (forbidden), because a user "
+ "with role customer must not be allowed to access the admin console.",
403, statusCode );
And yes, messages are allowed to be very long, as long as they help the developer to identify the issue fast and fix it the right way.

I don't put a message for the case you cite, unless I'm running a test where I have an array of similar test values that I'm running in a loop and I want to pinpoint exactly which one failed. Then I add a message to tell me which one.

I agree that providing a message is helpful and I always provide one.
To me, the useful thing to include is a clear statement of what went wrong - usually involving the words 'should' or 'should not'.
E.g., "objects are equal" is ambiguous - does it mean the objects are equal and that's why the test failed? Or that objects should be equal but they aren't? But if you say "Objects should be equal" or "Objects should not be equal" it's obvious why the assertion failed.

I particularly like how the Spock test framework encourages tests that read like a story and have come to structure tests under different frameworks similarly. I'm not particularly concerned about the individual error message making a lot of sense, I aim for quickly wrapping my head around the entire test once I open it:
assertEquals("Cloned and persisted items", mockedTiCount, clonedTis.size());
assertTrue("Belong to new transaction", clonedTis.stream().allMatch(ti -> ti.getTransaction().getId().equals(cloned.getId())));
assertNotEquals("Which has a different ID", t.getId(), cloned.getId());
assertEquals("While the originals are left intact", mockedTiCount, transactionItemRepository.findByTransactionId(t.getId()).size());
Opting for many small tests instead of few large ones helps here as well, as does a neatly structured, hopefully reusable, test setup code.

Related

How can I override default failure message of a test in google.Truth?

I am writing a test that assert that a document does not contain a specific String. When the test fails, it prints the 'actual' value in the form
expected not to contain a match for: my_regex
but was : a huge document that is unreadable
The document is very long. It would be preferable to not print it and just print the name of the document. I tried assertWithMessage() but it only adds a message, not replace the default one.
Sorry, we've considered providing this feature occasionally but not pulled the trigger.
For starters, it would often make the assertion statement longer than writing the check yourself. Compare:
assertThat(doc.matches(".*the-regex.*")).isTrue();
assertThat(doc).displayedAs("the doc").containsMatch("the-regex");
(To be fair, there are cases in which it's not so easy to write the check yourself.)
And anyway, much of the goal of Truth is to produce informative failure messages. In cases in which people have good reasons to leave that information out, they can fall back to isTrue() assertions.
(To be fair again, the isTrue() failure produces basically no useful message, whereas you'd like to have "expected not to contain a match for: my_regex." You can of course add it back with assertWithMessage, as you've said, but now your assertion statement is getting long again, and you have to repeat "my_regex" if you want it in the message.)
(Plus, it's nice to be able to always write the assertion in the idiomatic Truth way, rather than switching to non-idiomatic when you want the override the message.)
As noted in all the parentheticals above, though, this feature would have its uses. The "real" concerns are mainly:
API size. Consider also that some people want to omit different parts of the message, so they might desire more than one method.
People may call this method by mistake, accidentally throwing information away.
There's a related feature request here, which is for Truth to truncate values after a certain length. We've actually gotten feedback complaining about cases in which we do truncate, so there's a balance we need to strike here :) But it seems reasonable for us to provide some kind of configurable limit, perhaps based on a system property. I invite you to file an issue (and another for the "override default failure message" thing, if you'd like, even if I suspect we won't do it), though I should warn you that the next quarter or two are probably not going to see a lot of Truth development.
Actually, I forgot: Contrary to what I said in my other answer, there's actually something of a way to do this: Extend StringSubject to override the string representation, and use your custom subject:
public static StringSubject assertThatAbbreviatedString(String actual) {
return assertAbout(abbreviatedStrings()).that(actual);
}
public static Subject.Factory<StringSubject, String> abbreviatedStrings() {
return AbbreviatedStringSubject::new;
}
private static final class AbbreviatedStringSubject extends StringSubject {
AbbreviatedStringSubject(FailureMetadata metadata, String actual) {
super(metadata, actual);
}
#Override
protected String actualCustomStringRepresentation() {
return "<actual value omitted>";
// [Edit: Or maybe you can extract the title from the doc and return that?]
}
}
That enables you to write:
assertThatAbbreviatedString("abcdefghijklmnopqrstuvwyz").containsMatch("foo");
And the output is something like:
expected to contain a match for: foo
but was : <actual value omitted>
If you want to be able to plug in a specific name, rather than <actual value omitted>, the simplest thing is probably to use assertWithMessage(...).about(...).that(...), which you can again wrap in a helper method. (If assertWithMessage is a poor fit for some reason, there's at least one other approach I could get into.)

What is the conventional Java exception for "Too Many Results"

I am writing a generic API that takes parameters and returns results. I expect that if the data is consistent, only one result will be returned for an ID. If I get 1 result, I return it. If I get 0 results, I can throw "MissingResourceException" or "NoSuchElementException" etc. However, if I get multiple results, what should I throw? I have looked at the obvious places (Oracle/Java API documentation, Googling it, and of course, StackOverflow), but didn't find one.
Please note that I may not control the data, so the "the data should have been good/police your data" advice, while valid, will not help me.
Any help is appreciated.
Joshua Bloch's Effective Java says in Item 60 (Favor to use standard exceptions):
Also, feel free to subclass an existing exception if you want to add a bit more failure-capture information (Item 63).
So, I vote for one of IllegalStateException or YourOwnException (with additional failure-related info).

Unit testing with assertTrue vs others

I work in a TDD environment and I use assertTrue a lot whereas there are many other methods, such as assert equals etc. I have a class that I have more than 40 test cases and they are all assertTrue. is this acceptable?
I wanted to ask as a style, is this proper?
any suggestions?
if u think this question is inappropriate let me know i ll delete it.
EDIT:
assertTrue(targetSpecifiers.size() == 2);
assertTrue(targetSpecifiers.get(0).getPlacementId().compareTo(new BigInteger("1")) ==0);
assertTrue(targetSpecifiers.get(1).getPlacementId().compareTo(new BigInteger("2")) ==0);
The main benefits of using other assertions is that they better communicate intent and are likely to give a more meaningful default message in the event of failure.
e.g.
if you write assertEquals(2, x) if x is actually 1 then the failure message will be:
java.lang.AssertionError: expected:<2> but was:<1>
which is more helpful than if you write assertTrue(x == 2) where all you would see is the AssertionError and the stack trace.
This is even more important when you are using TDD because you when you write a failing test first you want to be confident that the test is failing for the reason you are expecting it to and that there is not some accidental behaviour going on.
Where appropriate you should use the correct assertXXX methods as they improve the reporting of failures. For e.g. if you are testing for the equality of let us say 2 string "abc" (expected) and "abxy" (actual), then the use of assertEquals
assertEquals("abc", "abxy")
will provide a better output that is easier to reason about than using the assertTrue like below
assertTrue("abc".equals("abxy"))
NOTE: Also pay attention to where you are specifying the actual and expected arguments. I see lot of developers not following the convention (junit's convention) that the expected should be the first param to the assertXXX methods. Improper usage also leads to lot of confusion
My guess is that you've got things like:
assertTrue(expectedValue.equals(actualValue));
That will still test the right thing - but when there's a failure, all it can tell you was that the assertion failed. If you used this instead:
assertEquals(expectedValue, actualValue);
... then the failure will say "Expected: 5; Was: 10" or something similar, which makes it considerably easier to work out what's going on.
Unless you're asserting the result of a method returning boolean or something like that, I find assertTrue to be pretty rarely useful.
If you could give examples of your assertions, we may be able to translate them into more idiomatic ones.
These assertions are perfectly valid, but other assertions are easier to read and deliver better failure messages.
I recommend looking at Hamcrest- this provides the most readable form of assertions and failure messages. Your example of
assertTrue(targetSpecifiers.size() == 2);
assertTrue(targetSpecifiers.get(0).getPlacementId().compareTo(new BigInteger("1")) ==0);
assertTrue(targetSpecifiers.get(1).getPlacementId().compareTo(new BigInteger("2")) ==0);
could be rewritten as
assertThat(targetSpecifiers, hasSize(2));
assertThat(targetSpecifiers.get(0).getPlacementId(), equalTo(BigInteger.valueOf(1));
assertThat(targetSpecifiers.get(1).getPlacementId(), equalTo(BigInteger.valueOf(1));
or even more succinctly as
assertThat(targetSpecifiers, contains(
hasProperty("placementId", equalTo(BigInteger.valueOf(1)),
hasProperty("placementId", equalTo(BigInteger.valueOf(2))
);
contains verifies completeness and order, so this covers all three assertions.

When to use an assertion and when to use an exception

Most of the time I will use an exception to check for a condition in my code, I wonder when it is an appropriate time to use an assertion?
For instance,
Group group=null;
try{
group = service().getGroup("abc");
}catch(Exception e){
//I dont log error because I know whenever error occur mean group not found
}
if(group !=null)
{
//do something
}
Could you indicate how an assertion fits in here? Should I use an assertion?
It seems like I never use assertions in production code and only see assertions in unit tests. I do know that in most cases, I can just use exception to do the checking like above, but I want to know appropriate way to do it "professionally".
Out of my mind (list may be incomplete, and is too long to fit in a comment), I would say:
use exceptions when checking parameters passed to public or protected methods and constructors
use exceptions when interacting with the user or when you expect the client code to recover from an exceptional situation
use exceptions to address problems that might occur
use assertions when checking pre-conditions, post-conditions and invariants of private/internal code
use assertions to provide feedback to yourself or your developer team
use assertions when checking for things that are very unlikely to happen otherwise it means that there is a serious flaw in your application
use assertions to state things that you (supposedly) know to be true
In other words, exceptions address the robustness of your application while assertions address its correctness.
Assertions are designed to be cheap to write, you can use them almost everywhere and I'm using this rule of thumb: the more an assertion statement looks stupid, the more valuable it is and the more information it embeds. When debugging a program that does not behave the right way, you will surely check the more obvious failure possibilities based on your experience. Then you will check for problems that just cannot happen: this is exactly when assertions help a lot and save time.
Assertions should be used to check something that should never happen, while an exception should be used to check something that might happen.
For example, a function might divide by 0, so an exception should be used, but an assertion could be used to check that the harddrive suddenly disappears.
An assertion would stop the program from running, but an exception would let the program continue running.
Note that if(group != null) is not an assertion, that is just a conditional.
Remember assertions can be disabled at runtime using parameters, and are disabled by default, so don't count on them except for debugging purposes.
Also you should read the Oracle article about assert to see more cases where to use - or not to use - assert.
As a general rule:
Use assertions for internal consistency checks where it doesn't matter at all if someone turns them off. (Note that the java command turns off all assertions by default.)
Use regular tests for any kind of checks what shouldn't be turned off. This includes defensive checks that guard against potential damage cause by bugs, and any validation data / requests / whatever provided by users or external services.
The following code from your question is bad style and potentially buggy
try {
group = service().getGroup("abc");
} catch (Exception e) {
//i dont log error because i know whenever error occur mean group not found
}
The problem is that you DON'T know that an exception means that the group was not found. It is also possible that the service() call threw an exception, or that it returned null which then caused a NullPointerException.
When you catch an "expected" exception, you should catch only the exception that you are expecting. By catching java.lang.Exception (and especially by not logging it), you are making it harder to diagnose / debug the problem, and potentially allowing the app to do more damage.
Well, back at Microsoft, the recommendation was to throw Exceptions in all APIs you make available publicly and use Asserts in all sorts of assumptions you make about code that's internal. It's a bit of a loose definition but I guess it's up to each developer to draw the line.
Regarding the use of Exceptions, as the name says, their usage should be exceptional so for the code you present above, the getGroup call should return null if no service exists. Exception should only occur if a network link goes down or something like that.
I guess the conclusion is that it's a bit left down to the development team for each application to define the boundaries of assert vs exceptions.
According to this doc http://docs.oracle.com/javase/6/docs/technotes/guides/language/assert.html#design-faq-general, "The assert statement is appropriate for nonpublic precondition, postcondition and class invariant checking. Public precondition checking should still be performed by checks inside methods that result in particular, documented exceptions, such as IllegalArgumentException and IllegalStateException."
If you want to know more about precondition, postcondition and class invariant, check this doc: http://docs.oracle.com/javase/6/docs/technotes/guides/language/assert.html#usage-conditions. It also contains with examples of assertions usage.
Testing for null will only catch nulls causing problems, whereas a try/catch as you have it will catch any error.
Broadly, try/catch is safer, but slightly slower, and you have to be careful that you catch all the kinds of error that may occur. So I would say use try/catch - one day the getGroup code may change, and you just might need that bigger net.
You can use this simple difference in mind while their usage. Exceptions will be used for checking expected and unexpected errors called checked and unchecked error while assertion is used mainly for debugging purposes at the run time to see whether the assumptions are validated or not.
Unfortunately asserts can be disabled. When in production you need all the help you can get when tracking down something unforeseen, so asserts disqualify themselves.
I confess I'm a little confused by your question. When an assertion condition is not met, an exception is thrown. Confusingly this is called AssertionError. Note that it's unchecked, like (for example) IllegalArgumentException which is thrown in very similar circumstances.
So using assertions in Java
is a more concise means of writing a condition/throw block
permits you to turn these checks on/off via JVM parameters. Normally I would leave these checks on all the time, unless they impact runtime performance or have a similar penalty.
See section 6.1.2 (Assertions vs. other error code) of Sun's documentation at the following link.
http://www.oracle.com/technetwork/articles/javase/javapch06.pdf
This document gives the best advice I've seen on when to use assertions. Quoting from the document:
"A good rule of thumb is that you should use an assertion for exceptional cases that you would like to forget about. An assertion is the quickest way to deal with, and forget, a condition or state that you don’t expect to have to deal with."
I’m not experienced with Java asserts but I think the answer here naturally follows from what Java asserts are:
Code that is only run if enabled
Disabled by default
Thus we can surmise that assertions should never be used to implement application logic: it should only be used as optional (because of the on/off feature) sanity checks/explicit assumptions. The correctness of your app (modulo bugs!) cannot depend on a runtime flag which is turned off by default.
So only use assertions to check internal assumptions (your own code only, not things that are out of your control like user input). But on the other hand you might sometimes want to use exceptions to check your assumptions; if you want to always check a certain assumption then you don’t need the on/off feature that assertions provide.
For the task of checking assumptions, it seems that assertions excel when:
The check might be costly so you want the option of disabling it
Using if-or-throw would be too much “noise” but you can bear the cost of one little assert <expr>
You want to leave a little comment which merely states something like:
// NOTE we KNOW that `x` is not null!
x.doWork();
Then the Java folks say that you should always replace that line with:
assert x != null;
x.doWork();
Or (in my opinion) if you prefer:
if (x == null) {
throw new IllegalStateException("shouldn’t be null");
}
x.doWork();
Things that follow from these principles
I think we can immediately expand on related principles (sibling answer) by using this “optional” principle (my gloss in cursive):
use exceptions when checking parameters passed to public or protected methods and constructors
Because you are checking things outside your code: code coming into your module
use exceptions when interacting with the user or when you expect the client code to recover from an exceptional situation
Because the input is from the user and has nothing to do with your code. Also assertions are not really something you are supposed to recover from.(†1)
use exceptions to address problems that might occur
I.e. errors that happen as a matter of course: not bugs in your code
use assertions when checking pre-conditions, post-conditions and invariants of private/internal code
Because it’s your own code: problems inside your own code are self-caused
use assertions to provide feedback to yourself or your developer team
Bugs are for developers to deal with
use assertions when checking for things that are very unlikely to happen otherwise it means that there is a serious flaw in your application
Key word “serious flaw in your application”
use assertions to state things that you (supposedly) know to be true
Checking assumptions
Notes
I think this is a general opinion. See also (my bold):
Why is AssertionError a subclass of Error rather than RuntimeException?
This issue was controversial. The expert group discussed it at length, and came to the conclusion that Error was more appropriate to discourage programmers from attempting to recover from assertion failures.

Some (anti-)patterns on using assert (Java, and others)

Finally, I have a question to ask on Stack Overflow! :-)
The main target is for Java but I believe it is mostly language agnostic: if you don't have native assert, you can always simulate it.
I work for a company selling a suite of softwares written in Java. The code is old, dating back to Java 1.3 at least, and at some places, it shows... That's a large code base, some 2 millions of lines, so we can't refactor it all at once.
Recently, we switched the latest versions from Java 1.4 syntax and JVM to Java 1.6, making conservative use of some new features like assert (we used to use a DEBUG.ASSERT macro -- I know assert has been introduced in 1.4 but we didn't used it before), generics (only typed collections), foreach loop, enums, etc.
I am still a bit green about the use of assert, although I have read a couple of articles on the topic. Yet, some usages I see leave me perplex, hurting my common sense... ^_^ So I thought I should ask some questions, to see if I am right to want to correct stuff, or if it goes against common practices. I am wordy, so I bolded the questions, for those liking to skim stuff.
For reference, I have searched assert java in SO and found some interesting threads, but apparently no exact duplicate.
How to avoid “!= null” statements in java? and How much null checking is enough? are quite relevant, because lot of asserts we have just check if variable is null. At some places in our code, there are usages of the null object (eg. returning new String[0]) but not always. We have to live with that, at least for maintenance of legacy code.
Some good answers also in Java assertions underused.
Oh, and SO indicates with reason that When should I use Debug.Assert()? question is related too (nice feature to reduce duplicates!).
First, main issue, which triggered my question today:
SubDocument aSubDoc = documents.GetAt( i );
assert( aSubDoc != null );
if ( aSubDoc.GetType() == GIS_DOC )
{
continue;
}
assert( aSubDoc.GetDoc() != null );
ContentsInfo ci = (ContentsInfo) aSubDoc.GetDoc();
(Yes, we use MS' C/C++ style/code conventions. And I even like it (coming from same background)! So sue us.)
First, the assert() form comes from conversion of DEBUG.ASSERT() calls. I dislike the extra parentheses, since assert is a language construct, not (no longer, here) a function call. I dislike also return (foo); :-)
Next, the asserts don't test here for invariants, they are rather used as guards against bad values. But as I understand it, they are useless here: the assert will throw an exception, not even documented with a companion string, and only if assertions are enabled. So if we have -ea option, we just have an assertion thrown instead of the regular NullPointerException one. That doesn't look like a paramount advantage, since we catch unchecked exceptions at highest level anyway.
Am I right supposing we can get rid of them and live with that (ie. let Java raise such unckecked exception)? (or, of course, test against null value if likely, which is done in other places).
Side note: should I have to assert in the above snippet, I would do that against ci value, not against the getter: even if most getters are optimized/inlined, we cannot be sure, so we should avoid calling it twice.
Somebody told, in the last referenced thread, that public methods should use tests against values of parameters (usage of the public API) and private methods should rely on asserts instead. Good advice.
Now, both kinds of methods must check another source of data: external input. Ie. data coming from user, from a database, from some file or from the network, for example.
In our code, I see asserts against these values. I always change these to real test, so they act even with assertions disabled: these are not invariants and must be properly handled.
I see only one possible exception, where input is supposed constant, for example a database table filled with constants used in relations: program would break if this table is changed but corresponding code wasn't updated.
Do you see other exceptions?
Another relatively frequent use I see, which seems OK: in the default of a switch, or at the end of a series of else if testing all possible values (these cases date back before our use of enums!), there is often an assert false : "Unexpected value for stuff: " + stuff;
Looks legitimate for me (these cases shouldn't happen in production), what do you think? (beyond the "no switch, use OO" advices which are irrelevant here).
And finally, are there any other useful use cases or annoying gotchas I missed here? (probably!)
The number one rule is to avoid side-effects in assertions. In other words, the code should behave identically with assertions turned off as it does when assertions are turned on and not failing (obviously assertions that fail are going to alter the behaviour because they will raise an error).
The number two rule is not to use assertions for essential checks. They can be turned off (or, more correctly, not turned on). For parameter-checking of non-private methods use IllegalArgumentException.
Assertions are executable assumptions. I use assertions to state my beliefs about the current state of the program. For example, things like "I assume that n is positive here", or "I assume that the list has precisely one element here".
I use assert, not only for parameter validation, but also used for verifying Threads.
Every time I do swing, I write assert in almost every method to mark "I should only be execute in worker thread/AWTThread". (I think Sun should do it for us.) Because of the Swing threading model, it MAY NOT fail (and randomly fail) if you access swing api from non-UI thread. It is quite difficult to find out all these problem without assert.
Another example I can imagination is to check JAR enclosed resource. You can have english exception rather then NPE.
EDIT:
Another example; object lock checking. If I know that I am going to use nested synchronized block, or when I am going to fix a deadlock, I use Thread.holdLock(Object) to ensure I won't get the locks in reverse order.
EDIT(2): If you are quite sure some code block should never be reach, you may write
throw new AssertionError("You dead");
rather then
assert false:"I am lucky";
For example, if you override "equals(Object)" on a mutable object, override hashCode() with AssertionError if you believe it will never be the key. This practice is suggested in some books. I won't hurt performance (as it should never reach).
you have touched on many of the reasons why i think asserts should be avoided in general. unless you are working with a codebase where assert usage has very strict guidelines, you very quickly get into a situation where you cannot ever turn the assertions off, in which case you might as well just be using normal logic tests.
so, my recommendation is skip the assertions. don't stick in extra null-pointer checks where the language will do it for you. however, if the pointer may not be dereferenced for a while, up-front null checking is a good idea. also, always use real exceptions for cases which should "never" happen (the final if branch or the default switch case), don't use "assert false". if you use an assertion, there's a chance someone could turn it off, and if the situation actually happens, things will get really confused.
I recommend checking parameters in public (API) methods and throwing IllegalArgumentException if the params aren't valid. No asserts here as an API user requires to get a proper error (message).
Asserts should be used in non-public methods to check post-conditions and possibly pre-conditions. For example:
List returnListOfSize(int size) {
// complex list creation
assert list.size == size;
}
Often using a clever error handling strategy asserts can be circumvented.

Categories