1

I wrote a set of feature files for testing a custom framework and I want to allow testing of specific implementations of the interfaces of the framework. I want to run a whole lot of features with different implementations.

To do that, I have created a custom ObjectFactory and passing implementations using PicoContainer dependency injection. I added this factory to a cucumber.properties file and it works just fine. The only problem is - what if I have more than one set of implementations to test?

I can create several ObjectFactories, but how can I run the tests multiple times with different factories? Is it possible to pass ObjectFactory implementation to Runner class, using annotation or something alike? I run features with JUnit runner, and if I can have several of them with different factories, it should work, I think. However the only option to specify ObjectFactory I've found is cucumber.options file which is one for a module...

Tatiana Goretskaya
  • 536
  • 10
  • 25

2 Answers2

2

Currently it is not possible to use multiple object factories in Cucumber. As a work around you could implement a single object factory that delegates to a different object factory depending on some environment variable.

You may also want to consider using cucumber-spring instead of cucumber-pico as cucumber-spring can pick up springs context configuration annotations from step definitions. This can be done with minimal configuration if you structure your project like this:

 | - runners 
 | | - CucumberConfigATest.java // @CucumberOptions(glue="steps", extraGlue="config.a") 
 | | - CucumberConfigBTest.java // @CucumberOptions(glue="steps", extraGlue="config.b")
 | - steps
 | | - SomeSteps.java
 | | - MoreSteps.java
 | - config
 | | - a
 | | | - StepsWithContextConfigA.java
 | | - b
 | | | - StepsWithContextConfigB.java
M.P. Korstanje
  • 10,426
  • 3
  • 36
  • 58
  • 1
    I came to the same idea with env variable and a factory. Unfortunately, I don't have time to experiment with cucumber-spring, otherwise I'd rather go with this way - it looks a lot cleaner. – Tatiana Goretskaya Mar 06 '19 at 19:54
1

@mpkorstanje provided an answer I came up with as well. In case someone needs an example of implementation - here it is:

@RunWith(Cucumber.class)
@CucumberOptions(features="src/test/resources")
public class MyRunner {

    @BeforeClass
    public static void setup(){
        System.setProperty(EventProcessorPicoFactory.EVENT_BUS_HANDLER, IUserECNDataHandler.class.getName());
    }

}

public class MyFactory {
    public MyObject build() {
        String type = System.getProperty("my.property.name");
        switch (type) {
            case  "my.value":
                return new MyObject();
            default:
                throw new IllegalArgumentException("not implemented");
            }
        }   

    }
Tatiana Goretskaya
  • 536
  • 10
  • 25
  • 1
    Cucumber also supports JUnits before and after class annotations. You don't need to exetend Cucumber. If you are on a recent version of it anyway (I think > 2.0.0). – M.P. Korstanje Mar 06 '19 at 20:34
  • I meant rather @BeforeClass, but thanks, I wasn't realizing I can use it in there. Tried to put it into initialization block, but it seemed to be never called - I guess, I need to learn more on how JUnit instantiates test classes – Tatiana Goretskaya Mar 07 '19 at 17:36
  • The initialization is runner dependent. The Cucumber runner doesn't instantiate the test class. – M.P. Korstanje Mar 07 '19 at 22:14
  • Looks like I was mistaken though. Cucumber currently invokes @BeforeClass rather well after booting up the object factory. This is a bug in the implementation. – M.P. Korstanje Mar 08 '19 at 02:44