How to organize unit tests for a complex class? - java

I have a complex class (300+ lines), which I'm trying to test from different "points of view". I've already created three different unit tests. Every test is a complex class itself (100+ lines). The question is -- what is the best place to store them, in project directory tree? This is how I'm doing it now (Maven is used):
pom.xml
/src
/main
/java
/com
/Foo
ComplexClass.java
/test
/java
/com
/Foo
/ComplexClass
FirstPointOfViewTest.java
SecondPointOfViewTest.java
ThirdPointOfViewTest.java
Of course, the names are just placeholders, used in order to explain the problem/question. What do you think about this approach?

Your class is so complex that you need three different test classes to test all the aspect of the class? Probably you have mixed too many concerns in a single class. I would suggest refactoring the class using proven design patterns to separate classes with orthogonal concerns that can then be tested individually.

One thing you might want to consider: if you keep your test code package structure the same as your main code package structure---even using different physical directories as you are currently doing---your test classes will be in the same logical package as your main classes. This means they gain access to default/protected members in the tested classes, which is often helpful. You'd have to get rid of the ComplexClass package in the test code to make that happen.
Another thing to consider: (I'll assuming you're testing with JUnit) Test classes are classes, so you can organize and structure them using inheritance. If you have 3 different points of view, maybe extract a base class which contains common functionality, this will make your tests easier to maintain in the long run, especially as more "points of view" are discovered.
Separating the source and test code as you are already doing is a great idea, it gives you more options for building and maintains a logical grouping which makes maintenance more straightforward.

I'd keep what you currently have. The main advantage of this maven structure is that rather than mixing source and test code together and trying to identify which classes to exclude from your build you just ignore the test directory entirely. The point of using the same package is to expose protected methods/variables to your test classes but not to a public API.
One thing I might suggest is something I picked up at a talk by John Smart on Test Driven Development which is to name your test classes in groups of functionality they are testing, so you just have FirstPointOfView.java which is testing the behaviour of your first point of view of the com.foo package. This approach should make it more obvious when you can split a test class into individual classes, if they are actually testing different sets of behaviour.
Edit: if ComplexClass is a directory you should drop that, so that your tests are in the same package, I think I may have missread your example tree

Related

JUnit: best strategy for placing test-methods

I started a project and using JUnit for the 1st time.
Whats the best practice of putting testcases?
1 testclass for every "real" class.
1 testclass for every package or even the complete project.
Testmethods in the "real" class without a testclass.
As far I see I can technically do every 3 ways but I do not have experience in that so I ask for some guidance to do it right from the very beginning.
EDIT
I am talking about code unit testing. I am using maven too but I think that is not important for my question.
1 test class for every "real" class.
I typically go with this pattern. Of course, tests for interfaces don't make much sense and there are times when small "entity" classes with getter and setter methods only (i.e. no logic) don't need a corresponding test class.
That said, I've been surprised at what utility I've found in unit tests even on very small classes. For example, even entity classes with only get/set methods which are stored in databases through DAO methods should be tested in case some of the database wiring is incorrect. You never know when you have a mismatched get/set method or if the toString(), asymmetric hashcode() or equals(), or other issues.
The entire point of "unit" tests is (IMHO) to test the smallest unit of your code in isolation -- this is the class. So therefore when I have a ContainerUtil class, I look for a corresponding ContainerUtilTest class in the test directory. I run coverage tests often and I expect just about any logic portions of all classes to be covered.
1 test class for every package or even the complete project.
I might have this as well but then I'd consider these to be "integration" tests. Tests that bridge between classes or between various parts of the project to ensure that your project works as a whole.
But these would be in addition to your unit tests.
Test methods in the "real" class without a test class.
Yeah, no. Really bad idea. You don't want your production code to include test code if at all possible. It decreases the readability of your classes, increases the change that you break something while trying to test, etc.. Just say no.
I also keep my test classes away from my sources. I usually use maven so I have my sources in src/main/java and my tests in src/test/java. You don't want your tests to end up in the jar or war files where they might confuse others.
It really depends on how big your project is, but in my experience the best approach would be one test class for every "big" functionality (this may not apply for unit testing), or in this case, for every "real" class.
About the other 2:
1 testclass for every package or even the complete project.
This may grow to big and messy, wouldn't recommend mixing different things in the same test class, the same way that you wouldn't mix classes within the same file
Testmethods in the "real" class without a testclass.
I do not recommend this one either as you lose track of where are the tests and which things have tests implemented vs are missing. Also, your code may require accessing other classes as well, so this may become a mess as again.
For unit testing, i so far have used one test class for each tested class. FOR ME, it seemed to be the least messy order. I put the unit tests under src/test/java in the same package tree as the tested classes in src/main/java. Integration tests are different and have their own files each.
One testclass has different disadvantages. Source code will become unreadable. You will do a lot of unnecessary work in #Before and #BeforeEach methods.
And i don’t get the point of putting tests into the tested class. Lots of imports, and how would you differ between „real“ and test methods? And because of the additional methods, source code will become unreadable.
I would suggest you try the first approach. It is very useful because you can track using some tool as Sonar the percentage of coverage from your unit tests.
Also, I strongly recommend you apply TDD to develop your code: first you write your test code to fail, then you write code to make your test pass and then you refactor.
Allow me to suggest two sources of reading to help you with that:
Test Driven Development: By Example
Refactoring: Improving the Design of Existing Code
These are the same reading resources I used to start building tests and using TDD.
I woudn't recommend you to use the other approaches, as you don't need to ship test code to production and using a single test class would cause a code smell known as "Large Class".

