diff --git a/.gitmodules b/.gitmodules
index 5893173a6..476d155da 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -1,3 +1,3 @@
-[submodule "test-harness"]
- path = test-harness
- url = https://github.com/open-feature/test-harness
+[submodule "spec"]
+ path = spec
+ url = https://github.com/open-feature/spec/
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 2aafb314f..84c9645b9 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -23,7 +23,7 @@ If you're adding tests to cover something in the spec, use the `@Specification`
## End-to-End Tests
-The continuous integration runs a set of [gherkin e2e tests](https://github.com/open-feature/test-harness/blob/main/features/evaluation.feature) using `InMemoryProvider`.
+The continuous integration runs a set of [gherkin e2e tests](https://github.com/open-feature/spec/blob/main/specification/assets/gherkin/evaluation.feature) using `InMemoryProvider`.
to run alone:
```
diff --git a/pom.xml b/pom.xml
index d9e4bc723..63fa4bd99 100644
--- a/pom.xml
+++ b/pom.xml
@@ -554,22 +554,21 @@
submodule
update
--init
- test-harness
+ spec
- copy-gherkin-tests
+ copy-evaluation-gherkin-tests
validate
exec
-
cp
- test-harness/features/evaluation.feature
+ spec/specification/assets/gherkin/evaluation.feature
src/test/resources/features/
diff --git a/spec b/spec
new file mode 160000
index 000000000..d4a9a9109
--- /dev/null
+++ b/spec
@@ -0,0 +1 @@
+Subproject commit d4a9a910946eded57cf82d6fd4921785a5e64c2b
diff --git a/src/test/java/dev/openfeature/sdk/e2e/RunCucumberTest.java b/src/test/java/dev/openfeature/sdk/e2e/EvaluationTest.java
similarity index 62%
rename from src/test/java/dev/openfeature/sdk/e2e/RunCucumberTest.java
rename to src/test/java/dev/openfeature/sdk/e2e/EvaluationTest.java
index 2c652338d..3e0f2ee89 100644
--- a/src/test/java/dev/openfeature/sdk/e2e/RunCucumberTest.java
+++ b/src/test/java/dev/openfeature/sdk/e2e/EvaluationTest.java
@@ -5,12 +5,17 @@
import org.junit.platform.suite.api.SelectClasspathResource;
import org.junit.platform.suite.api.Suite;
+import static io.cucumber.junit.platform.engine.Constants.GLUE_PROPERTY_NAME;
import static io.cucumber.junit.platform.engine.Constants.PLUGIN_PROPERTY_NAME;
@Suite
@IncludeEngines("cucumber")
-@SelectClasspathResource("features")
+@SelectClasspathResource("features/evaluation.feature")
@ConfigurationParameter(key = PLUGIN_PROPERTY_NAME, value = "pretty")
-public class RunCucumberTest {
-
+@ConfigurationParameter(key = GLUE_PROPERTY_NAME, value = "dev.openfeature.sdk.e2e.evaluation")
+public class EvaluationTest {
+
}
+
+
+
diff --git a/src/test/java/dev/openfeature/sdk/e2e/StepDefinitions.java b/src/test/java/dev/openfeature/sdk/e2e/evaluation/StepDefinitions.java
similarity index 90%
rename from src/test/java/dev/openfeature/sdk/e2e/StepDefinitions.java
rename to src/test/java/dev/openfeature/sdk/e2e/evaluation/StepDefinitions.java
index 459fcefea..cf1905926 100644
--- a/src/test/java/dev/openfeature/sdk/e2e/StepDefinitions.java
+++ b/src/test/java/dev/openfeature/sdk/e2e/evaluation/StepDefinitions.java
@@ -1,4 +1,4 @@
-package dev.openfeature.sdk.e2e;
+package dev.openfeature.sdk.e2e.evaluation;
import dev.openfeature.sdk.Value;
import dev.openfeature.sdk.EvaluationContext;
@@ -52,7 +52,7 @@ public class StepDefinitions {
@SneakyThrows
@BeforeAll()
- @Given("an openfeature client is registered with cache disabled")
+ @Given("a provider is registered")
public static void setup() {
Map> flags = buildFlags();
InMemoryProvider provider = new InMemoryProvider(flags);
@@ -67,7 +67,7 @@ public static void setup() {
// boolean value
@When("a boolean flag with key {string} is evaluated with default value {string}")
public void a_boolean_flag_with_key_boolean_flag_is_evaluated_with_default_value_false(String flagKey,
- String defaultValue) {
+ String defaultValue) {
this.booleanFlagValue = client.getBooleanValue(flagKey, Boolean.valueOf(defaultValue));
}
@@ -117,7 +117,7 @@ public void an_object_flag_with_key_is_evaluated_with_a_null_default_value(Strin
@Then("the resolved object value should be contain fields {string}, {string}, and {string}, with values {string}, {string} and {int}, respectively")
public void the_resolved_object_value_should_be_contain_fields_and_with_values_and_respectively(String boolField,
- String stringField, String numberField, String boolValue, String stringValue, int numberValue) {
+ String stringField, String numberField, String boolValue, String stringValue, int numberValue) {
Structure structure = this.objectFlagValue.asStructure();
assertEquals(Boolean.valueOf(boolValue), structure.asMap().get(boolField).asBoolean());
@@ -132,7 +132,7 @@ public void the_resolved_object_value_should_be_contain_fields_and_with_values_a
// boolean details
@When("a boolean flag with key {string} is evaluated with details and default value {string}")
public void a_boolean_flag_with_key_is_evaluated_with_details_and_default_value(String flagKey,
- String defaultValue) {
+ String defaultValue) {
this.booleanFlagDetails = client.getBooleanDetails(flagKey, Boolean.valueOf(defaultValue));
}
@@ -148,13 +148,13 @@ public void the_resolved_boolean_value_should_be_the_variant_should_be_and_the_r
// string details
@When("a string flag with key {string} is evaluated with details and default value {string}")
public void a_string_flag_with_key_is_evaluated_with_details_and_default_value(String flagKey,
- String defaultValue) {
+ String defaultValue) {
this.stringFlagDetails = client.getStringDetails(flagKey, defaultValue);
}
@Then("the resolved string details value should be {string}, the variant should be {string}, and the reason should be {string}")
public void the_resolved_string_value_should_be_the_variant_should_be_and_the_reason_should_be(String expectedValue,
- String expectedVariant, String expectedReason) {
+ String expectedVariant, String expectedReason) {
assertEquals(expectedValue, this.stringFlagDetails.getValue());
assertEquals(expectedVariant, this.stringFlagDetails.getVariant());
assertEquals(expectedReason, this.stringFlagDetails.getReason());
@@ -168,7 +168,7 @@ public void an_integer_flag_with_key_is_evaluated_with_details_and_default_value
@Then("the resolved integer details value should be {int}, the variant should be {string}, and the reason should be {string}")
public void the_resolved_integer_value_should_be_the_variant_should_be_and_the_reason_should_be(int expectedValue,
- String expectedVariant, String expectedReason) {
+ String expectedVariant, String expectedReason) {
assertEquals(expectedValue, this.intFlagDetails.getValue());
assertEquals(expectedVariant, this.intFlagDetails.getVariant());
assertEquals(expectedReason, this.intFlagDetails.getReason());
@@ -182,7 +182,7 @@ public void a_float_flag_with_key_is_evaluated_with_details_and_default_value(St
@Then("the resolved float details value should be {double}, the variant should be {string}, and the reason should be {string}")
public void the_resolved_float_value_should_be_the_variant_should_be_and_the_reason_should_be(double expectedValue,
- String expectedVariant, String expectedReason) {
+ String expectedVariant, String expectedReason) {
assertEquals(expectedValue, this.doubleFlagDetails.getValue());
assertEquals(expectedVariant, this.doubleFlagDetails.getVariant());
assertEquals(expectedReason, this.doubleFlagDetails.getReason());
@@ -217,7 +217,7 @@ public void the_variant_should_be_and_the_reason_should_be(String expectedVarian
@When("context contains keys {string}, {string}, {string}, {string} with values {string}, {string}, {int}, {string}")
public void context_contains_keys_with_values(String field1, String field2, String field3, String field4,
- String value1, String value2, Integer value3, String value4) {
+ String value1, String value2, Integer value3, String value4) {
Map attributes = new HashMap<>();
attributes.put(field1, new Value(value1));
attributes.put(field2, new Value(value2));
@@ -253,7 +253,7 @@ public void the_resolved_flag_value_is_when_the_context_is_empty(String expected
// not found
@When("a non-existent string flag with key {string} is evaluated with details and a default value {string}")
public void a_non_existent_string_flag_with_key_is_evaluated_with_details_and_a_default_value(String flagKey,
- String defaultValue) {
+ String defaultValue) {
notFoundFlagKey = flagKey;
notFoundDefaultValue = defaultValue;
notFoundDetails = client.getStringDetails(notFoundFlagKey, notFoundDefaultValue);
@@ -273,7 +273,7 @@ public void the_reason_should_indicate_an_error_and_the_error_code_should_be_fla
// type mismatch
@When("a string flag with key {string} is evaluated as an integer, with details and a default value {int}")
public void a_string_flag_with_key_is_evaluated_as_an_integer_with_details_and_a_default_value(String flagKey,
- int defaultValue) {
+ int defaultValue) {
typeErrorFlagKey = flagKey;
typeErrorDefaultValue = defaultValue;
typeErrorDetails = client.getIntegerDetails(typeErrorFlagKey, typeErrorDefaultValue);
diff --git a/test-harness b/test-harness
deleted file mode 160000
index 2d4c63c80..000000000
--- a/test-harness
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit 2d4c63c800aa3af172cf09176325d93124153cde