JUnit - how to use both TestCase AND TestResult in test? - java

In order to use JUnit's TestCase methods such as setUp() and tearDown(), I have to have my test class extend TestCase.
In order to user JUnit's TestResult methods such as addFailure() and addError(), I have to have my test class extend TestResult.
Java does not allow for multiple inheritances, so how do I gain access to both of these (or more) classes in my tests?
OR: am I misunderstanding the purpose of the TestResult class, and this isn't something I should be doing?
Because I would imagine that I should be able to test an assertion (or other test) inside a try block for example, then catch and subsequently addError the caught exception.

Related

JUnit #Before vs #Rule

I understand that,
#Before and #BeforeClass run before each test, or the entire test class, respectively
#Rule and #ClassRule wraps each test, or the entire test class, respectively.
Let's say I need to initialize some data before each test method,
How do I decide between using #Before and #Rule? Under what conditions is one preferred over another? The same question also goes for #BeforeClass vs.#ClassRule.
In order to use #Rule, you require a class that implements TestRule(preferred) or MethodRule, as can be read here.
Whereas #Before and #After require a new method to be written in every test case, #Rule does not because it is only an instantiation of already existing code.
So, if you would use #Before and #After for setUp() and tearDown() that you'll be using in many test cases, it is actually a better idea to use #Rule because of code reuse. If you have a test case that requires a unique #Before and/or #After, then these annotations are preferable.
For a bit more elaborate answer with a couple examples, take a look here. Ajit explains it very well.
Indeed, as #Quwin suggested, accoridng to JUnit 4.12 API doc,
TestRule can do everything that could be done previously with
methods annotated with #Before, #After, #BeforeClass, or
#AfterClass, but TestRules are (1) more powerful, and (2) more easily shared
between projects and classes.
Ways that TestRules are more powerful:
There are known implementing classes of the TestRule, which are some usefuls rules you can use out-of-the-box,
For examples of how this can be useful, see these provided TestRules, or write your own:
ErrorCollector: collect multiple errors in one test method
ExpectedException: make flexible assertions about thrown exceptions
ExternalResource: start and stop a server, for example
TemporaryFolder: create fresh files, and delete after test
TestName: remember the test name for use during the method
TestWatcher: add logic at events during method execution
Timeout: cause test to fail after a set time
Verifier: fail test if object state ends up incorrect
Another benefit of rules, is that multiple rules can be used in a single test case. You may want to use RuleChain to specify the order in which the rules should be run.

JUnit test cleanup for single method

I have a JUnit test class with a number of different test cases. One of these test cases has bit different test setup and cleanup than the other ones. What is the best way to do test cleanup in such scenario? Extract test case into separate class and use standard #Before and #After annotations?
Make a subclass with only that test, write custom #Before and #After methods calling super ones if needed.

Is there a good way to engage the initialization of a test suite when running an individual test case?

Under JUnit4, I have a test suite which uses a #classrule annotation to bootstrap a framework. This is needed to be able to construct certain objects during tests. It also loads some arbitrary application properties into a static. These are usually specific to the current test suite and are to be used by numerous tests throughout the suite. My test suite would look something like this (where FrameworkResource extends ExternalResource and does a lot of bootstrap work):
#RunWith(Suite.class)
#SuiteClasses({com.example.test.MyTestCase.class})
public class MyTestSuite extends BaseTestSuite {
#ClassRule
public static FrameworkResource resource = new FrameworkResource();
#BeforeClass
public static void setup(){
loadProperties("props/suite.properties")
}
}
The above works really well and the main build has no problem executing all testsuites and their respective test cases (SuiteClasses?). The issue is when I'm in eclipse and I want to run just one test case individually withough having to run the entire suite (as part of the local development process). I would right click the java file Run As > JUnit Test and any test needing the framework resource or test properties would fail.
My question is this:
Does JUnit4 provide a solution for this problem (without duplicating the initialization code in every test case)? Can a Test Case say something like #dependsOn(MyTestSuite.class)?.
If Junit doesn't have a magic solution, is there a common design pattern that can help me here?
As you are running just one test class, a good solution would be to move the initialisation code to the test class. You would need to add the #Before annotation to initialise the properties.
That would require that you duplicate the code on all your tests classes. For resolving this, you could create an abstract parent class that has the #Before method so all the child classes have the same initialization.
Also, the initialised data could be on static variables for checking if it is already initialised for that particular execution.

