diff --git a/.idea/compiler.xml b/.idea/compiler.xml
index a33ce1e0f0..4f9145d5f4 100644
--- a/.idea/compiler.xml
+++ b/.idea/compiler.xml
@@ -10,6 +10,9 @@
+
+
+
@@ -159,4 +162,4 @@
-
\ No newline at end of file
+
diff --git a/experimental/behave/build.gradle b/experimental/behave/build.gradle
new file mode 100644
index 0000000000..1c420488ce
--- /dev/null
+++ b/experimental/behave/build.gradle
@@ -0,0 +1,107 @@
+buildscript {
+ ext.kotlin_version = '1.2.21'
+ ext.commonsio_version = '2.6'
+ ext.cucumber_version = '1.2.5'
+ ext.crash_version = 'cce5a00f114343c1145c1d7756e1dd6df3ea984e'
+ ext.docker_client_version = '8.11.0'
+
+ repositories {
+ maven {
+ jcenter()
+ url 'https://jitpack.io'
+ }
+ }
+
+ dependencies {
+ classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
+ }
+}
+
+group 'net.corda.behave'
+
+apply plugin: 'java'
+apply plugin: 'kotlin'
+
+sourceCompatibility = 1.8
+
+repositories {
+ mavenCentral()
+}
+
+sourceSets {
+ scenario {
+ java {
+ compileClasspath += main.output
+ runtimeClasspath += main.output
+ srcDir file('src/scenario/kotlin')
+ }
+ resources.srcDir file('src/scenario/resources')
+ }
+}
+
+configurations {
+ scenarioCompile.extendsFrom testCompile
+ scenarioRuntime.extendsFrom testRuntime
+}
+
+dependencies {
+
+ // Library
+
+ compile "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
+ compile "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"
+
+ compile("com.github.corda.crash:crash.shell:$crash_version") {
+ exclude group: "org.slf4j", module: "slf4j-jdk14"
+ exclude group: "org.bouncycastle"
+ }
+
+ compile("com.github.corda.crash:crash.connectors.ssh:$crash_version") {
+ exclude group: "org.slf4j", module: "slf4j-jdk14"
+ exclude group: "org.bouncycastle"
+ }
+
+ compile "com.spotify:docker-client:$docker_client_version"
+
+ // Unit Tests
+
+ testCompile "junit:junit:$junit_version"
+
+ // Scenarios / End-to-End Tests
+
+ scenarioCompile "info.cukes:cucumber-java8:$cucumber_version"
+ scenarioCompile "info.cukes:cucumber-junit:$cucumber_version"
+ scenarioCompile "info.cukes:cucumber-picocontainer:$cucumber_version"
+ scenarioCompile "org.assertj:assertj-core:$assertj_version"
+ scenarioCompile "org.slf4j:log4j-over-slf4j:$slf4j_version"
+ scenarioCompile "org.slf4j:jul-to-slf4j:$slf4j_version"
+ scenarioCompile "org.apache.logging.log4j:log4j-slf4j-impl:$log4j_version"
+ scenarioCompile "org.apache.logging.log4j:log4j-core:$log4j_version"
+ scenarioCompile "commons-io:commons-io:$commonsio_version"
+
+}
+
+compileKotlin {
+ kotlinOptions.jvmTarget = "1.8"
+}
+
+compileTestKotlin {
+ kotlinOptions.jvmTarget = "1.8"
+}
+
+compileScenarioKotlin {
+ kotlinOptions.jvmTarget = "1.8"
+}
+
+test {
+ testLogging.showStandardStreams = true
+}
+
+task scenarios(type: Test) {
+ setTestClassesDirs sourceSets.scenario.output.getClassesDirs()
+ classpath = sourceSets.scenario.runtimeClasspath
+ outputs.upToDateWhen { false }
+}
+
+scenarios.mustRunAfter test
+scenarios.dependsOn test
\ No newline at end of file
diff --git a/experimental/behave/src/main/kotlin/net/corda/behave/Utility.kt b/experimental/behave/src/main/kotlin/net/corda/behave/Utility.kt
new file mode 100644
index 0000000000..b3dd28f73c
--- /dev/null
+++ b/experimental/behave/src/main/kotlin/net/corda/behave/Utility.kt
@@ -0,0 +1,7 @@
+package net.corda.behave
+
+object Utility {
+
+ fun dummy() = true
+
+}
\ No newline at end of file
diff --git a/experimental/behave/src/scenario/kotlin/Scenarios.kt b/experimental/behave/src/scenario/kotlin/Scenarios.kt
new file mode 100644
index 0000000000..b0c96a98ee
--- /dev/null
+++ b/experimental/behave/src/scenario/kotlin/Scenarios.kt
@@ -0,0 +1,12 @@
+import cucumber.api.CucumberOptions
+import cucumber.api.junit.Cucumber
+import org.junit.runner.RunWith
+
+@RunWith(Cucumber::class)
+@CucumberOptions(
+ features = arrayOf("src/scenario/resources/features"),
+ glue = arrayOf("net.corda.behave.scenarios"),
+ plugin = arrayOf("pretty")
+)
+@Suppress("KDocMissingDocumentation")
+class CucumberTest
diff --git a/experimental/behave/src/scenario/kotlin/net/corda/behave/scenarios/ScenarioHooks.kt b/experimental/behave/src/scenario/kotlin/net/corda/behave/scenarios/ScenarioHooks.kt
new file mode 100644
index 0000000000..745ef851b6
--- /dev/null
+++ b/experimental/behave/src/scenario/kotlin/net/corda/behave/scenarios/ScenarioHooks.kt
@@ -0,0 +1,17 @@
+package net.corda.behave.scenarios
+
+import cucumber.api.java.After
+import cucumber.api.java.Before
+
+@Suppress("KDocMissingDocumentation")
+class ScenarioHooks(private val state: ScenarioState) {
+
+ @Before
+ fun beforeScenario() {
+ }
+
+ @After
+ fun afterScenario() {
+ }
+
+}
\ No newline at end of file
diff --git a/experimental/behave/src/scenario/kotlin/net/corda/behave/scenarios/ScenarioState.kt b/experimental/behave/src/scenario/kotlin/net/corda/behave/scenarios/ScenarioState.kt
new file mode 100644
index 0000000000..a21ab59a10
--- /dev/null
+++ b/experimental/behave/src/scenario/kotlin/net/corda/behave/scenarios/ScenarioState.kt
@@ -0,0 +1,7 @@
+package net.corda.behave.scenarios
+
+class ScenarioState {
+
+ var count: Int = 0
+
+}
\ No newline at end of file
diff --git a/experimental/behave/src/scenario/kotlin/net/corda/behave/scenarios/StepsBlock.kt b/experimental/behave/src/scenario/kotlin/net/corda/behave/scenarios/StepsBlock.kt
new file mode 100644
index 0000000000..5880c939a3
--- /dev/null
+++ b/experimental/behave/src/scenario/kotlin/net/corda/behave/scenarios/StepsBlock.kt
@@ -0,0 +1,3 @@
+package net.corda.behave.scenarios
+
+typealias StepsBlock = (StepsContainer.() -> Unit) -> Unit
\ No newline at end of file
diff --git a/experimental/behave/src/scenario/kotlin/net/corda/behave/scenarios/StepsContainer.kt b/experimental/behave/src/scenario/kotlin/net/corda/behave/scenarios/StepsContainer.kt
new file mode 100644
index 0000000000..69ef293853
--- /dev/null
+++ b/experimental/behave/src/scenario/kotlin/net/corda/behave/scenarios/StepsContainer.kt
@@ -0,0 +1,25 @@
+package net.corda.behave.scenarios
+
+import cucumber.api.java8.En
+import net.corda.behave.scenarios.steps.dummySteps
+import org.slf4j.Logger
+import org.slf4j.LoggerFactory
+
+@Suppress("KDocMissingDocumentation")
+class StepsContainer(val state: ScenarioState) : En {
+
+ val log: Logger = LoggerFactory.getLogger(StepsContainer::class.java)
+
+ private val stepDefinitions: List<(StepsBlock) -> Unit> = listOf(
+ ::dummySteps
+ )
+
+ init {
+ stepDefinitions.forEach { it({ this.steps(it) }) }
+ }
+
+ private fun steps(action: (StepsContainer.() -> Unit)) {
+ action(this)
+ }
+
+}
diff --git a/experimental/behave/src/scenario/kotlin/net/corda/behave/scenarios/steps/DummySteps.kt b/experimental/behave/src/scenario/kotlin/net/corda/behave/scenarios/steps/DummySteps.kt
new file mode 100644
index 0000000000..ce86fa5186
--- /dev/null
+++ b/experimental/behave/src/scenario/kotlin/net/corda/behave/scenarios/steps/DummySteps.kt
@@ -0,0 +1,18 @@
+package net.corda.behave.scenarios.steps
+
+import net.corda.behave.scenarios.StepsBlock
+import org.assertj.core.api.Assertions.assertThat
+
+fun dummySteps(steps: StepsBlock) = steps {
+
+ When("^(\\d+) dumm(y|ies) exists?$") { count, _ ->
+ state.count = count
+ log.info("Checking pre-condition $count")
+ }
+
+ Then("^there is a dummy$") {
+ assertThat(state.count).isGreaterThan(0)
+ log.info("Checking outcome ${state.count}")
+ }
+
+}
diff --git a/experimental/behave/src/scenario/resources/features/dummy.feature b/experimental/behave/src/scenario/resources/features/dummy.feature
new file mode 100644
index 0000000000..6ff1613bd5
--- /dev/null
+++ b/experimental/behave/src/scenario/resources/features/dummy.feature
@@ -0,0 +1,6 @@
+Feature: Dummy
+ Lorem ipsum
+
+ Scenario: Noop
+ Given 15 dummies exist
+ Then there is a dummy
\ No newline at end of file
diff --git a/experimental/behave/src/scenario/resources/log4j2.xml b/experimental/behave/src/scenario/resources/log4j2.xml
new file mode 100644
index 0000000000..43fcf63c3d
--- /dev/null
+++ b/experimental/behave/src/scenario/resources/log4j2.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/experimental/behave/src/test/kotlin/net/corda/behave/UtilityTests.kt b/experimental/behave/src/test/kotlin/net/corda/behave/UtilityTests.kt
new file mode 100644
index 0000000000..c956cc67e1
--- /dev/null
+++ b/experimental/behave/src/test/kotlin/net/corda/behave/UtilityTests.kt
@@ -0,0 +1,13 @@
+package net.corda.behave
+
+import org.junit.Assert
+import org.junit.Test
+
+class UtilityTests {
+
+ @Test
+ fun `dummy`() {
+ Assert.assertEquals(true, Utility.dummy())
+ }
+
+}
\ No newline at end of file
diff --git a/settings.gradle b/settings.gradle
index a4f87dee28..4b0a92c815 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -16,6 +16,7 @@ include 'client:rpc'
include 'webserver'
include 'webserver:webcapsule'
include 'experimental'
+include 'experimental:behave'
include 'experimental:sandbox'
include 'experimental:quasar-hook'
include 'experimental:kryo-hook'