First of all - what is JBehave ? About that, it's better to read from it original site : http://jbehave.org/ :
JBehave is a framework for Behaviour-Driven Development (BDD). BDD is an evolution of test-driven development (TDD) and acceptance-test driven design, and is intended to make these practices more accessible and intuitive to newcomers and experts alike. It shifts the vocabulary from being test-based to behaviour-based, and positions itself as a design philosophy.
In shorts, it's addon for JUnit,which is giving possibilities to make testing process more transparent to business(non-developer) users. For example, with JBehave we can write test descriptions in plain text (.story) files.
Component of my application:
Active MQ getting started -1: Producer/Consumer(Sender/Receiver)
So, I want to re-write my JUnit tests using JBehave.
My test cases :
1. Producer/Consumer : simple test, 1 message have to be received by 1 Consumer.
2. Producer/Consumer : multiple test, with several consumers of one queue, 1 message have to be received by only 1 Consumer.
3. Publisher/Subscriber : all subscribers of topic have to receive the message.
From jbehave.com:
Behaviour-Driven Development encourages you to start defining the stories via scenarios that express the desired behaviour in a textual format, e.g.:
The textual scenario should use the language of the business
domain and shield away as much as possible the details of the technical
implementation. Also, it should be given a name that is expressive of
the functionality that is being verified, i.e. trader_is_alerted_of_status.story.
So,let's re-write our test cases from above,to "stories" syntax.
For that I created 2 files in test/resource directory: ProducerConsumer.story and PublisherSubscriber.story. In these files, I have to re-formulate test cases,using BDD syntax(Scenario, Give, When, Then).
My test stories files:
ProducerConsumer.story :
PublisherSubscriber.story:
ProducesConsumerJB:
PublisherSubscriberJB:
I copy/pasted it from one of examples from jbehave site.
My output after run:
Processing system properties {}
Using controls EmbedderControls[batch=false,skip=false,generateViewAfterStories=true,ignoreFailureInStories=true,ignoreFailureInView=true,verboseFailures=false,verboseFiltering=false,storyTimeoutInSecs=60,failOnStoryTimeout=false,threads=1]
(BeforeStories)
Running story ProducerConsumer.story
(ProducerConsumer.story)
Scenario: simple message receiving by one consumer
Given one producer, one consumer, one message (PENDING)
When producer sends message to queue (PENDING)
Then consumer receives message from queue (PENDING)
@Given("one producer, one consumer, one message")
@Pending
public void givenOneProducerOneConsumerOneMessage() {
// PENDING
}
@When("producer sends message to queue")
@Pending
public void whenProducerSendsMessageToQueue() {
// PENDING
}
@Then("consumer receives message from queue")
@Pending
public void thenConsumerReceivesMessageFromQueue() {
// PENDING
}
Scenario: simple message receiving by several consumers:only one of them have to receive message
Given one producer, several consumers, one message (PENDING)
When producer sends message to queue (PENDING)
Then only one consumer have to receive message from queue (PENDING)
@Given("one producer, several consumers, one message")
@Pending
public void givenOneProducerSeveralConsumersOneMessage() {
// PENDING
}
@When("producer sends message to queue")
@Pending
public void whenProducerSendsMessageToQueue() {
// PENDING
}
@Then("only one consumer have to receive message from queue")
@Pending
public void thenOnlyOneConsumerHaveToReceiveMessageFromQueue() {
// PENDING
}
Running story PublisherSubscriber.story
(PublisherSubscriber.story)
Scenario: broadcast message receiving by all subscribers of topic
Given one publisher, several subscribers, one message (PENDING)
When publisher sends message (PENDING)
Then all subscribers have to receive this message (PENDING)
@Given("one publisher, several subscribers, one message")
@Pending
public void givenOnePublisherSeveralSubscribersOneMessage() {
// PENDING
}
@When("publisher sends message")
@Pending
public void whenPublisherSendsMessage() {
Processing system properties {}
Using controls EmbedderControls[batch=false,skip=false,generateViewAfterStories=true,ignoreFailureInStories=true,ignoreFailureInView=true,verboseFailures=false,verboseFiltering=false,storyTimeoutInSecs=60,failOnStoryTimeout=false,threads=1]
(BeforeStories)
Running story ProducerConsumer.story
(ProducerConsumer.story)
Scenario: simple message receiving by one consumer
Given one producer, one consumer, one message (PENDING)
When producer sends message to queue (PENDING)
Then consumer receives message from queue (PENDING)
@Given("one producer, one consumer, one message")
@Pending
public void givenOneProducerOneConsumerOneMessage() {
// PENDING
}
@When("producer sends message to queue")
@Pending
public void whenProducerSendsMessageToQueue() {
// PENDING
}
@Then("consumer receives message from queue")
@Pending
public void thenConsumerReceivesMessageFromQueue() {
// PENDING
}
Scenario: simple message receiving by several consumers:only one of them have to receive message
Given one producer, several consumers, one message (PENDING)
When producer sends message to queue (PENDING)
Then only one consumer have to receive message from queue (PENDING)
@Given("one producer, several consumers, one message")
@Pending
public void givenOneProducerSeveralConsumersOneMessage() {
// PENDING
}
@When("producer sends message to queue")
@Pending
public void whenProducerSendsMessageToQueue() {
// PENDING
}
@Then("only one consumer have to receive message from queue")
@Pending
public void thenOnlyOneConsumerHaveToReceiveMessageFromQueue() {
// PENDING
}
Running story PublisherSubscriber.story
(PublisherSubscriber.story)
Scenario: broadcast message receiving by all subscribers of topic
Given one publisher, several subscribers, one message (PENDING)
When publisher sends message (PENDING)
Then all subscribers have to receive this message (PENDING)
@Given("one publisher, several subscribers, one message")
@Pending
public void givenOnePublisherSeveralSubscribersOneMessage() {
// PENDING
}
@When("publisher sends message")
@Pending
public void whenPublisherSendsMessage() {
// PENDING
}
@Then("all subscribers have to receive this message")
@Pending
public void thenAllSubscribersHaveToReceiveThisMessage() {
// PENDING
}
(AfterStories) // PENDING
}
@Then("all subscribers have to receive this message")
@Pending
public void thenAllSubscribersHaveToReceiveThisMessage() {
// PENDING
}
(AfterStories)
Everything looks good: jbehave found both .story files and even generated for us "mockup"(function definitions) of future implementation!
So, we can copy/paste function definitions to our test classes in to"fill"(implement) them.
My results :
Running story ProducerConsumer.story
(ProducerConsumer.story)
Scenario: simple message receiving by one consumer
log4j:WARN No appenders could be found for logger (org.apache.activemq.transport.WireFormatNegotiator).
log4j:WARN Please initialize the log4j system properly.
Given one producer, one consumer, one message
Sending message:com.demien.amq.TestObject@807bbc
Consumer[THE_ONLY_CONSUMER] Message received:
When producer sends message to queue
Then consumer receives message from queue
Scenario: simple message receiving by several consumers:only one of them have to receive message
Given one producer, several consumers, one message
Sending message:com.demien.amq.TestObject@7b0aef
Consumer[Consumer#0] Message received:
When producer sends message to queue
Then only one consumer have to receive message from queue
Running story PublisherSubscriber.story
(PublisherSubscriber.story)
Scenario: broadcast message receiving by all subscribers of topic
Given one publisher, several subscribers, one message
Subscriber[0] received message.
Subscriber[3] received message.
Subscriber[4] received message.
Subscriber[1] received message.
Subscriber[2] received message.
Subscriber[7] received message.
Subscriber[6] received message.
Subscriber[9] received message.
Subscriber[5] received message.
Subscriber[8] received message.
When publisher sends message
Then all subscribers have to receive this message
As we can see, result are very easy for understanding even for users which are not related with development. Also Jbehave can generate very beautiful html tables with results (whey are located in /target/jbehave directory) such as :
Full source code could be downloaded from here.
JBehave is a framework for Behaviour-Driven Development (BDD). BDD is an evolution of test-driven development (TDD) and acceptance-test driven design, and is intended to make these practices more accessible and intuitive to newcomers and experts alike. It shifts the vocabulary from being test-based to behaviour-based, and positions itself as a design philosophy.
In shorts, it's addon for JUnit,which is giving possibilities to make testing process more transparent to business(non-developer) users. For example, with JBehave we can write test descriptions in plain text (.story) files.
0. Goal.
As a developer , I want to test my ActiveMQ application using BDD methodology.Component of my application:
Active MQ getting started -1: Producer/Consumer(Sender/Receiver)
So, I want to re-write my JUnit tests using JBehave.
My test cases :
1. Producer/Consumer : simple test, 1 message have to be received by 1 Consumer.
2. Producer/Consumer : multiple test, with several consumers of one queue, 1 message have to be received by only 1 Consumer.
3. Publisher/Subscriber : all subscribers of topic have to receive the message.
1. Stories
What is "story"?From jbehave.com:
Behaviour-Driven Development encourages you to start defining the stories via scenarios that express the desired behaviour in a textual format, e.g.:
Given a stock of symbol STK1 and a threshold of 10.0 When the stock is traded at 5.0 Then the alert status should be OFF |
So,let's re-write our test cases from above,to "stories" syntax.
For that I created 2 files in test/resource directory: ProducerConsumer.story and PublisherSubscriber.story. In these files, I have to re-formulate test cases,using BDD syntax(Scenario, Give, When, Then).
My test stories files:
ProducerConsumer.story :
Scenario: simple message receiving by one consumer Given one producer, one consumer, one message When producer sends message to queue Then consumer receives message from queue Scenario: simple message receiving by several consumers:only one of them have to receive message Given one producer, several consumers, one message When producer sends message to queue Then only one consumer have to receive message from queue
PublisherSubscriber.story:
Scenario: broadcast message receiving by all subscribers of topic Given one publisher, several subscribers, one message When publisher sends message Then all subscribers have to receive this message
2. Test classes
Now we need JUnit tests which have to cover our stories. I created 2 files (each for each story file) : PublisherSubscriberJB and ProducesConsumerJB. They are empty now, we will implement them later.ProducesConsumerJB:
package com.demien.amq.jbehave; /** * Created by dmitry on 14.02.15. */ public class ProducerConsumerJB { }
PublisherSubscriberJB:
package com.demien.amq.jbehave; /** * Created by dmitry on 09.02.15. */ public class PublisherSubscriberJB { }
3. JBehave runner.
As I mentioned before, JBehave - addon on JUnit. So, we have to create jbehave-runner file,which will make our JUnit tests consider our stories files.I copy/pasted it from one of examples from jbehave site.
package com.demien.amq.jbehave; import org.jbehave.core.Embeddable; import org.jbehave.core.configuration.Configuration; import org.jbehave.core.configuration.MostUsefulConfiguration; import org.jbehave.core.i18n.LocalizedKeywords; import org.jbehave.core.io.LoadFromClasspath; import org.jbehave.core.io.StoryFinder; import org.jbehave.core.junit.JUnitStories; import org.jbehave.core.model.ExamplesTableFactory; import org.jbehave.core.parsers.RegexStoryParser; import org.jbehave.core.reporters.StoryReporterBuilder; import org.jbehave.core.steps.InjectableStepsFactory; import org.jbehave.core.steps.InstanceStepsFactory; import org.jbehave.core.steps.ParameterConverters; import java.text.SimpleDateFormat; import java.util.List; import static org.jbehave.core.io.CodeLocations.codeLocationFromClass; import static org.jbehave.core.reporters.Format.CONSOLE; import static org.jbehave.core.reporters.Format.HTML; import static org.jbehave.core.reporters.Format.TXT; import static org.jbehave.core.reporters.Format.XML; /** * Created by dmitry on 09.02.15. */ public class JBehaveRunner extends JUnitStories { public JBehaveRunner() { configuredEmbedder().embedderControls().doGenerateViewAfterStories(true).doIgnoreFailureInStories(true) .doIgnoreFailureInView(true).useThreads(1).useStoryTimeoutInSecs(60); } @Override public Configuration configuration() { Class<? extends Embeddable> embeddableClass = this.getClass(); // Start from default ParameterConverters instance ParameterConverters parameterConverters = new ParameterConverters(); // factory to allow parameter conversion and loading from external resources (used by StoryParser too) ExamplesTableFactory examplesTableFactory = new ExamplesTableFactory(new LocalizedKeywords(), new LoadFromClasspath(embeddableClass), parameterConverters); // add custom converters parameterConverters.addConverters(new ParameterConverters.DateConverter(new SimpleDateFormat("yyyy-MM-dd")), new ParameterConverters.ExamplesTableConverter(examplesTableFactory)); return new MostUsefulConfiguration() .useStoryLoader(new LoadFromClasspath(embeddableClass)) .useStoryParser(new RegexStoryParser(examplesTableFactory)) .useStoryReporterBuilder(new StoryReporterBuilder() .withCodeLocation(codeLocationFromClass(embeddableClass)) .withDefaultFormats() .withFormats(CONSOLE, TXT, HTML, XML)) .useParameterConverters(parameterConverters); } @Override public InjectableStepsFactory stepsFactory() { return new InstanceStepsFactory(configuration(), new PublisherSubscriberJB(), new ProducerConsumerJB()); } @Override protected List<String> storyPaths() { return new StoryFinder().findPaths(codeLocationFromClass(this.getClass()), "*.story", "*excluded*.story"); } }Most interesting thing here is function stepsFactory - here we have to list our "steps" - JUnit tests which have to cover our stories, which we created on previous steps.
4. First run
Now we can run our JBehave runner(just as regular JUnit test) to see if everything is fine: we have to be sure that JBehave have found our .story files.My output after run:
Processing system properties {}
Using controls EmbedderControls[batch=false,skip=false,generateViewAfterStories=true,ignoreFailureInStories=true,ignoreFailureInView=true,verboseFailures=false,verboseFiltering=false,storyTimeoutInSecs=60,failOnStoryTimeout=false,threads=1]
(BeforeStories)
Running story ProducerConsumer.story
(ProducerConsumer.story)
Scenario: simple message receiving by one consumer
Given one producer, one consumer, one message (PENDING)
When producer sends message to queue (PENDING)
Then consumer receives message from queue (PENDING)
@Given("one producer, one consumer, one message")
@Pending
public void givenOneProducerOneConsumerOneMessage() {
// PENDING
}
@When("producer sends message to queue")
@Pending
public void whenProducerSendsMessageToQueue() {
// PENDING
}
@Then("consumer receives message from queue")
@Pending
public void thenConsumerReceivesMessageFromQueue() {
// PENDING
}
Scenario: simple message receiving by several consumers:only one of them have to receive message
Given one producer, several consumers, one message (PENDING)
When producer sends message to queue (PENDING)
Then only one consumer have to receive message from queue (PENDING)
@Given("one producer, several consumers, one message")
@Pending
public void givenOneProducerSeveralConsumersOneMessage() {
// PENDING
}
@When("producer sends message to queue")
@Pending
public void whenProducerSendsMessageToQueue() {
// PENDING
}
@Then("only one consumer have to receive message from queue")
@Pending
public void thenOnlyOneConsumerHaveToReceiveMessageFromQueue() {
// PENDING
}
Running story PublisherSubscriber.story
(PublisherSubscriber.story)
Scenario: broadcast message receiving by all subscribers of topic
Given one publisher, several subscribers, one message (PENDING)
When publisher sends message (PENDING)
Then all subscribers have to receive this message (PENDING)
@Given("one publisher, several subscribers, one message")
@Pending
public void givenOnePublisherSeveralSubscribersOneMessage() {
// PENDING
}
@When("publisher sends message")
@Pending
public void whenPublisherSendsMessage() {
Processing system properties {}
Using controls EmbedderControls[batch=false,skip=false,generateViewAfterStories=true,ignoreFailureInStories=true,ignoreFailureInView=true,verboseFailures=false,verboseFiltering=false,storyTimeoutInSecs=60,failOnStoryTimeout=false,threads=1]
(BeforeStories)
Running story ProducerConsumer.story
(ProducerConsumer.story)
Scenario: simple message receiving by one consumer
Given one producer, one consumer, one message (PENDING)
When producer sends message to queue (PENDING)
Then consumer receives message from queue (PENDING)
@Given("one producer, one consumer, one message")
@Pending
public void givenOneProducerOneConsumerOneMessage() {
// PENDING
}
@When("producer sends message to queue")
@Pending
public void whenProducerSendsMessageToQueue() {
// PENDING
}
@Then("consumer receives message from queue")
@Pending
public void thenConsumerReceivesMessageFromQueue() {
// PENDING
}
Scenario: simple message receiving by several consumers:only one of them have to receive message
Given one producer, several consumers, one message (PENDING)
When producer sends message to queue (PENDING)
Then only one consumer have to receive message from queue (PENDING)
@Given("one producer, several consumers, one message")
@Pending
public void givenOneProducerSeveralConsumersOneMessage() {
// PENDING
}
@When("producer sends message to queue")
@Pending
public void whenProducerSendsMessageToQueue() {
// PENDING
}
@Then("only one consumer have to receive message from queue")
@Pending
public void thenOnlyOneConsumerHaveToReceiveMessageFromQueue() {
// PENDING
}
Running story PublisherSubscriber.story
(PublisherSubscriber.story)
Scenario: broadcast message receiving by all subscribers of topic
Given one publisher, several subscribers, one message (PENDING)
When publisher sends message (PENDING)
Then all subscribers have to receive this message (PENDING)
@Given("one publisher, several subscribers, one message")
@Pending
public void givenOnePublisherSeveralSubscribersOneMessage() {
// PENDING
}
@When("publisher sends message")
@Pending
public void whenPublisherSendsMessage() {
// PENDING
}
@Then("all subscribers have to receive this message")
@Pending
public void thenAllSubscribersHaveToReceiveThisMessage() {
// PENDING
}
(AfterStories) // PENDING
}
@Then("all subscribers have to receive this message")
@Pending
public void thenAllSubscribersHaveToReceiveThisMessage() {
// PENDING
}
(AfterStories)
Everything looks good: jbehave found both .story files and even generated for us "mockup"(function definitions) of future implementation!
So, we can copy/paste function definitions to our test classes in to"fill"(implement) them.
5. Stories implementation.
Now, let's put code into generated function definitions.ProducerConsumerJB
package com.demien.amq.jbehave; import com.demien.amq.Consumer; import com.demien.amq.Producer; import com.demien.amq.TestObject; import org.apache.activemq.ActiveMQConnectionFactory; import org.jbehave.core.annotations.Given; import org.jbehave.core.annotations.Then; import org.jbehave.core.annotations.When; import javax.jms.ConnectionFactory; import javax.jms.JMSException; import java.util.ArrayList; import java.util.List; import static org.junit.Assert.*; /** * Created by dmitry on 14.02.15. */ public class ProducerConsumerJB { public static String brokerURL = "tcp://localhost:61616"; private final ConnectionFactory factory = new ActiveMQConnectionFactory(brokerURL); private final String queueName1="TestQueue1"; private final String queueName2="TestQueue2"; Producer<TestObject> producer; Consumer<TestObject> consumer; List<Consumer<TestObject>> consumers; /* Scenario: simple message receiving by one consumer Given one producer, one consumer, one message (PENDING) When producer sends message to queue (PENDING) Then consumer receives message from queue (PENDING) */ @Given("one producer, one consumer, one message") public void givenOneProducerOneConsumerOneMessage() throws JMSException { producer=new Producer<TestObject>(factory, queueName1); consumer=new Consumer<TestObject>(factory, queueName1); consumer.setConsumerId("THE_ONLY_CONSUMER"); } @When("producer sends message to queue") public void whenProducerSendsMessageToQueue() throws JMSException, InterruptedException { producer.postObjectMessage(new TestObject()); Thread.sleep(1000); } @Then("consumer receives message from queue") public void thenConsumerReceivesMessageFromQueue() { int receivedMessageCount=consumer.getMessages().size(); assertEquals(1, receivedMessageCount); } /* Scenario: simple message receiving by several consumers:only one of them have to receive message Given one producer, several consumers, one message (PENDING) When producer sends message to queue (PENDING) Then only one consumer have to receive message from queue (PENDING) */ @Given("one producer, several consumers, one message") public void givenOneProducerSeveralConsumersOneMessage() throws JMSException { producer=new Producer<TestObject>(factory, queueName2); consumers=new ArrayList<Consumer<TestObject>>(); for (int i=0;i<10;i++) { Consumer<TestObject> eachConsumer=new Consumer<TestObject>(factory, queueName2); eachConsumer.setConsumerId("Consumer#"+Integer.toString(i)); consumers.add(eachConsumer); } } /* - already implemented @When("producer sends message to queue") public void whenProducerSendsMessageToQueue() { // PENDING } */ @Then("only one consumer have to receive message from queue") public void thenOnlyOneConsumerHaveToReceiveMessageFromQueue() { int receivedMessageCount=0; for (Consumer<TestObject> eachConsumer: consumers) { receivedMessageCount=receivedMessageCount+eachConsumer.getMessages().size(); } assertEquals(1, receivedMessageCount); } }
PublisherSubscriberJB
package com.demien.amq.jbehave; import com.demien.amq.Publisher; import com.demien.amq.Subscriber; import com.demien.amq.TestObject; import org.apache.activemq.ActiveMQConnectionFactory; import org.jbehave.core.annotations.Given; import org.jbehave.core.annotations.Then; import org.jbehave.core.annotations.When; import javax.jms.ConnectionFactory; import javax.jms.JMSException; import java.util.ArrayList; import java.util.List; import static org.junit.Assert.assertTrue; /** * Created by dmitry on 09.02.15. */ public class PublisherSubscriberJB { public static String brokerURL = "tcp://localhost:61616"; private final ConnectionFactory factory = new ActiveMQConnectionFactory(brokerURL); private final String topicName="TestTopic"; private final int SUBSCRIBERS_COUNT=10; Long TEST_ID=-1L; String TEST_NAME="test name"; Publisher<TestObject> publisher; List<Subscriber<TestObject>> subscribers; /* (PublisherSubscriber.story) Scenario: broadcast message receiving by all subscribers of topic Given one publisher, several subscribers, one message (PENDING) When publisher sends message (PENDING) Then all subscribers have to receive this message (PENDING) */ @Given("one publisher, several subscribers, one message") public void givenOnePublisherSeveralSubscribersOneMessage() throws JMSException { publisher=new Publisher<TestObject>(factory, topicName); subscribers=new ArrayList<Subscriber<TestObject>>(); for (int i=0; i<SUBSCRIBERS_COUNT; i++) { Subscriber<TestObject> subscriber=new Subscriber<TestObject>(factory, topicName); subscriber.setSubscriberId(Integer.toString(i)); subscribers.add(subscriber); } } @When("publisher sends message") public void whenPublisherSendsMessage() throws JMSException, InterruptedException { TestObject testObject=new TestObject(); testObject.id=new Long(TEST_ID); testObject.name=new String(TEST_NAME); //post message publisher.postObjectMessage(testObject); Thread.sleep(1000); } @Then("all subscribers have to receive this message") public void thenAllSubscribersHaveToReceiveThisMessage() { for (Subscriber<TestObject> subscriber:subscribers) { TestObject received=subscriber.getMessages().get(0); assertTrue(received.name.equals(TEST_NAME)); assertTrue(received.id.equals(TEST_ID)); } } }
6. Final run and results
Now, we can run our message broker and after the we can finally run our JBehave tests .My results :
Running story ProducerConsumer.story
(ProducerConsumer.story)
Scenario: simple message receiving by one consumer
log4j:WARN No appenders could be found for logger (org.apache.activemq.transport.WireFormatNegotiator).
log4j:WARN Please initialize the log4j system properly.
Given one producer, one consumer, one message
Sending message:com.demien.amq.TestObject@807bbc
Consumer[THE_ONLY_CONSUMER] Message received:
When producer sends message to queue
Then consumer receives message from queue
Scenario: simple message receiving by several consumers:only one of them have to receive message
Given one producer, several consumers, one message
Sending message:com.demien.amq.TestObject@7b0aef
Consumer[Consumer#0] Message received:
When producer sends message to queue
Then only one consumer have to receive message from queue
Running story PublisherSubscriber.story
(PublisherSubscriber.story)
Scenario: broadcast message receiving by all subscribers of topic
Given one publisher, several subscribers, one message
Subscriber[0] received message.
Subscriber[3] received message.
Subscriber[4] received message.
Subscriber[1] received message.
Subscriber[2] received message.
Subscriber[7] received message.
Subscriber[6] received message.
Subscriber[9] received message.
Subscriber[5] received message.
Subscriber[8] received message.
When publisher sends message
Then all subscribers have to receive this message
As we can see, result are very easy for understanding even for users which are not related with development. Also Jbehave can generate very beautiful html tables with results (whey are located in /target/jbehave directory) such as :
Story Reports
Stories | Scenarios | GivenStory Scenarios | Steps | ||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Name | Excluded | Total | Successful | Pending | Failed | Excluded | Total | Successful | Pending | Failed | Excluded | Total | Successful | Pending | Failed | Not Performed | Ignorable | Duration (hh:mm:ss.SSS) | View |
AfterStories | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 00:00:00.000 | stats|html|xml |txt |
BeforeStories | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 00:00:00.000 | stats|xml|html |txt |
ProducerConsumer | 0 | 2 | 2 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 6 | 6 | 0 | 0 | 0 | 0 | 00:00:03.000 | stats|html|xml |txt |
PublisherSubscriber | 0 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 3 | 3 | 0 | 0 | 0 | 0 | 00:00:01.000 | stats|xml|html |txt |
4 | 0 | 3 | 3 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 9 | 9 | 0 | 0 | 0 | 0 | 00:00:04.000 | Totals |
Full source code could be downloaded from here.