Debugging with the assert statement - java

I'm assuming that the reason the assert statement throws an AssertionError to stop your program is because an assumption about your code is wrong. The problem is, how am I supposed to debug my code by using debugging tools when the assert statement kills my java process?
EDIT: My question is different because the answer to the supposedly duplicate question doesn't answer mine.

EDIT:
If you look for a way to throw an exception and not throw an exception at the same time, there is no solution for this.
In modern IDEs you can, during debug:
tell the IDE to block on any AssertionError without setting any breakpoint
change the code of a method during a test when blocked, such as commenting out an assert
tell the IDE to resume running a method again How to step back in Eclipse debugger?
Also assert can be disabled for the purpose of debugging. That's one reason to use an assert instead of an if-block.
See:
How do I disable Java assertions for a junit test in the code

Related

Do JUnit Assertions ever get disabled?

Java assert statements are selectively enabled/disabled, based on config flags (eg, -ea). I read online that with JUnit assertions (eg, Assert.assertTrue), you don't need to worry about managing the assertion-config yourself. What exactly does this mean? Either:
1) JUnit assertions (mixed together with Prod code) are never disabled. They behave just like Validate statements, and always get run.
or
2) The JUnit test framework automatically enables all JUnit assertions when running JUnit tests. Whenever the application/code is run outside of JUnit, the JUnit assert methods do nothing at all.
or
3) JUnit assertions are always enabled/disabled by default, but there is a custom config/flag that can be used to disable/enable them
Which of the above is true?
--
Edit: Changed the wording a little bit to clear up any ambiguity.
This question seems to have opened up a can of worms with regards to coding-guidelines on when to use/not to use asserts. I'll post here the answer to my immediate question regarding whether JUnit Assert statements get disabled. Further down, you will find a discussion on the philosophical aspects of using assertions.
Summary: JUnit assert statements are never disabled, even when running in production with the disable-assertions flag.
Experiment: Created a small main function which throws an error in the very first line. The error was implemented in various different ways. I then ran the application from the command-line like so: mvn clean package; java $JAVA_OPTS -cp ....
Induced error by throwing IllegalArgument exception. Application failed with IllegalArgument exception.
Induced error by adding assert false and ran with assertions enabled (-ea). Application failed.
Induced error by adding assert false and ran with assertions disabled (-da). Application succeeded.
Induced error by adding Assert.assertTrue(false); and ran with assertions enabled (-ea). Application failed with AssertionError.
Induced error by adding Assert.assertTrue(false); and ran with assertions disabled (-da). Application failed with AssertionError.
Did a quick google search to see if there's any way to disable JUnit.Asserts. Didn't find anything. If anyone knows of a way to do so, please let me know, because I believe it's an important distinction.
Conclusion: assert keywords can be enabled/disabled using the -ea commandline flag. JUnit.Asserts cannot be enabled/disabled. If you want to add assertions to your production code, then this becomes a very important distinction. If you want the ability to disable them, use the assert keyword. If you want something that you know will always be enabled, then consider JUnit.Assert, or some other similar framework that throws AssertionErrors.
Regarding the philosophy behind assert usage:
It's good to add assertions of some form to your production code. See: https://docs.oracle.com/javase/8/docs/technotes/guides/language/assert.html#usage
Putting Assertions Into Your Code. There are many situations where it is good to use assertions, including:
Internal Invariants
Control-Flow Invariants
Preconditions, Postconditions, and Class Invariants
JUnit Asserts cannot be treated as a universal replacement for java assert keywords. The latter gives you the power to disable them, and the former doesn't. Hence, there is a design choice to be made in choosing which of the 2 to use.
Exceptions and Assertions serve very different purposes and should not be used interchangeably. The following discussion clarifies this further: When to use an assertion and when to use an exception
Related StackOverflow discussions:
assert vs. JUnit Assertions
I think you're confused between JUnit assertions and Java's built in assertions.
JUnit assertions are methods that throw an AssertionError exception and should only be used in your test code. JUnit code should not be used in production, only when running your JUnit tests during/between builds. The method names are named like assertEquals( expected, actual) and assertNull(Object) etc. You can't disable these assertions since they are method calls. Also your test code would be pretty useless if you could disable all the JUnit assert methodcalls.
Java's built in assertion is a boolean expression preceded by the assert keyword. If the expression returns false, then it too throws an AssertionError. This kind of assertion can be disabled in production to help speed up your code or turned on to help track down bugs. You can read more about the built in Java assert in the Java Programming Guide

Why would a program silently fail?

I have a legacy java app written up by a previous developer. A bug has recently been found in it, and I've been given the task of fixing it.
Part of the problem is that there were never any error messages reporting from it.
By putting in a lot of logging messages, I finally narrowed it down to a specific line in the code - it's trying to run a method on a null object.
This is something that SHOULD have thrown an error into the log. Yet it hasn't. And even fixing this one, there's a lot of this problem in the code - assuming something will have a value when it doesn't. Every time I put in a data-verification for one, it fails somewhere shortly down the line for a very similar reason, and then I have to go through the hassle of putting in logging commands every other line again to finally narrow it down.
Why would a java program be silently failing instead of throwing errors? I can't seem to find any sort of setting suggesting that this is on purpose, but I'm really not even sure where to look for such a thing.