Determining the test classes in a project

I wonder is there any id or specified label to distinguish a selected class whether it is one of the standard class declarations or test class in run-time?
EDIT: I collect the entire classes from the project. I separate abstract classes, interfaces, subclasses by looking the collection, whereas I also want to know how many classes have test behavior. In other words, how many classes are actually test classes. One more thing: I don't know these classes in advance, these are not mine!
Let me share with you how I like to organize my tests in eclipse :-) maybe you may find useful.
First, I create two projects, one for the app and another for the test.
The test project, of course, has a dependency on the app project
Now, let's suppose you want to add some test case, you just point to the right src dir.
So you want to create your test code without mixing app code and test code (for example, utils), just leave what's specific to the right project.
The only name convention I use is the eclipse junit default, appending the word "Test" in the end of the test class.
No need for ant scripts to deploy only the app code.
Even JUNIT dependency is restricted to the test project.
I hope it helps.

Best practive for JUnit package naming?

I was trying to find some best practice for naming Java package for testing. I would be thinking something along:
Tests on:
com.example.MyClass
should be in:
com.example.test.MyClassTest
Typically I put the test classes in the same package, but under a different source root. Aside from anything else, this allows you to test members (and indeed classes) which have default visibility. Sometimes I'll even make methods which would otherwise be private, package-level to make testing easier, knowing that it will only have limited impact. This very much depends on the context in which you're developing though. (Most of my code is written in a trusted environment; I want to limit access for elegance, but I'm not worried that anyone will actively try to use a method they shouldn't. And I use an annotation to indicate the intention.)
You definitely want an easy way of separating out your test classes from your production classes, both for deployment purposes and to let you concentrate on "just the prod code" when appropriate. But I don't see any disadvantage in using the same package declaration for both tests and production code.
One of the best options is putting the tests in another source folder. This way you can easily seperate the acctual source from the tests, e.g. when building a release. Take a look at Mavens default directory layout. A propper IDE should be able to handle different source folders even without Maven.
As for the package: If you have two different source folders, you can have the test classes in the same package. This has several advantages like beeing able to access package protected members from your test or using nice plugins like MoreUnit.

Separation of JUnit classes into special test package?

