Reputation: 1459
I am trying to run jbehave stories in a sequence.
My package structure for Integration tests is shown below
src/it/some/package/name/packageA/a.story
src/it/some/package/name/packageB/b.story
src/it/some/package/name/c.story
I want the story to be run in this sequence a.story, b.story, c.story
I tried using GivenStories in jBehave but they didn't seem to work (may be I am not specifying them correctly). I would very much appreciate it if someone could point to the creation of GivenStories text and also show some insight as to how jbehave creates the ordering when it runs the Integration tests because I see that running stories on my machine and on jenkins seems to be yielding different execution ordering.
Any help on this is greatly appreciated. Thanks!
Upvotes: 1
Views: 4636
Reputation: 117
The reason this happens is because JBehave runs tests in the order in which it finds them in the filesystem. To avoid this, you can extend JBehave's StoryFinder class and override findClassNames() to use an ordered list which you have stored somewhere (a properties file, build.xml, etc):
@Override
public List<String> findClassNames(String searchIn, List<String> includes, List<String> excludes) {
String[] orderedTestListArray = retrtieveTestNamesFromBuildXml();
List<String> scannedTestList = scan(searchIn, includes, excludes);
System.out.println("Scanned Test List: " + scannedTestList);
List<String> finalTestList = new ArrayList<String>();
for(String x: orderedTestListArray) {
for(String y: scannedTestList) {
if(y.contains(x))
finalTestList.add(y);
}
}
System.out.println("Final Ordered Test List: " + finalTestList);
return classNames(normalise(finalTestList));
}
In this case, I am retrieving the orderedTestListArray by parsing my ant build.xml file which includes the list of ordered tests I want to run:
private String[] retrtieveTestNamesFromBuildXml() {
String[] orderedTestListArray = null;
InputStream iStream = null;
try {
File file = new File("build.xml");
if(file.exists()) {
iStream = new FileInputStream(file);
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
Document doc = docBuilder.parse(iStream);
NodeList propertyNodes = doc.getElementsByTagName("property");
String orderedTestListString = null;
for (int i = 0; i < propertyNodes.getLength(); i++) {
Element elementNode = (Element) propertyNodes.item(i);
if(elementNode.getAttribute("name").equals("xed.tests.to.run")) {
orderedTestListString = elementNode.getAttribute("value");
break;
}
}
orderedTestListArray = orderedTestListString.split(",");
for(int i = 0; i <= orderedTestListArray.length-1; i++) {
orderedTestListArray[i] = orderedTestListArray[i].trim();
orderedTestListArray[i] = orderedTestListArray[i].substring(3, orderedTestListArray[i].length());
}
}
}
catch (Exception e) {
System.out.println("Error parsing XML info from build.xml");
e.printStackTrace();
System.exit(1);
}
finally {
try
{
if(iStream != null)
iStream.close();
}
catch (IOException e)
{
System.out.println("Error closing InputStream for build.xml");
e.printStackTrace();
}
}
return orderedTestListArray;
}
Finally, make sure you specify this new StoryFinder class while running from ant or maven as follows:
storyFinderClass=fullyQualifiedNameOfNewStoryFinderClass
Upvotes: 1
Reputation: 1459
I actually figured out a work around on this issue which i thought was much convenient than GivenStories
First i added a maven surefire configuration like this
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>${surefire.version}</version>
<configuration>
<includes>
<include>**/*TesterSequence.java</include>
</includes>
</configuration>
</plugin>
The SampleTesterSequence would be structured like the one shown below
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
@RunWith(Suite.class)
@Suite.SuiteClasses({ A.class,B.class,
C.class })
public class SampleTesterSequence {
@BeforeClass
public static void beforeStories() throws Exception {
//TODO Implement before story steps
}
@AfterClass
public static void afterStories() throws Exception {
//TODO Implement after story steps
}
}
As you can see the the suite will run the stories a,b,c in the sequence i mention with the suite, when surefire runs the tests it looks for a pattern ending with TesterSequence
and will run that class first and from that class it executes the stories we want to run in that order specified.
Upvotes: 1
Reputation: 439
Guess this response might be a bit late, but anyway. We're trying out JB also,still seems to be plenty of issues around making this work, esp for anything real world.
We have given stories working within a module, but if you try and invoke across modules (eg you have a dependent jar which holds a common story you'd like to call, then this doesn't seem to work at all).
In the same module though, make sure you place the GS entry in the right place in the story, as follows:
Story: Running BBB
GivenStories: com/xxx/test/stories/test_aaa_user.story
Given a BBB string
When I set BBB to activate
Then the BBB string is set to activate
This runs the AAA story before the BBB one.
Upvotes: 2