Skipping Java compilation errors [duplicate]

This question already has answers here:
Ignoring Compilation errors - Java
(7 answers)
Closed 9 years ago.
Is it possible to Skip Java compilation errors?
So the program may continue even if it encountered errors.
So it kinda does the max effort to continue working (until everything explodes)
No. If you get compilation errors, it means your program is not valid Java. What would it even mean for it to continue? It's not running yet.
If you have compilation errors, the program cannot be compiled to runtime code. That means practically that the program cannot be run.
So, the answer is NO, it cannot.
There is another type of errors - runtime errors. Those happens as a result of bad logic in the code (i.e. trying to modify a null object). Compiler cannot discover those as those are very subtle, depending-on-data (and most of the time depending on user input) errors. You can skip over those with the usage of a try-catch block. If you want to read more, please refer to this article:
http://docs.oracle.com/javase/tutorial/essential/exceptions/try.html
Yes, you can do that using the eclipse compiler. It will replace the method which contains the error with a method that will directly throw an Exception when it is invoked.
This will allow you to run the rest of the program. I would not recommend it though, as you'll get an inconsistent program. So use at your own risk.
Still it might come in handy, for example if you run unittests. This allows you to run tests, even if parts of your program are definitely not working.
No its just not possible. Compilation of java code gives you the byte code which is then run on JVM. If the compilation will fail then Java compiler will not be able to generate valid byte code. Thats the reason that there is no point in generating the incorrect byte code which can't be run by JVM as such.
if we break that thing then sooner or later no one will be develop the code. :)
Well ... kind of.
Some IDEs allow you to run code that has compilation errors in it. For example, Eclipse.
When you then try to execute (say) a method with a compilation error it, you get an exception whose message says something to the effect that there is a compilation error in this code. In fact, the Eclipse compiler has compiled the method to a stub method that will just throw an exception.
Note that this behaviour is NOT endorsed by the JLS. And personally, I think it is a bad idea to use this IDE feature.
IMO, a better approach is to comment out the parts of the code that are giving the compilation errors ... or just fix them.
Your expecting to avoid compilation errors, what do you thing ?if you avoid compilation errors will you get .class file? without .class file you cant imagine to run you code.
compilation errors arise when your code contain syntactical eroor. without proper syntax you cant do anything.
For more about compilation error see THIS

Popping debugger with code in Java

I used abort() In C to make my program crash. And debugger will trap this.
Maybe equivalent in Java should be exception. But Java also has very strict exception chaining policy, so using of exception for debugging purpose doesn't seem to be a good idea.
What should I use for this in Java? Intentional program crash for debugging purpose which can be trapped by debugger. (I am using Eclipse)
Update
It would be very nice if the code can be optionally opt-out on release build.
In Eclipse you can set debug points, and run in debug mode.
That said, there is a difference between a CheckedException (which must be caught by the calling function or passed up the chain) and an UncheckedException (which is closer to what you want). Throw the latter if you want to force a crash.
However, this is generally a bad way to program. You'll find better results using alternative means to catch the errors you want.
You can use assert(false). Assuming you're using Eclipse for the debugger, you can set Eclipse to break on specific exceptions (in this case, AssertionError). Make sure you enable assertions, otherwise it won't do anything.
Since you have to explicitly tell the JVM to enable assertions, I think this would count as "code [that] can be optionally opt-out on release build."
I do not know how to handle it in Eclipse. However, under JDB, this can be done by catching the Exceptions. Eclipse should have such an interface.
Using command line like this
"catch java.io.FileNotFoundException"
For details, please refer to here

TestNG - generating errors by unexpected exceptions

I would like to know, is there any way to set up TestNG to handle unexpected exceptions like errors and not like failures?
I tried to throw RuntimeException in my test and it was considered as failure, not like an error.
TestNG documentation talks only about success and failure states -
http://testng.org/doc/documentation-main.html#success-failure.
I would like to have TestNG behaviour similar to JUnit in first question on address
http://www.querycat.com/question/d1c9a200f18e6829cb06dda8eda8ad61
Thanks for your help.
Edit: Ignore what I had before. Unfortunately, I'm fairly certain the answer to your question is no, TestNG does not have this feature. The entirety of the TestNG documentation is here, so if a feature isn't listed on that page it probably doesn't exist. Remember that although TestNG is inspired by JUnit, it should not be considered a super-set of JUnit's features. The only thing I can think of if you want your test suite to catastrophically fail on an exception is to make it call System.exit(1).
You are using the wrong exception.
JUnit is distinguishing between success, failure (AssertionException thrown by assertXXX) and error (all other not expected exception).
If you know that a method will throw an exception you can catch it with #Test(expected=MyExpectedException).

Categories

Resources