Hi John,
Below are my objectives. I have implemented such a framework based on jBehave, but I would like to abandon it and move to Cucumber/Serenity BDD.
- run multiple .feature files concurrently and generate a single report
- each thread is given its own test session; no sharing of page objects or step def instances between threads, and instances are destroyed when thread/.feature is ended
- ability to inject container-managed dependencies into page object or step defs, some dependencies being "singleton" (shared between threads) others being "threadlocal". This is where PicoContainer is helpful. For example (jBehave):
/* subclass of JUnitStories */
@Override
public List<CandidateSteps> candidateSteps() {
return new PicoStepsFactory(configuration(), getPicoContainer())
.createCandidateSteps();
}
private PicoContainer getPicoContainer() {
// root container
MutablePicoContainer top = new PicoBuilder()
.withBehaviors(new Caching()) // Singleton behavior
.withConstructorInjection()
.build();
top.addComponent(ContentDAO.class);
top.addComponent(UserDAO.class);
// child container
final ClassLoadingPicoContainer child = new ClassLoadingPicoContainer(
top.getClass().getClassLoader(),
new ThreadCaching(), // Thread-Local behavior
top);
child.addComponent(WebElementRepository.class);
// scan the classpath for step def classes
child.visit(rootName, ".*\\.class", true, new ClassLoadingPicoContainer.ClassVisitor() {
@Override
public void classFound(@SuppressWarnings("rawtypes") Class clazz) {
// concrete classes only
int mods = clazz.getModifiers();
if (Modifier.isAbstract(mods) || Modifier.isInterface(mods)) {
return;
}
// search type hierarchy to see if its a step
for (Class<?> cur = clazz; cur != null && cur != Object.class; cur = cur.getSuperclass()) {
if (cur == AbstractSteps.class) {
child.addComponent(clazz);
break;
}
}
}
});
return child;
}
/* example stepdef */
public class MySteps extends AbstractSteps {
private ContentDao contentDao; // singleton
private UserDao userDao; // singleton
private WebElementRepository repo; // threadlocal
public MySteps(ContentDAO contentDao, UserDAO userDao, WebElementRepository repo) {
this.contentDao = contentDao;
this.userDao = userDao;
this.repo = repo;
}
// ...
}
I see Serenity uses a simple declaration only approach with Guice under the hood. I would be content if this were possible given the current toolsets.
PS - could you enable post editing in this group?