Building a test suite in a large existing Java code base - java

I am working on a web application with an existing code base that has probably been around for 10 years, there are ~1000 class files and ~100,000 lines of code. The good news is that the code is organized well, business logic is separate from the controller domain, and there is a high level of reusability. The bad news is there is only the very beginnings of a test suite (JUnit); there's maybe 12 dozen tests at most.
The code is organized fairly typically for an enterprise Java project. There is a stuts-esque controller package, the model consists of almost purely data objects, there is a hibernate like database layer that is largely encapsulated within data access objects, and a handful of service packages that are simple, self contained, and logical. The end goal of building this test suite is to move towards a continuous integration development process.
How would you go about building a test suite for such an application?
What tools would you use to make the process simpler?
Any suggestions welcome. thanks!

Start by reading Working Effectively with Legacy Code (short version here). Next I would write a couple of end-to-end smoke tests to cover the most common use cases. Here are some ideas on how to approach it: http://simpleprogrammer.com/getting-up-to-bat-series/
Then when I need to change some part of the system, I would cover it with focused unit tests (refer to the aforementioned book) and then do the change. Little by little the system - or at least the parts which change the most often - would be better covered and working with it would become easier.

I would create a few integration tests. Since they toch a lot of code, you probably will get an error when you screw up bigtime.
I wouldn't 'build a testsuite' as such, but rather before changing some part define a testset for it, and then go about changing it.
I would suggest looking into a test coverage tool (I don't code Java, so no clue what tool the best is for Java). While it does not tell you when you've tested enough, it does tell you when you tested too little ;)
Good luck!

If the project isn't already maven-ized I would do that. Also be sure to use a mocking framework like mockito. Hudson is a nice CI tool that integrates nicely with maven.

It looks like you are going to be writing both unit and functional tests, so JUnit might not be the best fit for this. Have you considered TestNG? Since you only have very few tests right now, you have the option to pick what's best for the job.

Related

Where to learn about writing test cases?

I'm a CS master student. Throughout my studies I coded many course projects in Java. Soon I will graduate. When I explore some github projects I often find people organize their projects as /main and /test. I have never organized it in such a way, i.e. I always have my source code files without any test directories. I think that folder often contains what I think is called 'test cases' or so.
Since I will find a job soon, then I would like to learn about production-quality code.
My questions:
Why people often have that folder? What does it contain?
Can you provide me with a link to a good tutorial about the practice of testing in java? i.e how to do it? In a nutshell I wanna understand the idea of that /tests/ folder.
I often find people organize their projects as /main and /test
This is a matter of taste. Not 100% sure but at least maven projects have such organization.
From Maven: Introduction to the Standard Directory Layout, this would be the project layout:
src
main
java <-- your Java source code
resources
filters
config
scripts
webapp
test
java <-- your unit tests for Java
resources
filters
it
assembly
site
Why people often have that folder? What does it contain?
Usually, people write test cases to cover the code and check if the code works as expected. This is known as Code Coverage. Code coverage also serves as regression tests in case somebody makes changes in the code for enhancements like code refactoring.
The test cases you will find them usually are for Unit Testing. Depending on the type of the project, you could also find Integration Tests.
There is also Test Driven Development, or TDD, which is a practice whose basis is writing the test cases before writing the real code.
Can you provide me with a link to a good tutorial about the practice of testing in java?
This is off topic for the site. There are plenty tutorials on the net about this.
I don't have a separate folder for mine but usually people keep their Unit Tests in that folder. A unit test generally sets up "fake" data to test a given class so that a developer can easily debug any issues.
The reason people provide a /test folder is to contain unit test for their project.
There are really many ways of testing Java but JUnit is a very commonly used method of testing.
It is a good practice to write tests for your code. Begin with writing Unit Tests. I found this tutorial very useful. Writing test ensures that your code behaves as expected , corner cases are tested and adding new code in the future does not break existing functionality.
There are also mocking frameworks like JMock and Mockito that make writing stubs and drivers for your methods easy.
What is even more interesting is people prefer writing tests before they write the actual implementation. This approach is called Test Driven Development or Extreme Programming. Writing tests first ensure one already has a prep code or pseudo code for the methods in mind.

