Skip to content

Commit

Permalink
Glossary builder, scenario setup, init class behaviour (#68)
Browse files Browse the repository at this point in the history
* fixed issue with scenario setup, feature setup still an issue #65
* modified the init class behaviour to allow explicit setup classes to be specified #67 
* fix to null pointer in the glossary builder when no step impls specified #66
  • Loading branch information
iantmoore committed Oct 8, 2017
1 parent 9d8bd0f commit 72a0fad
Show file tree
Hide file tree
Showing 9 changed files with 528 additions and 23 deletions.
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,15 @@ Requirements
------------
* Java 8

1.1.2
-----
* Initialisation classes added through config were being ignored. #67
* Updated the annotated conf example
* bug in the glossary builder, not excluded classnames in the config resulted in a null pointer. #66
* failure in scenario setup methods results in missing results data and report building failure. #65



1.1.1
-----
* Prevent duplicate step implementations being created in the glossary json file. Fixes #62
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,13 @@ public RootNode prepareExecutionConfig(final Config config , final Syntax syntax

public static Class<?>[] buildInitialisationClassList(List<Class<?>> stepImplClassList, List<Class<?>> initialisationClassList){

List<Class<?>> finalInitialisationClassList = null;
List<Class<?>> finalInitialisationClassList = new ArrayList<>();

// add the explicitly set init class list at the front
if (initialisationClassList != null){
finalInitialisationClassList.addAll(initialisationClassList);
}

if (stepImplClassList != null) {

final InitialisationClassSorter orderer = new InitialisationClassSorter();
Expand All @@ -126,14 +132,10 @@ public static Class<?>[] buildInitialisationClassList(List<Class<?>> stepImplCla
}
}
}

finalInitialisationClassList = orderer.getOrderedList();
}
if (finalInitialisationClassList == null && initialisationClassList != null) {
finalInitialisationClassList = initialisationClassList;
finalInitialisationClassList.addAll(orderer.getOrderedList());
}

if (finalInitialisationClassList != null) {
if (!finalInitialisationClassList.isEmpty()) {
return finalInitialisationClassList.toArray(new Class<?>[]{});
}
else {
Expand Down Expand Up @@ -325,12 +327,13 @@ private void addToCallHierarchy(final IExecutionNode node) {
log.trace("no uses already for node...");
immediateParents = new ArrayList<ExecutionNodeUsage>();
callerHierarchy.put(usage, immediateParents);
} else {
log.trace("got existing usages of node: ");
for (final ExecutionNodeUsage u : immediateParents) {
log.trace("already found: " + u.toString());
}
}
// else {
// log.trace("got existing usages of node: ");
// for (final ExecutionNodeUsage u : immediateParents) {
// log.trace("already found: " + u.toString());
// }
// }
log.trace("adding used by descr: " + node.getParent().getDescription() + " line: " + node.getParent().getLine());

immediateParents.add(new ExecutionNodeUsage(node.getParent()));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,8 @@ private boolean runSetup(final NODE_TYPE node, final RootNodeExecutionContext co

log.warn("setup failed", t);
context.addFailure(new SubstepExecutionFailure(t, node, true));
context.getNotificationDistributor().onNodeFailed(node, t);

return false;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,11 @@ class ExecutionResultsCollector extends IExecutionResultsCollector {
Files.write(generateJson(rootNode), summaryFile, UTF8)
}

case _ => log.debug("other node failed")
case n => {

// outlinescenariorownode
log.warn("other node failed " + node.getClass + " id: " + n.getId)
}
}

}
Expand Down Expand Up @@ -214,10 +218,10 @@ class ExecutionResultsCollector extends IExecutionResultsCollector {

}
case stepImplNode : StepImplementationNode => {
log.debug("stepImpl Node finished")
log.debug(s"stepImpl ${stepImplNode.getId} Node finished")

}
case _ => log.debug("other node finished")
case n => log.debug(s"other node ${n.getId} finished")
}

}
Expand Down Expand Up @@ -307,14 +311,17 @@ class ExecutionResultsCollector extends IExecutionResultsCollector {


basicScenarioNodes.map(outlineScenario => {

println("failing outlineScenario.getId: " + outlineScenario.getId)

val (sNode, resultsFile) = scenarioSummaryMap.get(outlineScenario.getId).get

ScenarioSummary(sNode.getId, resultsFile.getName, sNode.getResult.getResult.toString, sNode.getTags.toList)

})
}
case other => {
log.error("had another child type: " + other.getClass)
log.error("had another child type: " + other.getClass + " other id: " + other.getId)
List()
}
}
Expand Down Expand Up @@ -444,8 +451,13 @@ class ExecutionResultsCollector extends IExecutionResultsCollector {
featureNode.getId -> featureResultsDir
}).toMap
}



}



