2

My boss at work decided it would be a good idea to write unit tests for a Java program I've been working on for a while. The program is your fairly typical mess, but it isn't huge. I've never used or written any unit tests before, and from everything I've read on the subject a pre-existing project is not the best place to start. I don't really have a choice though, so I have some questions.

My main question is this: I've read a lot of things about what unit tests should do, what their scope should be, how to write production code in a TDD process, etc. I have yet to find anyone who talks about where the code should actually go. Do I write my tests in the production code classes themselves? Do I put all of them in a separate .java file (or files)? Do I put them in their own directory in the project? If I use either of the latter options, how would I access private objects and methods in order to test them? I feel like this should be a fairly obvious question, but I just don't know.

And a secondary question: I've seen a lot of convincing arguments for using TDD, and I would like to try it in my personal projects. Would whatever the answer to my first question is hold true for starting completely new projects? Or would I implement unit tests differently for pre-existing projects as opposed to new ones?

DementedDr
  • 177
  • 2
  • 15
  • There are millions of search results that answer exactly the questions you ask - asking again here on SO seems quite a waste of time. – KevinDTimm Oct 10 '13 at 20:47
  • You have problems, separating the tests is a trivial issue. The main problem is the code won't be written to be tested, and in order to test it you'll have to change it, and you have no unit tests to prove that changes t=you make to test it haven't broken it. If it's small, treat your current code as Proof Of Concept, start again and do it with TDD, i.e. properly. – Tony Hopkinson Oct 10 '13 at 20:54
  • It's fine -- great, even -- to add tests to pre-existing projects. It just might seem like a bit more work, because you'll have to do an initial push as opposed to building it up incrementally. You'll probably find that in the process, you'll have to refactor classes to make them smaller and more modular, which might even make the code less of a mess. – yshavit Oct 10 '13 at 21:03

5 Answers5

3

Tests do not go in production code, you can put them in a separate subdirectory. If you know about Maven, that project enforces a standard directory structure for where things go, so your production code goes under src/main/java, your properties files go in src/main/resources, while tests go under src/test/java and files used by the java code go under src/test/resources. Maven makes sure that nothing in src/test finds its way into the artifact that it builds. (Home-grown builds using ant often have a problem with this because you have to actually think about where things go and make an effort to keep tests and code separate, or else everything gets flung together.)

Even if you can't use maven it's worthwhile to copy the directory structure just to follow a common agreed-on model.

You should be able to test your objects by instantiating them in your tests and calling their methods. If you've written a lot of code without tests you may have written it in a way that's hard to test, such as with singletons. You may have to rework some of your existing code to make it more easily testable.

Nathan Hughes
  • 94,330
  • 19
  • 181
  • 276
  • I forgot a word in my question. How would I access _private_ classes and methods? I'm also curious: is this general convention the same for other languages (I have a private project written in C#)? – DementedDr Oct 10 '13 at 21:21
  • @DementedDr: short answer: You don't. actually tests that directly access implementation details like that can be a problem because if your implementation changes you have to extensively rework your tests. one of the trickier things about writing tests is figuring out how to make them specific enough to be useful while keeping them maintainable too. a lot of the time things private to an implementation that are sufficiently complex to be worth testing can be refactored into a separate class and exercised separately. C# should be similar in principle, though directory structures may differ. – Nathan Hughes Oct 10 '13 at 21:27
2

I would start with your bugs. When you come to fix a bug, write a test which shows the bug. When you fix the bug, your test should pass. Btw expect half the bugs to be in your tests.

When you write test which are so trivial they can't fail but they do you will see the value of having tests. All sorts of issues will be found earlier when they are easier to fix, before the users see it.

Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
0

If you never used TDD before, you will find this tutorial very useful:

Junit Tutorial

AndyBaba
  • 875
  • 5
  • 7
0

It is never too late to start the testing of a project, you shouldn't worry about it.

You need to learn TestNG or JUnit 4 for java.

You should create separate java files for your tests, in a separate directory. Your test classes name should end with Test, for example: For MyClass.java main code, you write a MyClassTest.java test class.

For the other parts of you question, please visit: What is unit testing and how do you do it?

Community
  • 1
  • 1
acsadam0404
  • 2,711
  • 1
  • 26
  • 36
0

The way to add tests to existing legacy code with no tests is to add them to any part that you change.

Even if you decide that the program can't go on without good unit test coverage you will be doing something like this as it goes from 0% coverage to a much higher figure. Just remember, a system with 1 test has more tests that a system with zero tests!

The main problem you will run into is that the existing interfaces between parts of the program will not be suited to testing. Usually this is tight coupling requiring set up of almost all the sub systems before what should be a simple, isolated test can be carried out.

A good way around this is to use mocks to simulate the dependencies of parts that are difficult to decouple

Vorsprung
  • 32,923
  • 5
  • 39
  • 63