Tuesday, May 20, 2008

Don't Forget to enable Java assert

I had been happily putting assert's in my Java tests and assuming they were working. Until there was one that really should have been failing. Hmmm... I added "assert false" and it still succeeded. What's going on?!

Then I remembered reading somewhere that assert checking is disabled by default. Doh!

You enable this via a command line argument to Java. In Eclipse you can do this in the Run item settings or you can make it the default in Window > Preferences > Java > Installed JREs > Edit > Default VM Arguments: -ea

Of course, once I enabled assert checking I found that a number of my tests were failing (had been all along). Thankfully they were easy to fix!

For now, I've enabled assert checking. But perhaps I shouldn't be using assert in my tests.

For the majority of my assert's I prefer if they are always checked. The exception would be particularly slow assert's you might want to disable in production.

In my C++ Suneido code I ended up using my own "verify" instead of assert that is never disabled. Because it is never disabled I can use it with expressions that are actual part of the functionality. This avoids temporary variables whose sole purpose is to be checked by an assert. e.g.


instead of:

bool result = myfunc();

I may end up doing the same thing in Java - I'll see how it goes.


Anonymous said...

jSuneido is a brilliant idea. Are you coding against JDK 1.5?

The issue with blocks you may be able to solve with inner classes.

Do you plan to put the server stuff in EE container so it will run on a Java server?

I am excited to see the results!!

andrew said...

I'm using JDK 6 for development but everything should still work with 1.5

I thought of inner classes too, but then I discovered that they are actually implemented by the Java compiler by "translating" to regular Java. The JVM itself does not have any facilities specifically for inner classes. But a similar technique could be used for blocks.

I had not really thought about EE stuff. Maybe later.

Andy C said...

Thanks mate, you just saved me from going nuts. It's a bit weird when eclipse steps through assert(false);

Anonymous said...

Thanks lot dude. you saved lot of my time..
i didn't know that first we need to enable assert.
With enabling i was writing a so many programs and testing it...

Byron said...

Thanks! you saved me some time. It's neat that asserts are toggled at runtime, and not at compile time.

Krish Perumal said...

Thx a lot for telling me this.....i was wondering the same about 'assert false' statements....

martinhport-g said...

Hi I was thinking about this today....do you think it would be a good idea to write tests for the asserts to check that the exception gets thrown.

There are levels with this.

1. Write a test that just makes and assertion purely to check that the -ea flag has been set. Then this will fail if you forget.

2. You could write simple unit test against each assert, expecting AssertionFailedError.

What do you think?

It might be a good idea to place these tests in their own package and thus be able to disable them.

andrew said...

Yes, that's what I ended up doing, although only after getting caught by this a second time. I should have thought of it the first time.

Burnt by Java Assert Again

Anonymous said...

Hi! Your post is very helpful! Thank you!

Tommy said...

If you are using Spring Test library or Junit you can use the Assertion utility classes eg. Spring has an Assert class with many test methods on eg. Assert.notNull(myTestObject);.

You dont need to enable assertions when using these.


Anonymous said...

Note that there's a good reason why assert is a keyword and can be enabled / disabled - when disabled, the assert simply won't be executed, skipped, etc. If you replace that with an assert() function, that method will always be executed, including the expression inside it.

So the cost of calling

assert something == bigfunction() : "message";

is zero, whilst

assert(something == bigfunction(), "message");

is the cost of executing the comparison, the bigfunction(), calling the method, and the cost of the method checking whether assertions should be handled.

andrew said...

I'm aware of that.

What I would question is whether it would make more sense for a development environment (e.g. Eclipse) to have asserts enabled by default.

Even with a function and a runtime flag to enable/disable, the JVM optimization will often remove the code if it's disabled.

Dobes said...

I think assertions are quite nice to keep around even after development. It's not until you get the end-users on the system that you really start to find the real weird bugs and without those assertions it is that much harder to figure out what is going on.

They say "optimize late" and this is definitely a case where optimization could be more harmful than helpful.

If you have such a "hot" piece of code that you can't afford to run the assertions, sure - optimize away those assertions. But for the 99% of code that runs once in a lifetime and is mostly I/O bound anyway, forget about it.