views:

157

answers:

7

Hi guys, I'm learning Java by reading "Head First Java" and by doing all the puzzles and excercies. In the book they recommend to write TestDrive classes to test the code and clases I've written, that's one really simple thing to do, but by doing this I think I can't fully test my code because I'm writing the test code knowing what I want to get, I don't know if it makes any sense, but I was wondering if there's any way of testing my code in a simple way that it tell's me what isn't working correctly. Thanks.

+1  A: 

One of the tenets of "Test Driven Development" is writing a test first (i.e. before you've written the code). Obviously this test will initially fail (your program may not even compile). If the test doesn't fail, then you know you've got a problem with the test itself. Once the test fails, the objective then becomes to keep writing code until the test passes.

Also, some of the more popular unit testing frameworks such as jUnit will allow you to test if something works or explicitly doesn't work (i.e. you can assert that a certain type of exception is thrown). This becomes useful to check bad input, corner cases, etc.

To steal a line from Stephen Covey, just begin with the end in mind and write as many tests as you can think of. This may seem trivial for very simple code, but the idea becomes useful as you move onto more complex problems.

Ben Hoffstein
This method seems very useful, thanks. I definitely give it a shot.
eiefai
+3  A: 

that's right - you know what to expect, and write test cases to cover that knowledge. In many respects this is normal - you want to test the stuff you've written just so you know it works as you expect.

now, you need to take it to the next step: find a system where it will be working (ie integrate it with other bits n pieces of the complete puzzle) and see if it still works according to your assumptions and knowledge.

Then you need to give it to someone else to test for you - they will quickly find the bits that you never thought of.

Then you give it to a real user, and they not only find the things you and your tester never thought of, but they also find the things that were never thought of by the requirements analyst.

This is the way software works, and possibly the reason its never finished.

PS. One thing about your test code that does matter more than anything - once you've done it once and found it works as expected, you can add more stuff to your app and then run your test code again to make sure it still works as expected. This is called regression testing and I think its the only reason to write your own unit tests.

and: Dilbert's take on testing.

gbjbaanb
Thanks, I'll give it a try. Any other advice as I'm still a newbie?
eiefai
I suggest another reason to write unit tests: the act of writing them leads you to write better code. You tend to be find yourself thinking about edge cases and corner cases.
djna
A: 

TestDrive

No, you should be writing JUnit or TestNG tests.

duffymo
+2  A: 

What do we mean by code? When Unit testing, which is what I think we're talking about here, we are testing specific methods and classes.

I think I can't fully test my code because I'm writing the test code knowing what I want to get

In other words you are investigating whether some code fulfils a contract. Consider this example:

 int getInvestvalue( int depositCents, double annualInterestRate, int years) {

 }

What tests can you devise? If you devise a good set of tests you can have some confidence in this routine. So we could try these kinds of input:

  deposit 100, rate 5.0, years 1 : expected answer 105
  deposit 100, rate 0, years 1 : expected answer 100
  deposit 100, rate 10, years 0 : expected anwer 100

What else? How about a negative rate?

More interestingly, how about a very high rate of interest like 1,000,000.50 and 100,000 years, what happens to the result, would it fit in an integer - the thing about devising this test is that it challenges the interface - why is there no exception documented?

The question then comes: how do we figure out those test cases. I don't think there is a single approach that leads to building a comprehensive set but here's a couple of things to consider:

  1. Edges: Zero, one, two, many. In my example we don't just do a rate of 5%. We consider especially the special cases. Zero is special, one is special, negative is special, a big number is special ...
  2. Corner cases: combinations of edges. In my example that's a large rate and large number of years. Picking these is something of an art, and is helped by our knowledge of the implmentation: here we know that there's a "multiplier" effect between rates and years.
  3. White box: using knowldge of the implementation to drive code coverage. Adjusting the inputs to force the code down particiular paths. For example if yoiu know that the code has a "if negative rate" conditional path, then this is a clue to include a negative rate test.
djna
This is exactly the kind of test I want to test my code/classes against, well, not exactly, but close. How can I get a glimpse at all of the different sceneries?
eiefai
added a few ideas
djna
A: 

Done correctly, your tests are your specification. It defines what your code is supposed to do. Each test defines a new aspect of your application. Therefore, you would never write tests looking for things that don't work correctly since you tests specify how things should work correctly.

Once you think you've finished unit testing and coding your component, one of the best and easiest ways to raise confidence that things are working correctly is to use a technique called Exploratory Testing, which can be thought of as an unscripted exploration of the part of the application you've written looking for bugs based on your intuition and experience (and deviousness!).

Pair Programming is another great way to prevent and flush out the bugs from your code. Two minds are better than one and often someone else will think of something you didn't (and vice versa).

Chris Knight
Thanks, pair programming it's out of discussion as I'm learning on my own, Exploratory Testing seems interesting I'll try it in my future projects.
eiefai
A: 

This site has a lot of help resources for testing codes. SoftwareTestingHelp

Holystream
+1  A: 

First, you need to make sure your code is written to be unit tested. Dependencies on outside classes should be made explicit (required by the constructor if possible) so that it isn't possible to write a unit test without identifying every possible way to break things. If you find that there are too many dependencies, or that it isn't obvious how each dependency will be used, you need to work on the Single Responsibility Principle, which will make your classes smaller, simpler, and more modular.

Once your code is written so that you can foresee situations that might occur based on your dependencies and input parameters, you should write tests looking for the correct behavior from a variety of those foreseeable situations. One of the biggest advantages I've found to unit testing is that it actually forced me to think, "What if ...", and figure out what the correct behavior would be in each case. For example, I have to decide whether it makes more sense to throw an exception or return a null value in the case of certain errors.

Once you think you've got all your bases covered, you might also want to throw your code at a tool like QuickCheck to help you identify possibilities that you might have missed.

StriplingWarrior