Prev: www.promptc.com (free shipping,only $16-69) for NFL jersey--Paypal
Next: Up to date SOAP implementation
From: Rhino on 18 May 2010 16:21 I'm having a bit of a conceptual struggle right now with the right way to handle exceptions in JUnit tests. Since I always explain concepts better in terms of examples, let me describe a scenario to you which should illustrate the situation clearly. I have a method called getRGBColor() whose input parameter is a six letter String that is supposed to contain exactly six hex digits. Those hex digits are the String representation of an RGB Color. Therefore, "FFFFFF" represents White. I have no trouble writing a JUnit test that passes in "FFFFFF" as an input value and then verifies that the Color returned by the method is White i.e. Color(255,255,255) so I can test that aspect of the code without trouble. However, the method throws IllegalArgumentException if the input String is not precisely 6 characters long or if any of the characters are not hex digits. I can easily invoke the method with a value that will cause the exception to be thrown and I can catch it with a standard try/catch block. I can also put code in my catch block to make sure that JUnit reports the error from the Exception in the method being tested. I end up with this test which correctly reports the IllegalArgumentException within the JUnit window: try { Color actualRGBColor = colorConversionUtils.getRGBColor("FFFFFFA"); Color expectedRGBColor = new Color(255, 255, 255); assertTrue("Actual color, " + actualRGBColor + ", does not equal expected color, " + expectedRGBColor, actualRGBColor.equals(expectedRGBColor)); } catch (IllegalArgumentException ia_excp) { assertionFailedError = new AssertionFailedError(ia_excp.getMessage()); assertionFailedError.initCause(ia_excp); throw assertionFailedError; } So far, so good. Now, here's where my problem comes in. When I execute this test, the method in which it is situated inevitably results in a black X decoration on the test result in the JUnit window of Eclipse. (I'm using JUnit3 for now.) I know that's reasonable given that it is correctly reporting an exception thrown by a method that is under test. However, I had the distinct impression in a conversion some months ago, that a properly written set of JUnit tests should always give me a green checkmark decoration on every test. And that makes a lot of sense to me too. Ideally, given that unit tests may be executed hundreds of times and each test class may have dozens of test methods in it, the last thing anyone wants to do is have to inspect each test method individually and know exactly which ones should have had green checkmarks, black X's and red X's. It's simply far easier to make sure that all of the tests had green checkmarks and only dive into them if some test _doesn't_ have a green checkmark. I don't see how I can reconcile these two ideas. If I test for thrown exceptions, I will inevitably get some black X's. (Unless there is some way to negate the exception test so that it only gives the black X if the exception FAILS to be thrown???) But if I get black X's, how am I to know quickly which of the test methods SHOULD be getting black X's and which ones should be getting green checkmarks? I don't much like the idea of trying to document all that and I certainly can't memorize it all.... -- Rhino
From: Daniel Pitts on 18 May 2010 16:38 On 5/18/2010 1:21 PM, Rhino wrote: > I'm having a bit of a conceptual struggle right now with the right way to > handle exceptions in JUnit tests. Since I always explain concepts better in > terms of examples, let me describe a scenario to you which should > illustrate the situation clearly. > > I have a method called getRGBColor() whose input parameter is a six letter > String that is supposed to contain exactly six hex digits. Those hex digits > are the String representation of an RGB Color. Therefore, "FFFFFF" > represents White. > > I have no trouble writing a JUnit test that passes in "FFFFFF" as an input > value and then verifies that the Color returned by the method is White i.e. > Color(255,255,255) so I can test that aspect of the code without trouble. > > However, the method throws IllegalArgumentException if the input String is > not precisely 6 characters long or if any of the characters are not hex > digits. > > I can easily invoke the method with a value that will cause the exception > to be thrown and I can catch it with a standard try/catch block. I can also > put code in my catch block to make sure that JUnit reports the error from > the Exception in the method being tested. I end up with this test which > correctly reports the IllegalArgumentException within the JUnit window: > > try { > Color actualRGBColor = colorConversionUtils.getRGBColor("FFFFFFA"); > Color expectedRGBColor = new Color(255, 255, 255); > assertTrue("Actual color, " + actualRGBColor + ", does not equal expected > color, " + expectedRGBColor, actualRGBColor.equals(expectedRGBColor)); > > } > catch (IllegalArgumentException ia_excp) { > assertionFailedError = new AssertionFailedError(ia_excp.getMessage()); > assertionFailedError.initCause(ia_excp); > throw assertionFailedError; > } > > > So far, so good. Now, here's where my problem comes in. When I execute this > test, the method in which it is situated inevitably results in a black X > decoration on the test result in the JUnit window of Eclipse. (I'm using > JUnit3 for now.) I know that's reasonable given that it is correctly > reporting an exception thrown by a method that is under test. > > However, I had the distinct impression in a conversion some months ago, > that a properly written set of JUnit tests should always give me a green > checkmark decoration on every test. And that makes a lot of sense to me > too. Ideally, given that unit tests may be executed hundreds of times and > each test class may have dozens of test methods in it, the last thing > anyone wants to do is have to inspect each test method individually and > know exactly which ones should have had green checkmarks, black X's and red > X's. It's simply far easier to make sure that all of the tests had green > checkmarks and only dive into them if some test _doesn't_ have a green > checkmark. > > I don't see how I can reconcile these two ideas. If I test for thrown > exceptions, I will inevitably get some black X's. (Unless there is some way > to negate the exception test so that it only gives the black X if the > exception FAILS to be thrown???) But if I get black X's, how am I to know > quickly which of the test methods SHOULD be getting black X's and which > ones should be getting green checkmarks? I don't much like the idea of > trying to document all that and I certainly can't memorize it all.... > > public void testParseException() { try { myObj.getRGB("Bad value!"); fail("Bad value did not cause exception!"); } catch(IllegalArgumentException e) { // Success! } } public void testGoodParse() { assertEqual(white, myObj.getRGB("FFFFFF")); } -- Daniel Pitts' Tech Blog: <http://virtualinfinity.net/wordpress/>
From: Tom Anderson on 18 May 2010 17:03 On Tue, 18 May 2010, Rhino wrote: > I can easily invoke the method with a value that will cause the > exception to be thrown and I can catch it with a standard try/catch > block. I can also put code in my catch block to make sure that JUnit > reports the error from the Exception in the method being tested. I end > up with this test which correctly reports the IllegalArgumentException > within the JUnit window: > > try { > Color actualRGBColor = colorConversionUtils.getRGBColor("FFFFFFA"); > Color expectedRGBColor = new Color(255, 255, 255); > assertTrue("Actual color, " + actualRGBColor + ", does not equal expected > color, " + expectedRGBColor, actualRGBColor.equals(expectedRGBColor)); > > } > catch (IllegalArgumentException ia_excp) { > assertionFailedError = new AssertionFailedError(ia_excp.getMessage()); > assertionFailedError.initCause(ia_excp); > throw assertionFailedError; > } > > So far, so good. No, not good, this is completely wrong. You want this: @Test(expected=IllegalArgumentException.class) public void getRGBColorThrowsExceptionOnBadInput() { colorConversionUtils.getRGBColor("FFFFFFA"); } > However, I had the distinct impression in a conversion some months ago, > that a properly written set of JUnit tests should always give me a green > checkmark decoration on every test. Correct. > If I test for thrown exceptions, I will inevitably get some black X's. > (Unless there is some way to negate the exception test so that it only > gives the black X if the exception FAILS to be thrown???) Got it in one. tom -- I KNOW WAHT IM TALKING ABOUT SO LISTAN UP AND LISTEN GOOD BECUASE ITS TIEM TO DROP SOME SCIENTISTS ON YUO!!! -- Jeff K
From: Rhino on 18 May 2010 17:05 > > public void testParseException() { > try { > myObj.getRGB("Bad value!"); > fail("Bad value did not cause exception!"); > } catch(IllegalArgumentException e) { > // Success! > } > } > > public void testGoodParse() { > assertEqual(white, myObj.getRGB("FFFFFF")); > } > > Thank you VERY much for the speedy AND accurate answer! It never occurred to me to try that! It solves my problem very simply and elegantly. :-) -- Rhino
From: Lew on 18 May 2010 17:09 On 05/18/2010 04:21 PM, Rhino wrote: > I'm having a bit of a conceptual struggle right now with the right way to > handle exceptions in JUnit tests. Since I always explain concepts better in > terms of examples, let me describe a scenario to you which should > illustrate the situation clearly. > > I have a method called getRGBColor() whose input parameter is a six letter > String that is supposed to contain exactly six hex digits. Those hex digits > are the String representation of an RGB Color. Therefore, "FFFFFF" > represents White. > > I have no trouble writing a JUnit test that passes in "FFFFFF" as an input > value and then verifies that the Color returned by the method is White i.e. > Color(255,255,255) so I can test that aspect of the code without trouble. > > However, the method throws IllegalArgumentException if the input String is > not precisely 6 characters long or if any of the characters are not hex > digits. > > I can easily invoke the method with a value that will cause the exception > to be thrown and I can catch it with a standard try/catch block. I can also > put code in my catch block to make sure that JUnit reports the error from > the Exception in the method being tested. I end up with this test which > correctly reports the IllegalArgumentException within the JUnit window: > > try { > Color actualRGBColor = colorConversionUtils.getRGBColor("FFFFFFA"); > Color expectedRGBColor = new Color(255, 255, 255); > assertTrue("Actual color, " + actualRGBColor + ", does not equal expected > color, " + expectedRGBColor, actualRGBColor.equals(expectedRGBColor)); > > } Your closing brace is supposed to line up at the same level as the 'try' command. > catch (IllegalArgumentException ia_excp) { The Java naming conventions decry the use of underscores in names of non-constant variables. Use camel case. You've seen this suggestion before, no? > assertionFailedError = new AssertionFailedError(ia_excp.getMessage()); > assertionFailedError.initCause(ia_excp); > throw assertionFailedError; Why the heck are you throwing an error for the desired result? > } .... > I don't see how I can reconcile these two ideas. If I test for thrown > exceptions, I will inevitably get some black X's. (Unless there is some way > to negate the exception test so that it only gives the black X if the > exception FAILS to be thrown???) But if I get black X's, how am I to know > quickly which of the test methods SHOULD be getting black X's and which > ones should be getting green checkmarks? I don't much like the idea of > trying to document all that and I certainly can't memorize it all.... If the test is supposed to throw an exception, then don't throw an AssertionFailedError in the 'catch' block. If the test is not supposed to fall through to the comparison with the expected color, then you are not expecting the color you assert to be expected. You will not "get a green check" if you lie about the expected results. Tell the truth instead; it works better. try { Color actualRGBColor = colorConversionUtils.getRGBColor("FFFFFFA"); fail( "should have thrown IllegalArgumentException" ); } catch ( IllegalArgumentException exc ) { assertNotNull( "Null exception!?", exc ); } -- Lew
|
Next
|
Last
Pages: 1 2 3 Prev: www.promptc.com (free shipping,only $16-69) for NFL jersey--Paypal Next: Up to date SOAP implementation |