case class FeatureSummary(nodeType: String, filename: String, result : String, id : Long,
executionDurationMillis : Option[Long], description : String, scenarios: List[ScenarioSummary], tags : List[String])

Expand All @@ -458,6 +470,36 @@ case class RootNodeSummary(nodeType: String, description: String, result : Strin
executionDurationMillis : Option[Long], features : List[FeatureSummaryForRootNode], tags : Option[String], nonFatalTags : Option[String], timestamp : Long, environment : String)


case class SubstepsNode(id : Long, nodeType: String, description: String, children : List[SubstepsNode])

// TODO - build a new node up, look at the akkaruner2. build up a new hierarchy
// utils class to build up new model - could use the same model for running with, convert the runner, listener and notifier... more big changes

//object SubstepsNode {
//
// def toSubstepNodeTree(rootNode: NodeWithChildren, nodeType = "RootNode") : SubstepsNode= {
//
// val children = rootNode.getChildren
//
// val substepNodeChildren =
// if (children == null) List() else {
//
// val childList = children.asScala.toList
// childList.map(c => {
// toSubstepNodeTree(c)
// })
// }
// SubstepsNode(rootNode.getId, nodeType, rootNode.getDescription, substepNodeChildren)
// }
//
// def toSubstepNodeTree(featureNode: FeatureNode) : SubstepsNode = {
// ???
// }
//
//}



import scala.collection.JavaConverters._


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import java.util.Arrays;
import java.util.List;

import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.is;

/**
Expand Down Expand Up @@ -213,6 +214,28 @@ public void testDermineClassesForTPCLA223() {
System.out.println(initialisationClasses);
}

@Test
public void testInitialisationClassesInStepImplsAndExplicit(){

final List<Class<?>> stepImplClasses = new ArrayList<Class<?>>();

stepImplClasses.add(StepImplsClass2_5_6.class);

final List<Class<?>> explicitInitClasses = new ArrayList<>();
explicitInitClasses.add(InitClass3.class);


final List<Class<?>> initialisationClasses = Arrays.asList(ExecutionNodeRunner.buildInitialisationClassList(stepImplClasses, explicitInitClasses));

Assert.assertThat(initialisationClasses.size(), is(4));

Assert.assertThat(initialisationClasses.get(0), equalTo(InitClass3.class));
Assert.assertThat(initialisationClasses.get(1), equalTo(InitClass2.class));
Assert.assertThat(initialisationClasses.get(2), equalTo(InitClass5.class));
Assert.assertThat(initialisationClasses.get(3), equalTo(InitClass6.class));

}

@Test(expected = SubstepsConfigurationException.class)
public void testDetermineClassesForInvalidLoop() {

Expand Down
10 changes: 10 additions & 0 deletions core/src/test/resources/annotated.conf
Original file line number Diff line number Diff line change
Expand Up @@ -75,18 +75,28 @@ org.substeps.baseExecutionConfig {
// set of listeners that receive test started / passed / failed events
"com.technophobia.substeps.runner.logger.StepExecutionLogger"
]

fastFailParseErrors=true
// if true, parse failures of all scenarios and substeps result in immediate termination.
// During development it may be beneficial to relax this. Parse errors found during execution are
// still treated as an error

featureFile="target/test-classes/features"
// path to a directory of feature files or a specific feature file

substepsFile="target/test-classes/substeps"
// path to a directory of substep definition files or a specific one


// array of step implentation classes in scope for this test
stepImplementationClassNames=[
"com.org.my.StepImplementations"
]

// initialisation classes to be used in addition to any required initialisation classes referenced in the step impls above
initialisationClasses=[
"com.org.my.SetupAndTearDown"
]
}


Expand Down
Loading

0 comments on commit 72a0fad

Please sign in to comment.