-
-
Notifications
You must be signed in to change notification settings - Fork 0
feat: Implement BDD with Cucumber and Gherkin #68
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
This commit introduces Behavior-Driven Development (BDD) to the HatchGrid backend using Cucumber and Gherkin. Key changes include: - Added Cucumber dependencies to `server/thryve/thryve.gradle.kts`. - Configured JUnit Platform to run Cucumber tests. - Created `user_registration.feature` with Gherkin scenarios for user registration. - Implemented `UserRegistrationSteps.kt` with step definitions for the feature file. The BDD tests cover scenarios for: - Successful user registration. - User registration with an existing email. - User registration with an invalid email format. All tests, including the new BDD tests, pass successfully. A minor fix was applied to `UserRegistrationSteps.kt` to correctly access the error message from `ApiDataResponse`.
WalkthroughThese changes introduce Cucumber-based BDD testing for user registration in the Thryve server module. They add a Kotlin step definition class, a feature file outlining registration scenarios, and update the build script to support Cucumber tests. The new tests cover successful registration, duplicate email, and invalid email format cases. Changes
Sequence Diagram(s)sequenceDiagram
participant Tester as Cucumber Test
participant Steps as UserRegistrationSteps
participant Controller as UserRegisterController
participant Service as UserRegistrator (Mock)
Tester->>Steps: Run Given/When/Then steps
Steps->>Service: (Given) Mock registration behavior
Steps->>Controller: (When) POST /register with user data
Controller->>Service: Register user (mocked)
Service-->>Controller: Return registration result
Controller-->>Steps: HTTP response
Steps->>Tester: (Then) Assert response and results
Poem
✨ Finishing Touches
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
Deploying hatchgrid with
|
| Latest commit: |
63500c2
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://1239bdaa.hatchgrid.pages.dev |
| Branch Preview URL: | https://feature-bdd-cucumber-gherkin.hatchgrid.pages.dev |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR integrates Behavior-Driven Development (BDD) into HatchGrid’s backend using Cucumber and Gherkin, adding dependencies, configuring the test task, and providing a user registration feature with matching step definitions.
- Added Cucumber dependencies and configured the JUnit Platform to run Cucumber tests
- Created
user_registration.featurewith scenarios for user registration - Implemented
UserRegistrationSteps.ktto define and execute the Gherkin steps
Reviewed Changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| server/thryve/thryve.gradle.kts | Added Cucumber dependencies and configured the test engine |
| server/thryve/src/test/resources/features/user_registration.feature | Added Gherkin scenarios covering user registration cases |
| server/thryve/src/test/kotlin/com/hatchgrid/thryve/users/infrastructure/http/steps/UserRegistrationSteps.kt | Implemented step definitions for the BDD scenarios |
| tasks.withType<Test> { | ||
| useJUnitPlatform() | ||
| useJUnitPlatform { | ||
| includeEngines("cucumber") |
Copilot
AI
Jun 18, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
By specifying only the Cucumber engine here, other JUnit tests (e.g. unit tests) may be excluded. Consider including both 'junit-jupiter' and 'cucumber' engines or using the default configuration alongside a separate Cucumber test task.
| includeEngines("cucumber") | |
| includeEngines("junit-jupiter", "cucumber") |
| coEvery { mockUserRegistrator.registerNewUser(any()) } returns ApiDataResponse.success(UserResponse(email, email, firstName, lastName)) | ||
| } | ||
|
|
||
| @When("the user attempts to register") |
Copilot
AI
Jun 18, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The second scenario uses 'When the new user attempts to register', which doesn’t match this step definition. Either add a second @when annotation for that phrase or unify the Gherkin step text.
| @When("the user attempts to register") | |
| @When("the user attempts to register") | |
| @When("the new user attempts to register") |
| assert(apiDataResponse?.status == ApiResponseStatus.SUCCESS) | ||
| assert(apiDataResponse?.data?.email == email) | ||
| } | ||
|
|
||
| @Then("the user should receive a confirmation") | ||
| fun the_user_should_receive_a_confirmation() { | ||
| // This step would typically involve checking an email or a notification service. | ||
| // For this example, we\'ll assume the successful creation implies confirmation. | ||
| assert(apiDataResponse?.status == ApiResponseStatus.SUCCESS) |
Copilot
AI
Jun 18, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Kotlin's built-in assert is disabled by default at runtime. Switch to a JUnit assertion (e.g., Assertions.assertEquals) or WebTestClient’s expectBody checks to ensure failures are reported.
| assert(apiDataResponse?.status == ApiResponseStatus.SUCCESS) | |
| assert(apiDataResponse?.data?.email == email) | |
| } | |
| @Then("the user should receive a confirmation") | |
| fun the_user_should_receive_a_confirmation() { | |
| // This step would typically involve checking an email or a notification service. | |
| // For this example, we\'ll assume the successful creation implies confirmation. | |
| assert(apiDataResponse?.status == ApiResponseStatus.SUCCESS) | |
| assertEquals(ApiResponseStatus.SUCCESS, apiDataResponse?.status) | |
| assertEquals(email, apiDataResponse?.data?.email) | |
| } | |
| @Then("the user should receive a confirmation") | |
| fun the_user_should_receive_a_confirmation() { | |
| // This step would typically involve checking an email or a notification service. | |
| // For this example, we\'ll assume the successful creation implies confirmation. | |
| assertEquals(ApiResponseStatus.SUCCESS, apiDataResponse?.status) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 3
🧹 Nitpick comments (2)
server/thryve/thryve.gradle.kts (1)
97-101: Missing runtime dependency & Kotlin flavour
cucumber-junit-platform-engineis required at runtime; placing it intestImplementationdrags it transitively, but Gradle’s dependency insight often flags it as unused. For clarity add:testRuntimeOnly("io.cucumber:cucumber-junit-platform-engine:${libs.versions.cucumber.get()}")
- Step definitions are written in Kotlin yet only
cucumber-javais added. While it works,cucumber-kotlinoffers better lambda / default parameter support and avoids reflexive edge-cases. Consider:testImplementation("io.cucumber:cucumber-kotlin:${libs.versions.cucumber.get()}")server/thryve/src/test/resources/features/user_registration.feature (1)
12-17: Scenario wording causes duplicate action – consider removing the extra Given
And a new user attempts to register with the same emailduplicates the subsequentWhen the new user attempts to registerstep and does not add pre-conditions.
Dropping the redundant line streamlines the scenario without changing intent.- And a new user attempts to register with the same email
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
server/thryve/src/test/kotlin/com/hatchgrid/thryve/users/infrastructure/http/steps/UserRegistrationSteps.kt(1 hunks)server/thryve/src/test/resources/features/user_registration.feature(1 hunks)server/thryve/thryve.gradle.kts(2 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (6)
- GitHub Check: Lint with Detekt
- GitHub Check: Build and Test
- GitHub Check: Analyze (javascript-typescript)
- GitHub Check: Analyze (actions)
- GitHub Check: Analyze (java-kotlin)
- GitHub Check: Cloudflare Pages
🔇 Additional comments (1)
server/thryve/src/test/kotlin/com/hatchgrid/thryve/users/infrastructure/http/steps/UserRegistrationSteps.kt (1)
19-31: Un-usedcucumber-spring– wire Spring context or drop the dependency
cucumber-springis included but the step class is instantiated manually (not Spring-managed).
If full Spring context is desired, annotate with@SpringBootTest/@ContextConfigurationand let Cucumber autowire beans; otherwise remove the dependency to keep the test class lightweight.
| useJUnitPlatform { | ||
| includeEngines("cucumber") | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Restricting to only the cucumber engine hides the rest of your JUnit‐Jupiter suite
includeEngines("cucumber") means only the Cucumber engine will be executed; all classic JUnit-Jupiter tests (junit-jupiter) and any property-based tests (junit-quickcheck, etc.) are silently skipped.
Unless that is intentional, extend – rather than replace – the engine list:
-useJUnitPlatform {
- includeEngines("cucumber")
-}
+useJUnitPlatform {
+ includeEngines("cucumber", "junit-jupiter")
+}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| useJUnitPlatform { | |
| includeEngines("cucumber") | |
| } | |
| useJUnitPlatform { | |
| includeEngines("cucumber", "junit-jupiter") | |
| } |
🤖 Prompt for AI Agents
In server/thryve/thryve.gradle.kts around lines 118 to 120, the current
configuration restricts test execution to only the Cucumber engine by using
includeEngines("cucumber"), which causes all other JUnit-Jupiter tests to be
skipped. To fix this, modify the configuration to include the Cucumber engine
alongside the default engines instead of replacing them, ensuring that all test
engines run as intended.
| fun the_user_account_should_be_created_successfully() { | ||
| assert(apiDataResponse?.status == ApiResponseStatus.SUCCESS) | ||
| assert(apiDataResponse?.data?.email == email) | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
kotlin.assert() is ignored unless JVM is run with -ea – replace with test asserts
Gradle’s Test task does not enable assertions by default, so these checks are currently no-ops.
Swap them for JUnit/Jupiter or Kotlin-test assertions:
-assert(apiDataResponse?.status == ApiResponseStatus.SUCCESS)
+assertEquals(ApiResponseStatus.SUCCESS, apiDataResponse?.status)
-assert(apiDataResponse?.error == "Email already in use")
+assertEquals("Email already in use", apiDataResponse?.error)Repeat for all similar lines.
Also applies to: 61-65, 84-86, 88-91, 104-106
🤖 Prompt for AI Agents
In
server/thryve/src/test/kotlin/com/hatchgrid/thryve/users/infrastructure/http/steps/UserRegistrationSteps.kt
around lines 55 to 58, replace the kotlin.assert() calls with proper JUnit or
Kotlin-test assertion methods because kotlin.assert() is ignored unless JVM is
run with -ea, making these checks ineffective. Use assertions like assertEquals
or assertTrue from the testing framework to ensure the tests actually validate
the conditions. Apply the same replacement for all similar assertions in lines
61-65, 84-86, 88-91, and 104-106.
| apiDataResponse = webTestClient.post().uri("/api/register") | ||
| .contentType(MediaType.APPLICATION_JSON) | ||
| .bodyValue(request) | ||
| .exchange() | ||
| .expectStatus().isCreated | ||
| .expectBody(ApiDataResponse::class.java) | ||
| .returnResult().responseBody as ApiDataResponse<UserResponse> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hard-coding isCreated makes failing scenarios pass or break unexpectedly
All scenarios reuse this @When step, yet expectStatus().isCreated asserts HTTP 201 even for error paths (duplicate/invalid email).
Either parameterise the expected status or assert by scenario in the corresponding @Then.
-expectStatus().isCreated
+expectStatus().satisfies {
+ // 201 for success, 4xx for validations – we’ll verify later
+}Alternatively split the When step into success/failure variants.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| apiDataResponse = webTestClient.post().uri("/api/register") | |
| .contentType(MediaType.APPLICATION_JSON) | |
| .bodyValue(request) | |
| .exchange() | |
| .expectStatus().isCreated | |
| .expectBody(ApiDataResponse::class.java) | |
| .returnResult().responseBody as ApiDataResponse<UserResponse> | |
| apiDataResponse = webTestClient.post().uri("/api/register") | |
| .contentType(MediaType.APPLICATION_JSON) | |
| .bodyValue(request) | |
| .exchange() | |
| .expectStatus().satisfies { | |
| // 201 for success, 4xx for validations – we’ll verify later | |
| } | |
| .expectBody(ApiDataResponse::class.java) | |
| .returnResult().responseBody as ApiDataResponse<UserResponse> |
🤖 Prompt for AI Agents
In
server/thryve/src/test/kotlin/com/hatchgrid/thryve/users/infrastructure/http/steps/UserRegistrationSteps.kt
around lines 45 to 51, the test step hard-codes the expected HTTP status as 201
Created, which causes failure scenarios to pass or break incorrectly. To fix
this, modify the step to accept the expected HTTP status as a parameter or
remove the status assertion from the When step and instead assert the status
explicitly in the Then step for each scenario. Alternatively, split the When
step into separate success and failure variants with appropriate status
assertions.
Test Results 37 files - 106 37 suites - 106 24s ⏱️ -35s Results for commit 63500c2. ± Comparison against base commit fe19b9d. This pull request removes 339 and adds 4 tests. Note that renamed tests count towards both. |
|
This PR was marked as stale due to inactivity. It will be closed automatically in 7 days if there are no updates. |
|
WIP 👍 |
|
This PR was marked as stale due to inactivity. It will be closed automatically in 60 days if there are no updates. |
This commit introduces Behavior-Driven Development (BDD) to the HatchGrid backend using Cucumber and Gherkin.
Key changes include:
server/thryve/thryve.gradle.kts.user_registration.featurewith Gherkin scenarios for user registration.UserRegistrationSteps.ktwith step definitions for the feature file.The BDD tests cover scenarios for:
All tests, including the new BDD tests, pass successfully. A minor fix was applied to
UserRegistrationSteps.ktto correctly access the error message fromApiDataResponse.Summary by CodeRabbit