Can unit tests be used for checking student work

I have a class of high school programming students and I would like an automated way to check the validity of their work. I go through their code and look for structure, efficiency and basic expected outcomes but I was hoping to take it to another level.
Would Unit Testing be a viable solution?
Is there an elegant way of check a bunch of student programs at once?
We are using Eclipse and I've imported their project, containing all of their programs, from their local network drive. Works great. I'm just trying to give them more feedback on how they are doing, and even introduce them to unit testing, which is something I've never done.
yes sure you can do that for checking the students work as
Unit Testing reduces the level of bugs in production code.
Automated tests can be run as frequently as required.
In my university we had automated tests for excercises. We just mailed the class files or built jars to an email address. On the serverside you set them in the classpath and start your tests. It's actually quite easy to implement. The important thing is to clearly document package structure and such in the given requirements, maybe even supply a project skeleton.
Nice plus: the students were given a smaller sets of tests so they could verify they work before they submitted it.
I think introducing them to unit testing and TDD is a great idea.
However, if YOU write the unit tests and give them to your students before they do the assignment, then they won't learn to write unit tests. Also, they will structure their code according to your test, which may or may not be what you want.
If they, on the other hand, write the unit tests, they will learn how to do that, but you won't know what their tests are testing.
Perhaps you could extract code test coverage and assign them to reach 80, 90 or 100% coverage or something like that.
I did a review of a programming test today, for a eventual new hire, and I feel that the reasoning behind programming choices is really important.

Test Driven Development - Spring Application

I am developing a REST API. I have Jmeter tests already for the functional testing. I wanted to add unit tests and also want to follow test driven development(TDD) from now on to make any enhancement and add new functionality to my existing project (which is bound to grow very complex and does not have any unit tests in place).
After reading a lot about TDD I am little confused about whether I should be going for TDD. There are extreme outlooks for and against it.
I think I will follow TDD only to develop my service layer, which encompasses only business logic.
Any suggestions about my approach ?
TDD is more than that. It is not only a way for you to check if a system is externally working fine. TDD is also a means to accelerate development of your classes, even if they do not interact with other systems.
Think of a test as a response to the following questions:
Am I done developing this class?
Do the classes I already developed and tested still work fine after a change I've made?
How to represent requirements as source code?
An explanation about each question:
How do you know you are done writing a class? A test can tell you that by only showing a test successful message after your class does everything it was supposed to do.
You need test automation in order to test often.
Whenever you have a new requirement, write a new test that represents this requirement.
TDD is one of the best practices to follow as you would test before you develop. And you would know at each and every step during developing the application/service if you have broken any previous functionality.
You are at the right path and I would always encourage using TDD. If you are working on a project right from scratch then just go for it.
Since yours is an existing project it may be a headache at first till you cover unit test cases for all the existing functionality.
So the best approach is:
Write down all the unit test cases for existing functionality before you start development for new functionality.
While doing that you may come up with a lot of surprises and may end up re-factoring a lot of code. This will help you while developing future new functionality.
Now since your code looks much better you can start TDD for the new functionality.
Let me know if this helps. I have used TDD in many of my projects and I am comfortable with that.
Since you're using Spring, I'd suggest that the object to unit test should not be a web service. I'd make it an interface-based POJO. The behavior should not be affected by the choice to deploy as REST.
Marshaling and unmarshaling the HTTP request and response to objects for the POJO to consume can be separate.
This arrangement will have the added benefit of not requiring deployment to a container in order to test.

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.

Java/J2EE standard practices and design choices

I have a couple of design/architectural questions that always come up in our shop. I said "our", as opposed to "me" personally. Some of the decisions were made and made when J2EE was first introduced so there are some bad design choices and some good.
In a web environment, how do you work with filters. When should you use J2EE filters and when shouldn't you? Is it possible to have many filters, especially if you have too much logic in them. For example, there is a lot of logic in our authentication process. If you are this user, go to this site and if not go to another one. It is difficult to debug because one URL path could end up rendering different target pages.
Property resource bundle files for replacement values in JSP files: It seems that the consensus in the Java community is to use bundle files that contain labels and titles for a jsp parsing. I can see the benefit if you are doing development with many different languages and switching the label values based on locale. But what if you aren't working with multiple languages? Should every piece of static text in a JSP file or other template file really have to be put into a property file. Once again, we run into issues with debugging where text may not show up due to misspelling with property value keys or corrupt property files. Also, we have a process where graphic designers will send us html templates and then we convert them to jsp. It seems it more confusing to then remove the static text, add a key, add the key/value in a property file, etc.
E.g. A labels.properties file may contain the Username: label. That gets replaced by some key and rendered to the user.
Unit Testing for all J2EE development - we don't encourage unit testing. Some people do but I have never worked at shop that uses extensive unit testing. Once place did and then when crunch time hit, we stopped doing unit testing and then after a while the unit tests were useless and wouldn't ever compile. Most of the development I have done has been with servers, web application development, database connectivity. I see where unit testing can be cumbersome because you need an environment to unit test against. I think unit test manifestos encourage developers not to actually connect to external sources. But it seems like a major portion of the testing should be connecting to a database and running all of the code, not just a particular unit. So that is my question, for all types of development (like you see in CRUD oriented J2EE development) should we write unit tests in all cases? And if we don't write unit tests, what other developer testing mechanisms could we use?
Edited: Here are some good resources on some of these topics.
http://www.ibm.com/developerworks/java/library/j-diag1105.html
Redirection is a simpler way to handle different pages depending on role. The filter could be used simply for authentication, to get the User object and any associated Roles into the session.
As James Black said, if you had a central controller you could obviate the need to put this logic in the filters. To do this you'd map the central controller to all urls (or all non-static urls). Then the filter passes a User and Roles to the central controller which decides where to send the user. If the user tries to access a URL he doesn't have permission for, this controller can decide what to do about it.
Most major MVC web frameworks follow this pattern, so just check them out for a better understanding of this.
I agree with James here, too - you don't have to move everything there but it can make things simpler in the future. Personally, I think you often have to trade this one off in order to work efficiently with designers. I've often put the infrastructure and logic in to make it work but then littered my templates with static text while working with designers. Finally, went back and pulled all the static text out into the external files. Sure enough, found some spelling mistakes that way!
Testing - this is the big one. In my experience, a highly disciplined test-first approach can eliminate 90% of the stress in developing these apps. But unit tests are not quite enough.
I use three kinds of tests, as indicated by the Agile community:
acceptance/functional tests - customer defines these with each requirement and we don't ship til they all pass (look at FitNesse, Selenium, Mercury)
integration tests - ensure that the logic is correct and that issues don't come up across tiers or with realistic data (look at Cactus, DBUnit, Canoo WebTest)
unit tests - both defines the usage and expectations of a class and provides assurance that breaking changes will be caught quickly (look at JUnit, TestNG)
So you see that unit testing is really for the benefit of the developers... if there are five of us working on the project, not writing unit tests leads one of two things:
an explosion of necessary communication as developers try and figure out how to use (or how somebody broke) each other's classes
no communication and increased risk due to "silos" - areas where only one developer touches the code and in which the company is entirely reliant on that developer
Even if it's just me, it's too easy to forget why I put that little piece of special case logic in the class six months ago. Then I break my own code and have to figure out how... it's a big waste of time and does nothing to reduce my stress level! Also, if you force yourself to think through (and type) the test for each significant function in your class, and figure out how to isolate any external resources so you can pass in a mock version, your design improves immeasurably. So I tend to work test-first regardless.
Arguably the most useful, but least often done, is automated acceptance testing. This is what ensures that the developers have understood what the customer was asking for. Sometimes this is left to QA, and I think that's fine, but the ideal situation is one in which these are an integral part of the development process.
The way this works is: for each requirement the test plan is turned into a script which is added to the test suite. Then you watch it fail. Then you write code to make it pass. Thus, if a coder is working on changes and is ready to check in, they have to do a clean build and run all the acceptance tests. If any fail, fix before you can check in.
"Continuous integration" is simply the process of automating this step - when anyone checks code in, a separate server checks out the code and runs all the tests. If any are broken it spams the last developer to check in until they are fixed.
I once consulted with a team that had a single tester. This guy was working through the test plans manually, all day long. When a change took place, however minor, he would have to start over. I built them a spreadsheet indicating that there were over 16 million possible paths through just a single screen, and they ponied up the $10k for Mercury Test Director in a hurry! Now he makes spreadsheets and automates the test plans that use them, so they have pretty thorough regression testing without ever-increasing QA time demands.
Once you've begun automating tests at every layer of your app (especially if you work test-first) a remarkable thing happens. Worry disappears!
So, no, it's not necessary. But if you find yourself worrying about technical debt, about the big deployment this weekend, or about whether you're going to break things while trying to quickly change to meet the suddenly-urgent customer requirements, you may want to more deeply investigate test-first development.
Filters are useful to help move logic such as is the user authenticated, to properly handle this, since you don't want this logic in every page.
Since you don't have a central controller it sounds like your filters are serving this function, which is fine, but, as you mentioned, it does make debugging harder.
This is where unit tests can come in handy, as you can test different situations, with each filter individually, then with all the filters in a chain, outside of your container, to ensure it works properly.
Unit testing does require discipline, but, if the rule is that nothing goes to QA without a unit test then it may help, and there are many tools to help generate tests so you just have to write the test. Before you debug, write or update the unit test, and show that the unit test is failing, so the problem is duplicated.
This will ensure that that error won't return, and that you fixed it, and you have updated a unit test.
For resource bundles. If you are certain you will never support another language, then as you refactor you can remove the need for the bundles, but, I think it is easier to make spelling/grammar corrections if the text is actually in one place.
Filters in general are expected to perform smaller units of functionality and filter-chaining would be used to apply the filters as needed. In your case, maybe a refactoring can help to move out some of the logic to additional filters and the redirecting logic can be somewhat centralized through a controller to be easier to debug and understand.
Resource bundles are necessary to maintain flexibility, but if you know absolutely that the site is going to be used in a single locale, then you might skip it. Maybe you can move some of the work in maintaining the bundles to the designers i.e let them have access to the resource bundles, so that you get the HTML with the keys in place.
Unit testing is much easier to implement at the beginning of a project as opposed to building it into a existing product. For existing software, you may still implement unit tests for the new features. However, it requires a certain amount of insistence from team leads and the team needs to buy into the necessity of having unit tests. Code review for unit tests helps and a decision on what parts of the code need to be absolutely covered can help developers. Tools/plugins like Coverlipse can indicate the unit testing coverage, but they tend to look at every possible code path, some of which may be trivial.
At one of my earlier projects, unit tests were just compulsory and unit tests would be automatically kicked off after each check-in. However, this was not Test-driven development, as the tests were mostly written after the small chunks of code were written. TDD can result in developers writing code to just work with the unit tests and as a result, developers can lose the big picture of the component they are developing.
In a web environment, how do you work with filters. When should you use J2EE filters and when shouldn't you?
Filters are meant to steer/modify/intercept the actual requests/responses/sessions. For example: setting the request encoding, determining the logged-in user, wrapping/replacing the request or response, determining which servlet it should forward the request to, and so on.
To control the actual user input (parameters) and output (the results and the destination) and to execute actual business logic, you should use a servlet.
Property resource bundle files for replacement values in JSP files.
If you don't do i18n, just don't use them. But if you ever grow and the customer/users want i18n, then you'll be happy that you're already prepared. And not only that, it also simplifies the use of a CMS to edit the content by just using the java.util.Properties API.
Unit Testing for all J2EE development
JUnit can take care about it. You can also consider to "officially" do user tests only. Create several use cases and test it.

Categories