I'm writing a unit test for a custom subclass of org.springframework.http.converter.xml.AbstractXmlHttpMessageConverter<T>
and I need a stub implementation of org.springframework.http.HttpInputMessage. Looking through the Spring unit tests in the SVN repository, I found the class MockHttpInputMessage, which does exactly what I want.
Now, I wonder what is the proper way to reuse this class?
Or is it generally a bad idea, because the class is not meant to be used outside of the Spring unit tests?
I'm not involved in the Spring project, but from the names I would assume that the class is not intended for reuse. Therefore, I would simply take the class in source form and add it to your project test sources.
Of course all this assumes, this is acceptable with respect to licenses.
I would simply copy it to my own repository, and use it to my hearts content. You want it under your own control so that you are not adversely affected by future changes.
Related
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".
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.
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.
I often use the refactor -> rename functionality in eclipse and I also have the habit of naming the associated unit test TestedClassNameTest. But when I rename my tested class I must not forget to rename my unitTest. It would be extremely useful to rename my unit test automatically when the tested class is renamed.
I guess it wouldn't be that difficult to create a plugin that does the job but maybe that isn't even necessary?
I've found a plugin that does the trick http://moreunit.sourceforge.net/
After several googling and eclipse searches, it seems such feature is not yet available.
Today there is no notion of "class being unit tested" in Eclipse. What I mean here, is that you can create a Unit test classes testing anything you want: a full package, a single class, a single method, a full plugin ....
To get more accurate, there is "NO relation in Eclipse's model" between your tested class and the associated unit test.
I totally agree with you that it would be nice to such a feature in Eclipse. To go further it would be really cool to be able to generate Unit tests skeletons and thus have these tests classes linked to the tested ones.
May be you can laucnh the discussion on Eclipse Buzilla, maybe in the PDE category.
Manu
eclipse would not figure this out to change: It only changes the references of the method used in other classes or in the same class.
If you really want to make this functionality work, you could extend eclipse's refactoring API as I did for my project and give it this new functionality.
If you like to have any references on this just ask me ;-)
I'm currently re-using JUnit 4 tests from another project against my code. I obtain them directly from the other project's repository as part of my automated Ant build. This is great, as it ensures I keep my code green against the very latest version of the tests.
However, there is a subset of tests that I never expect to pass on my code. But if I start adding #Ignore annotations to those tests, I will have to maintain my own separate copy of the test implementation, which I really don't want to do.
Is there a way of excluding individual tests without modifying the Test source? Here's what I have looked at so far:
As far as I can see, the Ant JUnit task only allows you to exclude entire Test classes, not individual test methods - so that's no good for me, I need method granularity.
I considered putting together a TestSuite that uses reflection to dynamically find and add all of the original tests, then add code to explicitly remove the tests I don't want to run. But I ditched that idea when I noticed that the TestSuite API doesn't provide a method for removing tests.
I can create my own Test classes that extend the original Test classes, override the specific tests I don't want to run, and annotate them with #Ignore. I then run JUnit on my subclasses. The downside here is that if new Test classes are added to the original project, I won't pick them up automatically. I'll have to monitor for new Test classes as they are added to the original project. This is my best option so far, but doesn't feel ideal.
The only other option I can think of is to run the bad tests anyway and ignore the failures. However, these tests take a while to run (and fail!) so I'd prefer to not run them at all. Additionally, I can't see a way of telling the Ant task to ignore failures on specific test methods (again - I see how you can do it for individual Test classes, but not methods).
If you can't touch the original test at all you are going to have some serious limitations. Your overriding sounds like the best bet, but with a couple of changes:
Build the Ant tests specifically excluding the super classes, so that additional classes that you don't know about get run.
You can use the #Rule annotation (new to JUnit 4.7) to know what test is being run and abort it (by returning an empty Statement implementation) rather than overriding specific methods, giving you more flexibility in knowing whether or not to avoid the test. The only problem with this method is that you can't stop the #Before methods from running using this method, which may be slow. If that is a problem (and you really can't touch the tests) then #Ignore in the overridden method is the only thing I can think of.
If, however, you can touch those tests, some additional options open up:
You could run them with a custom runner by specifying the #RunWith tag on the class. This runner would just pass over execution to the standard runner (JUnit4.class) in that project, but in your project (via a system property or some other mechanism) would inspect the test name and not run a test. This has the advantage of being the least intrusive, but the most difficult to implement (runners are hairy beasts, one of the stated goals of #Rule was to eliminate most of the need to make them).
Another is to make an assumeThat statement on the test that would check some configuration setting that would be true if that test should run. That would actually involve injecting right into the test, which is most likely a deal breaker in anything remotely labeled a "separate project."
It doesn't help you now, but TestNG supports this sort of ability.
OK, this is a rather heavyweight solution, but don't throw things at me if it sounds ridiculous.
The core of Junit4 is the org.junit.runner.Runner class, and its various subclasses, most importantly org.junit.runners.Suite. These runners determine what the tests are for a given test class, using things like #Test and #Ignore.
It's quite easy to create custom implementations of a runner, and normally you would hook them up by using the #RunWith annotation on your test classes, but obviously that's not an option for you.
However, in theory you could write your own Ant task, perhaps based upon the standard Ant Junit task, which takes your custom test runner and uses it directly, passing each test class to it in turn. Your runner implementation could use an external config file which specifies which test methods to ignore.
It'd be quite a lot of work, and you'd have to spend time digging around in the prehistoric Ant Junit codebase to find out how it works. The investment in time may be worth it, however.
It's just a shame that the Junit Ant task doesn't provide a mechanism to specify the test Runner, that would be ideal.
A possibility I can think of to achieve what you want with the stated constraints is to use bytecode modification. You could keep a list of classes and methods to ignore in a separate file, and patch the bytecode of the test classes as you load them to remove this methods altogether.
If I am not mistaken, JUnit uses reflection to find the test methods to execute. A method rename operation would then allow you to remove these methods before JUnit finds them. Or the method can be modified to return immediately, without performing any operation.
A library like BCEL can be used to modify the classes when loaded.
If you want to run only a subset of the tests it sounds like that class has more than one responsibility and should be refactored down. Alternately the test class could be broken apart so that the original project had all the tests but on one or more classes(I'm guessing some of the tests are really integration tests and touch the database or network) and you could exclude the class(es) you didn't want.
If you can't do any of that, your option of overriding is probably best. Take the process of whenever you need to ignore some methods you extend that class and add it to your Ant exclude list. That way you can exclude what you can't pass and will still pull in all new tests (methods you didn't override and new test classes) without modifying your build.
If the unwanted tests are in specific classes/packages, you could use a fileset exclude in Ant to exclude them during import.
Two options
Work with the owner of the borrowed tests to extract your ones into a separate class you both can share.
Create your own test class which proxies the test class you want to use. For each method you want to include have a method in your class. You'll need to construct an instance of the test class you are calling and do before and after methods too if they're in the original.
Create a custom Junit runner based on blockjunitrunner and use it to filter out or in the tests you want.