Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
107 changes: 107 additions & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ dependencies {
// ✅ Cucumber for BDD
testImplementation("io.cucumber:cucumber-java:7.27.2")
testImplementation("io.cucumber:cucumber-junit-platform-engine:7.27.2")
testImplementation("io.cucumber:cucumber-picocontainer:7.27.2")

// JUnit 5 Suite annotations
testImplementation("org.junit.platform:junit-platform-suite:1.13.4")
Expand Down Expand Up @@ -180,6 +181,112 @@ tasks.register<Test>("allCucumberTests") {
shouldRunAfter(tasks.test)
}

// ─── BDD tasks (Phase 0 of BDD migration plan) ───────────────────────────────
// Default BDD run: defers to CucumberTestRunner's static-init default tag
// filter, which is "not @nametag and not @slow and not @wip and not @ignore"
// but yields to an explicit -Dcucumber.filter.tags=<expr> override.
tasks.register<Test>("bddTest") {
useJUnitPlatform()
maxHeapSize = "1024m"
systemProperty("cucumber.junit-platform.naming-strategy", "long")
systemProperties = System.getProperties().toMap() as Map<String, Any>
Comment on lines +191 to +192

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Assigning to systemProperties replaces the entire map of system properties for the test task. This causes the cucumber.junit-platform.naming-strategy property set on the previous line to be lost unless it is also present in the host JVM's system properties. Use the systemProperties() method instead to append properties to the existing map. This pattern is repeated in several other BDD tasks (bddNametag, bddSlow, etc.).

    systemProperty("cucumber.junit-platform.naming-strategy", "long")
    systemProperties(System.getProperties().toMap() as Map<String, Any>)


// Make BDD env vars part of the task's up-to-date cache key so that
// switching AGGREGATOR_URL / TRUST_BASE_PATH / tag filter actually forces a
// re-run. Without this, Gradle sees unchanged source+classpath and serves
// a cached pass in ~3 seconds.
inputs.property("AGGREGATOR_URL", System.getenv("AGGREGATOR_URL") ?: "")
inputs.property("AGGREGATOR_API_KEY", System.getenv("AGGREGATOR_API_KEY") ?: "")
inputs.property("TRUST_BASE_PATH", System.getenv("TRUST_BASE_PATH") ?: "")
inputs.property(
"cucumber.filter.tags",
System.getProperty("cucumber.filter.tags") ?: ""
)

// Stream Cucumber's `pretty` formatter output live to the console.
// Without this, Gradle captures the test JVM's stdout and you only see a
// progress bar + pass/fail totals at the end.
testLogging {
showStandardStreams = true
events("passed", "skipped", "failed")
exceptionFormat = org.gradle.api.tasks.testing.logging.TestExceptionFormat.FULL
}

filter {
includeTestsMatching("*CucumberTestRunner*")
}
shouldRunAfter(tasks.test)
}

// Nametag-gated scenarios: expected to be reported as SKIPPED until UnicityId
// is ported to Java v2. See BDD_MIGRATION_PLAN.md Phase 8.
tasks.register<Test>("bddNametag") {
useJUnitPlatform()
maxHeapSize = "1024m"
systemProperty("cucumber.junit-platform.naming-strategy", "long")
systemProperties = System.getProperties().toMap() as Map<String, Any>
systemProperty("cucumber.filter.tags", "@nametag")

filter {
includeTestsMatching("*CucumberTestRunner*")
}
shouldRunAfter(tasks.test)
}

// Performance / load scenarios — needs sharded aggregator topology.
tasks.register<Test>("bddSlow") {
useJUnitPlatform()
maxHeapSize = "4096m"
systemProperty("cucumber.junit-platform.naming-strategy", "long")
systemProperties = System.getProperties().toMap() as Map<String, Any>
systemProperty("cucumber.filter.tags", "@slow or @shard-load")

filter {
includeTestsMatching("*CucumberTestRunner*")
}
shouldRunAfter(tasks.test)
}

// Fast subset — excludes @tree (the ~136-row 4-level-tree family that dominates
// live-aggregator runtime) in addition to the default exclusions. Use this for
// quick live-aggregator smoke runs. Full coverage: use bddTest (slow on live).
tasks.register<Test>("bddTestFast") {
useJUnitPlatform()
maxHeapSize = "1024m"
systemProperty("cucumber.junit-platform.naming-strategy", "long")
systemProperties = System.getProperties().toMap() as Map<String, Any>
systemProperty(
"cucumber.filter.tags",
"not @nametag and not @slow and not @wip and not @ignore and not @tree"
)
inputs.property("AGGREGATOR_URL", System.getenv("AGGREGATOR_URL") ?: "")
inputs.property("TRUST_BASE_PATH", System.getenv("TRUST_BASE_PATH") ?: "")
testLogging {
showStandardStreams = true
events("passed", "skipped", "failed")
exceptionFormat = org.gradle.api.tasks.testing.logging.TestExceptionFormat.FULL
}
filter {
includeTestsMatching("*CucumberTestRunner*")
}
shouldRunAfter(tasks.test)
}

// Everything — used for coverage sweeps. Expect nametag scenarios to skip until
// UnicityId is ported.
tasks.register<Test>("bddAll") {
useJUnitPlatform()
maxHeapSize = "2048m"
systemProperty("cucumber.junit-platform.naming-strategy", "long")
systemProperties = System.getProperties().toMap() as Map<String, Any>
systemProperty("cucumber.filter.tags", "not @ignore")

filter {
includeTestsMatching("*CucumberTestRunner*")
}
shouldRunAfter(tasks.test)
}

// Create separate JARs for each platform
tasks.register<Jar>("androidJar") {
archiveClassifier.set("android")
Expand Down
39 changes: 39 additions & 0 deletions src/test/java/org/unicitylabs/sdk/e2e/CucumberTestRunner.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package org.unicitylabs.sdk.e2e;

import io.cucumber.junit.platform.engine.Constants;
import org.junit.platform.suite.api.ConfigurationParameter;
import org.junit.platform.suite.api.IncludeEngines;
import org.junit.platform.suite.api.SelectPackages;
import org.junit.platform.suite.api.Suite;

@Suite
@IncludeEngines("cucumber")
@SelectPackages("org.unicitylabs.sdk.features")
@ConfigurationParameter(
key = Constants.GLUE_PROPERTY_NAME,
value = "org.unicitylabs.sdk.e2e.steps,"
+ "org.unicitylabs.sdk.e2e.steps.shared,"
+ "org.unicitylabs.sdk.e2e.config")
@ConfigurationParameter(
key = Constants.PLUGIN_PROPERTY_NAME,
value = "pretty,"
+ "html:build/cucumber-reports/cucumber.html,"
+ "json:build/cucumber-reports/cucumber.json")
@ConfigurationParameter(
key = Constants.EXECUTION_DRY_RUN_PROPERTY_NAME,
value = "false")
@ConfigurationParameter(
key = Constants.PLUGIN_PUBLISH_QUIET_PROPERTY_NAME,
value = "true")
// Default tag filter — excludes nametag-gated scenarios (blocked until UnicityId
// lands), load/perf scenarios, and work-in-progress. Overridable by passing
// -Dcucumber.filter.tags=<expr> on the command line; system properties take
// precedence over @ConfigurationParameter defaults per JUnit Platform spec.
@ConfigurationParameter(
key = Constants.FILTER_TAGS_PROPERTY_NAME,
value = "not @slow and not @wip and not @ignore "
+ "and not @bft-shard-only and not @multi-shard-only "
+ "and not @pending-src-cleanup "
+ "and not @stateful and not @fresh-aggregator")
public class CucumberTestRunner {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package org.unicitylabs.sdk.e2e.config;

import io.cucumber.java.After;
import io.cucumber.java.Before;
import io.cucumber.java.Scenario;
import org.unicitylabs.sdk.e2e.context.TestContext;

/**
* Cucumber lifecycle hooks. Cucumber's PicoContainer creates one instance per scenario and
* injects the shared {@link TestContext}, ensuring the same context reaches every step class
* that takes it as a constructor parameter.
*/
public class CucumberConfiguration {

private final TestContext testContext;

public CucumberConfiguration(TestContext testContext) {
this.testContext = testContext;
}

@Before
public void beforeScenario(Scenario scenario) {
testContext.clearTestState();
System.out.println("[BDD] >>> " + scenario.getName());
}

@After
public void afterScenario(Scenario scenario) {
System.out.println(
"[BDD] <<< " + scenario.getName() + " — " + scenario.getStatus());
}

@After("@reset")
public void fullReset() {
testContext.reset();
}
}
Loading
Loading