Skip to content

test: Add Cucumber BDD coverage for the Articles API - #286

Open
devin-ai-integration[bot] wants to merge 1 commit into
mainfrom
devin/1786376027-cucumber-articles-bdd
Open

devin-ai-integration[bot] wants to merge 1 commit into
mainfrom
devin/1786376027-cucumber-articles-bdd

Conversation

@devin-ai-integration

@devin-ai-integration devin-ai-integration Bot commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds a Cucumber layer on top of the existing suite: 51 scenarios across create-article, article-feed and favorite-article, driving the real HTTP API (security filters, MyBatis, SQLite) rather than mocks. ./gradlew test now runs 119 tests (68 before); ./gradlew cucumberTest runs the scenarios alone.

Infrastructure, all under src/test/java/io/spring/cucumber:

  • RunCucumberTest@Suite + @IncludeEngines("cucumber"), glue io.spring.cucumber, features at src/test/resources/features.
  • CucumberSpringConfiguration@CucumberContextConfiguration + @SpringBootTest(RANDOM_PORT) on a new cucumber profile (build/cucumber.db, Flyway stops at V1 so scenarios own their data). Its beans live in a nested @TestConfiguration on purpose: the app component-scans io.spring, and a @Component here would leak into every other Spring test context.
  • ApiClient resolves the port lazily (environment.getRequiredProperty("local.server.port")) — injecting it as a constructor @Value fails, the property does not exist yet when the bean is created.
  • Hooks wipes every table before each scenario, so scenarios are order-independent and reruns are clean.

Steps build the request from the columns actually present in the table, which is what makes the missing-field outline data-driven:

When I create an article with:
  | title       | [empty]     |
  | description | Ever wonder |
Then the response status should be 422
And the response should report "can't be empty" for the field "title"
if (article.containsKey(field)) payload.put(field, EMPTY.equals(v) ? "" : v);
payload.put("tagList", tagList(article.get("tags")));  // always sent: a null tagList NPEs in Article

Two API behaviors constrained the scenarios and are worth knowing:

  • Sending "title": null (or omitting it) returns 500, not 422: DuplicatedArticleValidator calls Article.toSlug(value) on a null value before @NotBlank can reject it. The feature therefore sends [empty] for the fields under test; a blank Gherkin cell is null, which is why only description/body appear in the second Examples table. Not fixed here — this PR only adds tests.
  • /articles/feed applies LIMIT to the tag-joined rows (findArticlesOfAuthors joins article_tags without a distinct id subquery), so a tagged article consumes several rows of the page. The global feed does not have this problem (selectArticleIds). The user-feed pagination outline uses untagged articles to stay meaningful.

Not addressed: the pre-existing JaCoCo gate still fails (0.34 vs 0.80) as AGENTS.md instructs — run with -x jacocoTestCoverageVerification.

Link to Devin session: https://partner-workshops.devinenterprise.com/sessions/ced6e245b02a49059d54e07f1b07ca25


Open in Devin Review

@devin-ai-integration

Copy link
Copy Markdown
Contributor Author

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment, CI, and merge conflict monitoring

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

✅ Devin Review: No Issues Found

Devin Review analyzed this PR and found no bugs or issues to report.

Open in Devin Review

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants