Run TestCase from java and display results on Eclipse JUnit view - java

I defined some classes with, each one, several public methods with #Test annotation. All methods follow the same behavioral pattern (retrieve ressources from IDs, test if empty, log, call the real test for each line on the resource). So, I've externalized this behavior in an abstract class I instanciate on each method, like this:
#Test
public void someTest(){
new BasicTestPattern("X","Y","Z"){ // some parameters to retrieve resources
#Override
protected void testLine(){
someCheck1();
someCheck2();
}
}.run();
}
This solution eliminate 10-30 lines per test method.
Now, I want to go further with a custom annotation, like that:
#TestPattern(param1="X",param2="Y",param3="Z")
public void someTest(){
someCheck1();
someCheck2();
}
Finally I created a little framework to retrieve all the methods with this new annotation in order to instanciate BasicTestPattern and execute it. It is executed well in a TestCase subclass, like that:
TestCase junit_test = new TestCase(){
#Override
public void runTest() {
pattern.run();
}
};
junit_test.run();
However, no Test is displayed/listed in the JUnit view from Eclipse. I see only the number of tests succeeded.
How can I do that ? Thank you.

You probably will need to make your own custom Runner to find all the methods annotated with your #TestPattern method. (and probably also with #Test ?)
Then your test class will look like this:
#RunWith(YourRunner.class)
public class YourTest{
#TestPattern(param1="X",param2="Y",param3="Z")
public void someTest(){
...
}
#Test
public void anotherNormalTest(){
...
}
}
This Blog explains how to write custom Runners. But you can probably get away with extending BlockJUnit4ClassRunner to add the your special test methods to the list of tests to run.
I think you would only have to override the computeTestMethods() method which is how BlockJUnit4ClassRunner finds all the test methods to run (the methods annotated with #Test) you can override it to find the methods you annotated with your own annotation.
public class your TestRunner extends BlockJUnit4ClassRunner{
protected List<FrameworkMethod> computeTestMethods() {
//this is all the #Test annotated methods
List<FrameworkMethod> testAnnotatedMethods = super.computeTestMethods();
//these are all the methods with your #TestPattern annotation
List<FrameworkMethod> yourAnnotatedMethods = getTestClass().getAnnotatedMethods(TestPattern.class);
//do whatever you need to do to generate the test
//methods with the correct parameters based on
//the annotation ?
//Might need to make fake or
//synthetic FrameworkMethod instances?
...
//combine everyting into a single List
List<FrameworkMethod> allTestMethods =...
//finally return all the FrameworkMethods as a single list
return allTestMethods;
}
}
You might have to make your own FrameworkMethod implementation wrapper to get the info from the annotation and do whatever set up is required before invoking the method.
This will make it seamlessly integrate with normal JUnit classes and work with the JUnit IDE view
Good Luck

Related

How to have multiple setups for different sets of JUnit Tests?

I have just started learning JUnit very recently and came across the following problem.
Have a look at the following class
class MyClass {
String a;
public MyClass(String a) {
this.a=a;
String doSomething(String a) {
if( a.isEmpty() )
return "isEmpty";
else
return"isNotEmpty";
}
I want to test the above method for both the conditions. If I proceed with the general structure of writing testcases it will look something like this:
class MyClassTest {
MyClass myClass;
#BeforeEach
void setUp() {
myClass=new MyClass("sampleString");
}
#Test
void doSomethingTest() {
Assertions.equal("isNotEmpty", myClass.doSomething());
}
}
However, for testing the empty string condition I will need another setup method where instead of "sampleString" I pass an empty string.
Following are the approaches I could think of and the questions for each:
Not use setUp at all and instead initialize the class in the individual test method. However, if let's say there are 10 testcases; 5 of which require empty string and rest "sampleString" then this doesn't make sense. Again, we can have a separate method for this repetitive code and call it individually in each testcase but then that defeats the purpose of having a steup method. Lets say I wanted to use two different setup methods, is there a way to do so?
Have a parameterized setup. I don't know if this is possible though. If yes, please share some useful links for this.
Use TestFactory. I tried reading up about this, but couldn't find an example for this specific case. If you have any, please share.
This example has been kept simple for illustrative purposes.
Group the tests with the same setup in an inner class annotated with #Nested. Each nested test class can have its own setup in a local #BeforeEach method.
You can always prepare the non-common data inside your test method. I've always thought it's easier this way, compared to using parameterized tests. You can't mix parameterized and non-parameterized tests in 1 file.
#Test
void doSomething_nullString()
{
myClass = new MyClass(null);
Assert.assertNull(myClass.doSomething());
}
#Test
void doSomething_emptyString()
{
myClass = new MyClass("");
Assert.assertEquals("", myClass.doSomething());
}
#Test
void doSomething_nonEmptyString()
{
myClass = new MyClass("sampleString");
Assert.assertEquals("sampleString", myClass.doSomething());
}
Or, you can always have helper methods inside the test class.
private MyClass createTestObject_nonNullString() {
return new MyClass("nonNullString");
}
private MyClass createTestObject_nullString() {
return new MyClass(null);
}
#Test
public void doSomething_sample() {
MyClass test = createTestObject_nonNullString();
// perform test
}

Get current class test methods before class started in TestNG

I would like to get a list of test methods from the current test class before it is started. When I tried to extend TestListenerAdapter for this, testContext.getAllTestMethods() returned all test methods from all classes. But how to get only methods from the current class?
I found a partial answer on the question. First of all, I can get all test methods by extending TestListenerAdapter
public class MyListener extends TestListenerAdapter {
#Override
public void onStart(ITestContext testContext) {
super.onStart(testContext);
ITestNGMethod[] methods = testContext.getAllTestMethods();
// here we can save methods into some object
}
Then, in our test class in #BeforeClass() we can access the object and get the only methods from the this.getClass().getName() class. So, we filter the only methods from the current class. In this case we can access all required information like description and other important test attributes.
If you don't have a listener, you can also use the #BeforeClass annotation similar way as specified by OP's own answer:
#BeforeClass
public void setup(ITestContext context) {
for (ITestNGMethod method : context.getAllTestMethods()) {
if(method.getRealClass() == this.getClass()) {
// do what you have to do
}
}
}

JUnit4 Run A method After Some Methods?

I have a method that is not a regular test method. It is a cleanup method. I want to run it after some methods (some methods that are not test methods but are called from some test methods ).
How can do that using JUnit4?
PS: After and AfterClass are not a choice. I want to run a method after "some" non test methods (some methods that are called within test methods).
have you tried #AfterClass And #After ,#Before ,#BeforeClass ?
for the case of #AfterClass your method should be static .
in these case your method would be launched once before all the Tests.
check this link.
junit-beforeclass-and-afterclass-behavior-in-case-of-multiple-test-cases
You will need to call those methods manually or through AOP if you are using Spring.
You could use a TestWatcher to listen to when the test has finished, & check the test-name to see if your code should be ran. E.g.:
#Rule
public TestRule runFooSomtimes = new TestWatcher() {
public void foo() {
//do stuff here
}
List<String> methodsToCheck = new ArrayList<String>() {{
add("testMethodOne");
}}
#Override
protected void finished(Description description) {
if(methodsToCheck.contains(description.getMethodName())) {
foo();
}
}
};
(Excuse any errors, away from an IDE at the moment, but should give an idea.)

Get method invocated inside a method in Java

I want to make a JUnit test to assure that some classes don't use a specific set of methods (from another classes). Example
class MyClass
{
void myMethod()
{
otherClass.otherClassStaticMethod();
}
}
class myTest
{
void test()
{
assertFalse(CalledMethods.getMethodsCalledBy("myClass.myMethod").Contains("otherClass.otherClassStaticMethod"));
}
}
In this test I want to assure that myMethod doesn't invocate otherClassStaticMethod. How can I find what methods are being called inside a method in compile time (ignore methods called using reflection)? I thought about a .java parser, do you recommend any?
you can mock "otherClass" and verify that the method isn't invoked. E.g. using Mockito you can even specify in which order what methods are supposed to be invoked (under the condition their instances are mocks) and specify which methods are not allowed to be invoked
as coding.mof said, to mock static methods you should use PowerMock/PowerMockito:
example:
PowerMockito.mockStatic(OtherClass.class);
PowerMockito.verifyStatic(never());
OtherClass.otherClassStaticMethod();
It sounds like you should be using a mock library and let that handle it all for you. I'd recommend JMock as my library of choice. If you're using instance methods then this would be perfect for you - if, as your example shows, it's static methods then PowerMock may work*1.
With JMock, you'd have something like:
public class MyClass {
public MyClass(Dependency dependency) {
this.dependency = dependency;
}
void myMethod() {
dependency.someMethod();
}
}
#RunWith(JMock.class)
public class MyTest {
private Mockery context = new Mockery();
#Test
public void doesNotCallSomeMethod() {
Dependency dependency = context.mock(Dependency.class);
MyClass obj = new MyClass(dependency);
obj.myMethod(); <--- this will fail fast
}
}
When you call obj.myMethod, JMock will instantly report that you never said dependency should have any methods called. It will also tell you what method you DID call and what parameters you passed in if any
*1 I don't use PowerMock as I steer away from static methods unless they are pure functions

How to run some code before each JUnit #Test method individually, without using #RunWith nor AOP?

use case is simple: I want to run some boiler plate code before each method in JUnit test annotated with #Test and my custom annotation (let's call it #Mine).
I do not want to use following methods (explanation in parenthesis):
#RunWith (my test may, or may not use this annotation already, so I cannot assume that I will be able to use my own runner)
AOP (I cannot make any dependencies to third party libraries, such as AspectJ)
I guess this leaves me with reflection only, which is fine by me. I thought off using #Before accompanied with getting current method via Thread.getCurrentThread() etc. but somehow I find this solution to be a little bit dirty, since I would have to make boiler plate code again within this method to fire reflection (and avoiding any unnecessary code was the goal in the first place).
Maybe you have some other ideas?
You need a solution very similar to the answer to Mark unit test as an expected failure, based upon a TestRule. Using the example of a #Deprecated annotation (you can use yours here), you can insert code if the annotation exists on the method. The Description class contains the list of annotations on the method.
public class ExecutionTest {
public class BeforeExecution implements TestRule {
public Statement apply(Statement base, Description description) {
return statement(base, description);
}
private Statement statement(final Statement base, final Description description) {
return new Statement() {
#Override
public void evaluate() throws Throwable {
if (description.getAnnotation(Deprecated.class) != null) {
// you can do whatever you like here.
System.err.println("this will be run when the method has an #Deprecated annotation");
}
base.evaluate();
}
};
}
}
#Rule public BeforeExecution beforeExecution = new BeforeExecution();
// Will have code executed.
#Deprecated
#Test public void test1() {
// stuff
}
// won't have code executed.
#Test public void test2() {
// stuff
}
}
I would split the class into two. One with the methods you would have annotated with #mine and one for the others.
Then use #before as normal.
This adds no none standard code and will be easy to understand and maintain for future developers as well.

Categories