Carl
Carl

Reputation: 7564

Java Habits for main method

I write code primarily for personal use, but I'm considering releasing an application (scientific simulation/visualization) that I originally developed for personal use.

One of my habits is to use a main method in classes for testing the operation of the class in isolation. I figure that's probably bad in someway (as are no doubt various other habits originating from self-teaching and the scientific development environment). However, it's never been a problem for self-use stuff that I've noticed.

Would you all be so kind as to confirm (or deny) that the proliferation of mains is a problem for an application released to the scientific community (the source would also be open), and if so, why?

EDIT: To play devil's advocate (okay, my advocate) relative to some of the offered answers: part of the "application use" is expected to be source modification by non-developers (the typical scientist) on a smallish scale. I know that on the receiving end, that having the tests for a class built directly into that class would be pretty straightforward for me to recognize and modify accordingly (especially if that were consistently the case for the classes). Would using something like JUnit provide similar utility, keeping in mind the audience?

ACCEPT DECISION: I think KLE's answer is the best balance of thorough and succinct, so I picked it, but I think the discussion comments in Bill's are also very helpful. I also don't understand why Johannes's answer was voted down - the "how does this piece work" perspective is very important to the scientific community coders - and while the other answers point out various reasons why separated unit tests are probably more useful than my current habit, they don't really address that use, so his answer is far from "unhelpful". Thanks to all current (and future) responders, and here's to wishing there was a way to combine multiple responses as the correct answer!

Upvotes: 6

Views: 707

Answers (7)

Andreas Dolk
Andreas Dolk

Reputation: 114847

I would not use main methods in all classes for testing purposes too. First, to follow the separation of concerns rule (using and testing are different concerns) and because we have elegant solutions for testing.

Second, and that hasn't been mentioned so far, if each and every class has a main method, it's pretty hard to find the 'real' entry point into the application. If I see a class with a main method, I expect that this will let me 'use' the class in its intended way. I don't expect, that this will start a test case (maybe with serious side effects).

Ah, just a third aspect that comes to my mind: the main methods are always public, so user of your library is free to use these methods at any time, even from during execution of his own application. This can have terrible side-effects, especially in multi-threaded environments.

Upvotes: 0

KLE
KLE

Reputation: 24169

JUnit lets you have tests, just like your mains, but also:

  • a main is typically only one method, that can get real big ; if extracting small methods used only for test, there is a risk to use that methods in regular code
  • doesn't clutter the class itself with the testing methods, they are in a different class
  • allows inheritance in the test classes (main, as a static method, is impossible to inherit or reuse) ; typically, the setup before the actual test maybe pretty long, and reusing it naturally is great
  • a main has no result (success or failure), only an output ; you need to check manually the output to determine the result, and possibly understand it
  • allow execution of several tests (class, package, project, all) at once, which is required for regression testing (or you will spend your afternoon executing them one by one)
  • JUnit provide many additional features out of the box, like marking some tests as ignored, checking that a test is not too long, provide several launching UIs etc.
  • you can reuse some tests on each implementation or subclass (ex: checking for Liskov substitution), which allows you to test a lot without maintaining a lot of test code.

Upvotes: 6

Aaron Digulla
Aaron Digulla

Reputation: 328850

There is nothing wrong with this approach per se but there is a major drawback: You must call each main() method individually to test all your code. Chances are that you won't. It's just too much hazzle. Also, when doing this, you must know which main() methods are real entry points and which ones are tests. This isn't at all obvious.

With JUnit and similar tools, you can mark code as "this is a test". This allows the tool to find all tests in your project automatically and run all of them at once. This way, chances are much higher that you'll run all tests most of the time and that bugs are caught early.

Upvotes: 0

JZeeb
JZeeb

Reputation: 321

First of all, it is great that you are writing tests. I don't really like the approach of having a main method in lots of classes in a project. I would advocate moving the test code out and using a testing framework. This keeps the source code cleaner, and if you use a consistent naming methodolgy for your test classes, it is easy to find the associated tests too.

Upvotes: 6

cletus
cletus

Reputation: 625457

It's not terrible but it's not advised for two reasons:

  1. It may allow users to do things you don't want them to do or at least give them the idea that they can do something you'd rather they didn't; and
  2. Prolific main() methods are often a poor substitute for unit tests.

It's (2) you should really concentrate on.

Upvotes: 3

Vincent Ramdhanie
Vincent Ramdhanie

Reputation: 103155

You need to use a testing tool such as JUNIT to perform testing on your classes rather than inserting the testing code into your production code.

This cleanly separates the tests from your code.

Upvotes: 2

Bill the Lizard
Bill the Lizard

Reputation: 406125

Testing your class in its own main method is bad because it gives the class an extra responsibility (testing itself). Tests should go in separate classes, preferably using a testing library like JUnit.

The proliferation of mains (I like this phrase you've coined) also makes it more confusing for a developer to find the entry point to your application when they are approaching it for the first time.

Upvotes: 12

Related Questions