How can I run particular sets of JUnit tests under specific circumstances?

I have a Java codebase that is developed exclusively in Eclipse. There
are a set of JUnit4 tests that can be divided into two mutually exclusive
subsets based on when they are expected to run:
"Standard" tests should run when a developer right-clicks the test
class (or containing project) and selects Run As > JUnit Test. Nothing
unusual here—this is exactly how JUnit works in Eclipse.
"Runtime" tests should only run when called programmatically from
within the application when it is started up in a specific state.
The two types of tests might sit adjacent to each other in the same Java
package. (Ideally we could intermix them in the same class, though
that's not a hard requirement.)
My first solution was to annotate the "Runtime" test classes with a new
#TestOnLaunch annotation. The application is able to find these classes,
and was running the tests contained in them (annotated with #Test) using
JUnitCore.run(Class<?>...). However, these tests leak into the
"Standard" scenario above, because the Eclipse test runner will run any
method annotated with #Test, regardless of the intent of my custom class
annotation.
Next I tried moving the #TestOnLaunch annotation to the method level.
This prevents the "leakage" of the "Runtime" tests into the "Standard"
scenario, but now I can't seem to get JUnitCore to run those test
methods. run.(Request) with a Request targeted at the correct class and
method, for example, fails with "No runnable methods", presumably
because it can't find the #Test annotation (because it's not there).
I'm very interested to know if there's a "JUnit way" of solving this
kind of problem. Presumably I could write my own Runner (to run methods
annotated with #TestOnLaunch)—is this the right approach? If so, how do
I then kick off the testing programmatically with a bunch of classes,
analogous to calling JUnitCore.run(Class<?>...)?
If you don't mix the two type test method in the same test class, this below may help:
http://johanneslink.net/projects/cpsuite.jsp
You can use the filter feature to setup two test suite.
I setup three test suites in my project by defining several mark interfaces:
UnitTests, IntegrationTests, DeploySmokeTests, AcceptanceTests
And three test suites:
#RunWith(ClasspathSuite.class)
#SuiteTypes({UnitTests.class, IntegrationTests.class})
public class CommitTestSuite {}
#RunWith(ClasspathSuite.class)
#SuiteTypes({DeploySmokeTests.class})
public class DeploySmokeTestSuite {}
#RunWith(ClasspathSuite.class)
#SuiteTypes({AcceptanceTests.class})
public class AcceptanceTestSuite {}
Now you could achieve your goal by running specific test suite. An alternative solution is using junit category:
#Category(IntegrationTests.class)
public class SomeTest {
#Test
public void test1() {
...
}
#Test
public void test2() {
....
}
}
#RunWith(Categories.class)
#IncludeCategory(UnitTests.class, IntegrationTests.class)
#SuiteClasses( { //all test classes })
public class CommitTestSuite {}
As I said if you mix differenct type test method in one test class, the first one can't help you, but by using the seconde solution you could annotate your category interface on test method (I annotated it on test class in the example above). But if you choose the second solution, you have to maintain your test suite every time you add a new test class.
First, you should reevaluate why you're using JUnit tests at runtime; that seems like an odd choice for a problem that probably has a better solution.
However, you should look at using a Filter to determine which tests to run, possibly in conjunction with a custom annotation.

How to make sure one testclass is executed after another

I have two test classes written using junit
TestClass1
TestClass2
If we need to ensure that TestClass2 is run only after TestClass1 in executed. How do we achieve this?
You can achieve this using the Junit test suite. When you specify the list of classes to be executed in a test suite, you're defining an array, and these test classes will be executed in order, except when you're doing parallel execution.
Note that JUnit does not guarantee the order of execution of tests within a class.

Categories