0

I got a lot of different flows which are resuing moduls. Like this Flow1 = M1->M2->M3->M5 or Flow2 = M1->M2->M4->M6->M3->M5.

Now I want to write a testCase for each modul to shorten the time of testdevelopement and then combine those cases to test the flow. Those tests all need an initial setup, sometimes other paramters and certain informations should be carried through the flow. How can I insert them into the testmodul without hardcoding them into the model since they should be changeable for reuse. Since testcases do not support constructors and parameterized test cases are not what I am looking for.

So not like Running the same JUnit test case multiple time with different data but Running differen JUnit test cases with the same source of data.

Is it possible to do that or am I on the wrong track?

If anything is unclear please ask. I'd really appreciate help.

Greetings Tarken

Community
  • 1
  • 1
Tarken
  • 2,112
  • 2
  • 23
  • 42

2 Answers2

1

Let's see if I understand your problem correctly. You would like to define a test for M1 (testM1), a test for M2 (testM2) a test for M3 (testM3) etc. You would then like to test the combination of M1->M2->M3 by calling all of the test methods testM1, testM2, testM3 in order, but passing some arbitrary data between those methods. So testM1 gets called, and it produces some data which gets passed to testM2, which produces data which gets passed to testM3. The solution below is designed for this, but can easily be extended to include classes.

There are two ways of doing this. The easiest is to define a @Rule in your classes which gets the context stored in a static field in the Suite class and updates it. If you extend ExternalResource, you can do something like:

private Context context;

@Rule
public ExternalResource resource= new ExternalResource() {
    @Override
    protected void before() throws Throwable {
        // get context from Suite class
        context = MySuite.getContext();
    };

    @Override
    protected void after() {
        // put context into Suite class
        MySuite.setContext(context);
    };
};

Your methods would then use that context as normal. This would work in most cases, but creates a dependance from the test to a particular MySuite class.

The more complex option

You can do this using a custom @Suite class with a customer Runner. My answer to How to define JUnit method rule in a suite? shows how to execute custom code before and after a particular method (in that case one with a @depcrecated annotation).

You would need to do something similar. So your Suite would create the context for the test, and before executing a particular test method, the runner retrieves the context from the suite, calls a setter in the test class. The test method uses that context, returns and the runner retrieves the context from the test class and updates the suite class. The obvious place to store the context would be the suite, since the test classes themselves are created each time. I think it's too much work to try and pass the context in as a parameter, you'd have to change a lot more code.

So in your Runner, you would have something like

public class MyRunner extends BlockJUnit4ClassRunner {
    private MySuite suite;

    public MyRunner(Class<?> klass, MySuite suite) throws InitializationError {
        super(klass);
        this.suite = suite;
    }

    @Override
    protected void runChild(final FrameworkMethod method, RunNotifier notifier) {
        Description description= describeChild(method);
        if (method.getAnnotation(Ignore.class) != null) {
            notifier.fireTestIgnored(description);
        } else {
            // call suite.getContext()
            // call setContext() in class
            runLeaf(methodBlock(method), description, notifier);
            // call getContext() in class
            // call suite.setContext()
        }
    }
}

It is possible to override the beforeclass behaviour as well.

Community
  • 1
  • 1
Matthew Farwell
  • 60,889
  • 18
  • 128
  • 171
  • Thx Matthew this looks really promising for transfering my information. I ll try that. – Tarken Nov 04 '11 at 10:45
  • You need the "@Rule" so that JUnit runs the code before and after each method. Think of it as a generic way of defining a "@Before" and "@After" method. You can use the same Rule between classes without code duplication. You can also chain them by using RuleChain. You can configure the Context in the tests by simply adding the configuration code to a no-argument constructor. – Matthew Farwell Nov 04 '11 at 11:07
-1

Use BeforeClass.

Valentin Rocher
  • 11,667
  • 45
  • 59
  • That doesnt help the question how to transport the information. I know where to put it. The question is how to get it there. – Tarken Nov 04 '11 at 09:50