I am learning the concepts of Test-Driven Development through reading the Craftsman articles (click Craftsman under By Topic) recommended in an answer to my previous question, "Sample project for learning JUnit and proper software engineering". I love it so far!
But now I want to sit down and try it myself. I have a question that I hope will need only a simple answer.
How do you organize your JUnit test classes and your actual code? I'm talking mainly about the package structure, but any other concepts of note would be helpful too.
Do you put test classes in org.myname.project.test.* and normal code in org.myname.project.*? Do you put the test classes right alongside the normal classes? Do you prefer to prefix the class names with Test rather than suffix them?
I know this seems like the kind of thing I shouldn't worry about so soon, but I am a very organization-centric person. I'm almost the kind of person that spends more time figuring out methods to keep track of what to get done, rather than actually getting things done.
And I have a project that is currently neatly divided up into packages, but the project became a mess. Instead of trying to refactor everything and write tests, I want to start fresh, tests first and all. But first I need to know where my tests go.
edit: I totally forgot about Maven, but it seems a majority of you are using it! In the past I had a specific use case where Maven completely broke down on me but Ant gave me the flexibility I needed, so I ended up attached to Ant, but I'm thinking maybe I was just taking the wrong approach. I think I'll give Maven another try because it sounds like it will go well with test-driven development.
I prefer putting the test classes into the same package as the project classes they test, but in a different physical directory, like:
myproject/src/com/foo/Bar.java
myproject/test/com/foo/BarTest.java
In a Maven project it would look like this:
myproject/src/main/java/com/foo/Bar.java
myproject/src/test/java/com/foo/BarTest.java
The main point in this is that my test classes can access (and test!) package-scope classes and members.
As the above example shows, my test classes have the name of the tested class plus Test as a suffix. This helps finding them quickly - it's not very funny to try searching among a couple of hundred test classes, each of whose name starts with Test...
Update inspired by #Ricket's comment: this way test classes (typically) show up right after their tested buddy in a project-wise alphabetic listing of class names. (Funny that I am benefiting from this day by day, without having consciously realized how...)
Update2: A lot of developers (including myself) like Maven, but there seems to be at least as many who don't. IMHO it is very useful for "mainstream" Java projects (I would put about 90% of projects into this category... but the other 10% is still a sizeable minority). It is easy to use if one can accept the Maven conventions; however if not, it makes life a miserable struggle. Maven seems to be difficult to comprehend for many people socialized on Ant, as it apparently requires a very different way of thinking. (Myself, having never used Ant, can't compare the two.) One thing is for sure: it makes unit (and integration) testing a natural, first-class step in the process, which helps developers adopt this essential practice.
I put my test classes in the same package as what they are testing but in a different source folder or project. Organizing my test code in this fashion allows me to easily compile and package it separately so that production jar files do not contain test code. It also allows the test code to access package private fields and methods.
I use Maven. The structure that Maven promotes is:-
src/main/java/org/myname/project/MyClass.java
src/test/java/org/myname/project/TestMyClass.java
i.e. a test class with Test prepended to the name of the class under test is in a parallel directory structure to the main test.
One advantage of having the test classes in the same package (not necessarily directory though) is you can leverage package-scope methods to inspect or inject mock test objects.

How should I structure a Java application, where do I put my classes?

First of all, I know how to build a Java application. But I have always been puzzled about where to put my classes. There are proponents for organizing the packages in a strictly domain oriented fashion, others separate by tier.
I myself have always had problems with
naming,
placing
So,
Where do you put your domain specific constants (and what is the best name for such a class)?
Where do you put classes for stuff which is both infrastructural and domain specific (for instance I have a FileStorageStrategy class, which stores the files either in the database, or alternatively in database)?
Where to put Exceptions?
Are there any standards to which I can refer?
I've really come to like Maven's Standard Directory Layout.
One of the key ideas for me is to have two source roots - one for production code and one for test code like so:
MyProject/src/main/java/com/acme/Widget.java
MyProject/src/test/java/com/acme/WidgetTest.java
(here, both src/main/java and src/test/java are source roots).
Advantages:
Your tests have package (or "default") level access to your classes under test.
You can easily package only your production sources into a JAR by dropping src/test/java as a source root.
One rule of thumb about class placement and packages:
Generally speaking, well structured projects will be free of circular dependencies. Learn when they are bad (and when they are not), and consider a tool like JDepend or SonarJ that will help you eliminate them.
I'm a huge fan of organized sources, so I always create the following directory structure:
/src - for your packages & classes
/test - for unit tests
/docs - for documentation, generated and manually edited
/lib - 3rd party libraries
/etc - unrelated stuff
/bin (or /classes) - compiled classes, output of your compile
/dist - for distribution packages, hopefully auto generated by a build system
In /src I'm using the default Java patterns: Package names starting with your domain (org.yourdomain.yourprojectname) and class names reflecting the OOP aspect you're creating with the class (see the other commenters). Common package names like util, model, view, events are useful, too.
I tend to put constants for a specific topic in an own class, like SessionConstants or ServiceConstants in the same package of the domain classes.
Where I'm working, we're using Maven 2 and we have a pretty nice archetype for our projects. The goal was to obtain a good separation of concerns, thus we defined a project structure using multiple modules (one for each application 'layer'):
- common: common code used by the other layers (e.g., i18n)
- entities: the domain entities
- repositories: this module contains the daos interfaces and implementations
- services-intf: interfaces for the services (e.g, UserService, ...)
- services-impl: implementations of the services (e.g, UserServiceImpl)
- web: everything regarding the web content (e.g., css, jsps, jsf pages, ...)
- ws: web services
Each module has its own dependencies (e.g., repositories could have jpa) and some are project wide (thus they belong in the common module). Dependencies between the different project modules clearly separate things (e.g., the web layer depends on the service layer but doesn't know about the repository layer).
Each module has its own base package, for example if the application package is "com.foo.bar", then we have:
com.foo.bar.common
com.foo.bar.entities
com.foo.bar.repositories
com.foo.bar.services
com.foo.bar.services.impl
...
Each module respects the standard maven project structure:
src\
..main\java
...\resources
..test\java
...\resources
Unit tests for a given layer easily find their place under \src\test... Everything that is domain specific has it's place in the entities module. Now something like a FileStorageStrategy should go into the repositories module, since we don't need to know exactly what the implementation is. In the services layer, we only know the repository interface, we do not care what the specific implementation is (separation of concerns).
There are multiple advantages to this approach:
clear separation of concerns
each module is packageable as a jar (or a war in the case of the web module) and thus allows for easier code reuse (e.g., we could install the module in the maven repository and reuse it in another project)
maximum independence of each part of the project
I know this doesn't answer all your questions, but I think this could put you on the right path and could prove useful to others.
Class names should always be descriptive and self-explanatory. If you have multiple domains of responsibility for your classes then they should probably be refactored.
Likewise for you packages. They should be grouped by domain of responsibility. Every domain has it's own exceptions.
Generally don't sweat it until you get to a point where it is becoming overwhelming and bloated. Then sit down and don't code, just refactor the classes out, compiling regularly to make sure everything works. Then continue as you did before.
Use packages to group related functionality together.
Usually the top of your package tree is your domain name reversed (com.domain.subdomain) to guarantee uniqueness, and then usually there will be a package for your application. Then subdivide that by related area, so your FileStorageStrategy might go in, say, com.domain.subdomain.myapp.storage, and then there might be specific implementations/subclasses/whatever in com.domain.subdomain.myapp.storage.file and com.domain.subdomain.myapp.storage.database. These names can get pretty long, but import keeps them all at the top of files and IDEs can help to manage that as well.
Exceptions usually go in the same package as the classes that throw them, so if you had, say, FileStorageException it would go in the same package as FileStorageStrategy. Likewise an interface defining constants would be in the same package.
There's not really any standard as such, just use common sense, and if it all gets too messy, refactor!
One thing that I found very helpful for unit tests was to have a myApp/src/ and also myApp/test_src/ directories. This way, I can place unit tests in the same packages as the classes they test, and yet I can easily exclude the test cases when I prepare my production installation.
Short answer: draw your system architecture in terms of modules, drawn side-by-side, with each module sliced vertically into layers (e.g. view, model, persistence). Then use a structure like com.mycompany.myapp.somemodule.somelayer, e.g. com.mycompany.myapp.client.view or com.mycompany.myapp.server.model.
Using the top level of packages for application modules, in the old-fashioned computer-science sense of modular programming, ought to be obvious. However, on most of the projects I have worked on we end up forgetting to do that, and end up with a mess of packages without that top-level structure. This anti-pattern usually shows itself as a package for something like 'listeners' or 'actions' that groups otherwise unrelated classes simply because they happen to implement the same interface.
Within a module, or in a small application, use packages for the application layers. Likely packages include things like the following, depending on the architecture:
com.mycompany.myapp.view
com.mycompany.myapp.model
com.mycompany.myapp.services
com.mycompany.myapp.rules
com.mycompany.myapp.persistence (or 'dao' for data access layer)
com.mycompany.myapp.util (beware of this being used as if it were 'misc')
Within each of these layers, it is natural to group classes by type if there are a lot. A common anti-pattern here is to unnecessarily introduce too many packages and levels of sub-package so that there are only a few classes in each package.
I think keep it simple and don't over think it. Don't over abstract and layer too much. Just keep it neat, and as it grows, refactoring it is trivial. One of the best features of IDEs is refactoring, so why not make use of it and save you brain power for solving problems that are related to your app, rather then meta issues like code organisation.
One thing I've done in the past - if I'm extending a class I'll try and follow their conventions. For example, when working with the Spring Framework, I'll have my MVC Controller classes in a package called com.mydomain.myapp.web.servlet.mvc
If I'm not extending something I just go with what is simplest. com.mydomain.domain for Domain Objects (although if you have a ton of domain objects this package could get a bit unwieldy).
For domain specific constants, I actually put them as public constants in the most related class. For example, if I have a "Member" class and have a maximum member name length constant, I put it in the Member class. Some shops make a separate Constants class but I don't see the value in lumping unrelated numbers and strings into a single class. I've seen some other shops try to solve this problem by creating SEPARATE Constants classes, but that just seems like a waste of time and the result is too confusing. Using this setup, a large project with multiple developers will be duplicating constants all over the place.
I like break my classes down into packages that are related to each other.
For example:
Model For database related calls
View Classes that deal with what you see
Control Core functionality classes
Util Any misc. classes that are used (typically static functions)
etc.

Categories