{"id":15174181,"url":"https://github.com/boolivar/jdoc-test","last_synced_at":"2025-10-26T07:31:22.561Z","repository":{"id":227736513,"uuid":"763043929","full_name":"boolivar/jdoc-test","owner":"boolivar","description":"Write BDD tests in JavaDocs!","archived":false,"fork":false,"pushed_at":"2025-02-03T23:05:56.000Z","size":411,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-02-04T00:18:39.585Z","etag":null,"topics":["bdd","cucumber","spock","test"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/boolivar.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-02-25T12:12:26.000Z","updated_at":"2025-02-03T23:05:58.000Z","dependencies_parsed_at":"2024-04-07T21:24:32.966Z","dependency_job_id":"ecfa318f-86fc-4f1d-b467-422fde29da3c","html_url":"https://github.com/boolivar/jdoc-test","commit_stats":{"total_commits":160,"total_committers":2,"mean_commits":80.0,"dds":0.07499999999999996,"last_synced_commit":"73a634cd0478c670cf8bfdbf9f6e3ee46a389d29"},"previous_names":["boolivar/jdoc-test"],"tags_count":14,"template":false,"template_full_name":"boolivar/java-gradle-template","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/boolivar%2Fjdoc-test","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/boolivar%2Fjdoc-test/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/boolivar%2Fjdoc-test/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/boolivar%2Fjdoc-test/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/boolivar","download_url":"https://codeload.github.com/boolivar/jdoc-test/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":238284876,"owners_count":19446743,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["bdd","cucumber","spock","test"],"created_at":"2024-09-27T11:40:28.549Z","updated_at":"2025-10-26T07:31:22.555Z","avatar_url":"https://github.com/boolivar.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# [jdoc-test](https://boolivar.github.io/jdoc-test/)\n\n[![Maven Central Version](https://img.shields.io/maven-central/v/io.github.boolivar.jdoctest/jdoc-core)](https://central.sonatype.com/namespace/io.github.boolivar.jdoctest)\n[![CI](https://github.com/boolivar/jdoc-test/workflows/CI/badge.svg)](https://github.com/boolivar/jdoc-test/actions/workflows/ci.yml)\n[![codecov](https://codecov.io/gh/boolivar/jdoc-test/graph/badge.svg?token=PCV1VTNFYT)](https://codecov.io/gh/boolivar/jdoc-test)\n[![codeclimate](https://api.codeclimate.com/v1/badges/5abdb712f0e232643f83/maintainability)](https://codeclimate.com/github/boolivar/jdoc-test/maintainability)\n[![codebeat](https://codebeat.co/badges/2cfd51bf-0d1b-4422-a845-e71b37e7a3f6)](https://codebeat.co/projects/github-com-boolivar-jdoc-test-master)\n[![release](https://img.shields.io/github/v/release/boolivar/jdoc-test)](https://github.com/boolivar/jdoc-test/releases/latest)\n[![](https://jitpack.io/v/boolivar/jdoc-test.svg)](https://jitpack.io/#boolivar/jdoc-test)\n\n[![Lines of Code](https://sonarcloud.io/api/project_badges/measure?project=boolivar_jdoc-test\u0026metric=ncloc)](https://sonarcloud.io/summary/new_code?id=boolivar_jdoc-test)\n[![Bugs](https://sonarcloud.io/api/project_badges/measure?project=boolivar_jdoc-test\u0026metric=bugs)](https://sonarcloud.io/summary/new_code?id=boolivar_jdoc-test)\n[![Code Smells](https://sonarcloud.io/api/project_badges/measure?project=boolivar_jdoc-test\u0026metric=code_smells)](https://sonarcloud.io/summary/new_code?id=boolivar_jdoc-test)\n\n\nWrite BDD tests in javadocs!\n\n```java\npublic class MathUtils {\n    /**\n     * Calculate square of x.\n     * \n     * \u003cpre\u003e\u003ccode lang=\"spock\"\u003e\n     * def \"returns square\"() {\n     *   expect:\n     *     MathUtils.sqr(2) == 4\n     * }\n     * \u003c/code\u003e\u003c/pre\u003e\n     * \n     * \u003cpre\u003e\u003ccode lang=\"gherkin\"\u003e\n     * Feature: square calculation\n     *   Scenario Outline: integers\n     *     When input value equals \u003cx\u003e\n     *     Then result should be \u003csqr\u003e\n     *     Examples:\n     *       | x | sqr |\n     *       | 0 | 0   |\n     *       | 1 | 1   |\n     *       | 2 | 4   |\n     *       |-1 | 1   |\n     *       | 10| 100 |\n     *       | 11| 121 |\n     * \u003c/code\u003e\u003c/pre\u003e\n     */\n    public static int sqr(int x) {\n        return x * x;\n    }\n}\n```\n\n## What?\n\n**jdoc-test** is a framework for javadoc sourced java tests.\n\nJavadoc writing is cumbersome. Documentation quickly becomes outdated. There is no guarantee that code does what documentation says.  \nDevelopers often prefer to write tests instead of documentation. Tests never lie.\n\nSo why not just write tests in documentation? [BDD](https://en.wikipedia.org/wiki/Behavior-driven_development) frameworks\nuse test specifications written in (more or less) human language. Such documentation goes in sync with actual code and shows code\nusage example. Java code, tests and documentation become tightly coupled by putting BDD specification in javadoc.\n\n## WHAT?\n\n[jdoc-spock](#jdoc-spock) jupiter engine library runs [spockframework](https://spockframework.org/) test specifications written in javadocs.\n\n[jdoc-spock-gradle-plugin](#jdoc-spock-gradle-plugin) gradle [plugin](https://plugins.gradle.org/plugin/io.github.boolivar.jdoctest.jdoc-spock) automates spockframework specs generation and testing.\n\n[jdoc-cucumber](#jdoc-cucumber) jupiter engine library runs [gherkin](https://cucumber.io/docs/gherkin/reference/) features written in javadocs.\n\n[jdoc-cucumber-gradle-plugin](#jdoc-cucumber-gradle-plugin) gradle [plugin](https://plugins.gradle.org/plugin/org.bool.jdoctest.jdoc-cucumber) automates cucumber feature generation and testing. \n\n:warning: **Library tests itself using itself executing own `jdoc-spock` tests written in javadocs.** \n\n## WHAT???\n\nYes, see `jdoc-spock` and `jdoc-cucumber` [test](https://github.com/boolivar/jdoc-test/blob/master/jdoc-spock-commons/src/main/java/org/bool/jdoc/spock/ResourceContainer.java) [examples](https://github.com/boolivar/jdoc-test/blob/master/jdoc-cucumber/src/main/java/org/bool/jdoc/cucumber/ConfigParams.java) in [source](https://github.com/boolivar/jdoc-test/blob/master/jdoc-core/src/main/java/org/bool/jdoc/core/JavaFileParser.java) [code](https://github.com/boolivar/jdoc-test/blob/master/jdoc-spock-commons/src/main/java/org/bool/jdoc/spock/ClassIntrospector.java).\n\n## How?\n\n### jdoc-spock\n\n\u003c!-- x-release-please-start-version --\u003e\n```xml\n\u003cdependency\u003e\n    \u003cgroupId\u003eio.github.boolivar.jdoctest\u003c/groupId\u003e\n    \u003cartifactId\u003ejdoc-spock\u003c/artifactId\u003e\n    \u003cversion\u003e0.11.0\u003c/version\u003e\n    \u003cscope\u003etest\u003c/scope\u003e\n\u003c/dependency\u003e\n```\n\u003c!-- x-release-please-end --\u003e\n\n---\n\n1. Write `jdoc-spock` tests.\n   \n`jdoc-spock` contains junit platform engine to run tests. It considers text in javadoc or block comment between `\u003ccode lang=\"spock\"\u003e` `\u003c/code\u003e` tags as spock specification code.\nAdditional non-mandatory `\u003cpre\u003e` tag keeps code formatting for javadoc presentation:\n```java\n/**\n * \u003cpre\u003e\u003ccode lang=\"spock\"\u003e\n * def \"Calling delegate bar method\"() {\n *   when:\n *     $target.foo()\n *   then:\n *     1 * delegate.bar()\n * }\n * \u003c/code\u003e\u003c/pre\u003e\n */\npublic void foo() {\n    delegate.bar();\n} \n```\n\n2. Add `jdoc-spock` dependency.\n\n`build.gradle` example:\n\u003c!-- x-release-please-start-version --\u003e\n```gradle\nrepositories {\n    mavenCentral()\n}\n\ndependencies {\n    testRuntimeOnly \"io.github.boolivar.jdoctest:jdoc-spock:0.11.0\"\n}\n```\n\u003c!-- x-release-please-end --\u003e\n\n\u003e [!IMPORTANT]\n\u003e `jdoc-spock` versions before `0.9.0` available only on [jitpack](https://jitpack.io/#boolivar/jdoc-test).\n\u003e\n\u003e ```gradle\n\u003e repositories {\n\u003e     maven { url \"https://jitpack.io\" }\n\u003e }\n\u003e \n\u003e dependencies {\n\u003e     testRuntimeOnly \"io.github.boolivar.jdoctest:jdoc-spock:0.8.1\"\n\u003e }\n\u003e ```\n\n3. Compile java code with parameter names using `javac` `-parameters` argument.\n\n`build.gradle` example:\n```gradle\ncompileJava {\n    options.compilerArgs \u003c\u003c \"-parameters\"\n}\n```\n\n`jdoc-spock` uses constructor argument names to generate fields in specification initialized with mocks.\n`$target` field of spock specification is initialized with instance of class under test (instance of primary class in java file where jdoc-spock specification is located).\n`jdoc-spock` searches for biggest constructor with mockable (non-final class) arguments and creates mock for each constructor argument. Mocks stored in spec fields using corresponding names.\n\nAs an example for java class:\n\n```java\npublic class Foo {\n\n    private final Bar delegate;\n\n    public Foo(Bar delegate) {\n        this.delegate = delegate;\n    }\n}\n```\n\ngenerated spock fields will be:\n```groovy\ndef delegate = Mock(Bar)\ndef $target = new Foo(delegate)\n```\n\n4. Set up paths to java sources using test suite `@SelectDirectories` or `@SelectFile`:\n\n```java\nimport org.junit.platform.suite.api.IncludeEngines;\nimport org.junit.platform.suite.api.SelectDirectories;\nimport org.junit.platform.suite.api.Suite;\n\n@Suite\n@IncludeEngines(\"jdoc-spock\")\n@SelectDirectories(\"src/main/java\")\npublic class JdocSpockTestSuite {\n}\n```\n\njdoc-spock supports platform engine `DiscoverySelector` and `FileSelector`.\n\nOptionally comma-separated paths to java sources can be provided using either `jdoc.spock.test-dirs` or `jdoc.spock.test-files` junit platform [Configuration Parameters](https://junit.org/junit5/docs/current/user-guide/#running-tests-config-params).\n\n`build.gradle` example:\n```gradle\ntest {\n    useJUnitPlatform()\n    systemProperties = [\"jdoc.spock.test-dirs\" : sourceSets.main.java.srcDirs.join(\",\")]\n}\n```\n\n5. Run tests with `jdoc-spock` junit engine.\n\n`gradle` example:\n```sh\ngradle test\n```\n\n### jdoc-cucumber\n\n\u003c!-- x-release-please-start-version --\u003e\n```xml\n\u003cdependency\u003e\n    \u003cgroupId\u003eio.github.boolivar.jdoctest\u003c/groupId\u003e\n    \u003cartifactId\u003ejdoc-cucumber\u003c/artifactId\u003e\n    \u003cversion\u003e0.11.0\u003c/version\u003e\n    \u003cscope\u003etest\u003c/scope\u003e\n\u003c/dependency\u003e\n```\n\u003c!-- x-release-please-end --\u003e\n\n---\n\n1. Write jdoc gherkin feature using `\u003ccode lang=\"gherkin\"\u003e` tag:\n\n```java\n/**\n * \u003cpre\u003e\u003ccode lang=\"gherkin\"\u003e\n * Feature: foo() invokes bar()\n *   Scenario: invoke foo()\n *     When invoke foo()\n *     Then bar() invoked\n * \u003c/code\u003e\u003c/pre\u003e\n */\npublic class Foo {\n\n    private final Bar bar;\n\n    public Foo(Bar bar) {\n        this.bar = bar;\n    }\n\n    public void foo() {\n        bar.bar();\n    }\n}\n```\n\n2. Provide cucumber and jdoc-cucumber test dependencies.\n\n`build.gradle` example:\n\u003cpre\u003e\nrepositories {\n    mavenCentral()\n}\n\ndependencies {\n    \u003c!-- x-release-please-version --\u003etestRuntimeOnly \"io.github.boolivar.jdoctest:jdoc-cucumber:0.11.0\"\n    testImplementation \"io.cucumber:cucumber-java:7.17.0\"\n}\n\u003c/pre\u003e\n\n\u003e [!IMPORTANT]\n\u003e `jdoc-cucumber` versions before `0.9.0` available only on [jitpack](https://jitpack.io/#boolivar/jdoc-test).\n\u003e\n\u003e `build.gradle` example:\n\u003e ```gradle\n\u003e repositories {\n\u003e     maven { url \"https://jitpack.io\" }\n\u003e }\n\u003e dependencies {\n\u003e     testRuntimeOnly \"io.github.boolivar.jdoctest:jdoc-cucumber:0.8.1\"\n\u003e     testImplementation \"io.cucumber:cucumber-java:7.17.0\"\n\u003e }\n\u003e ```\n\n3. Write cucumber step definitions.\n\n```java\nimport io.cucumber.java.en.Then;\nimport io.cucumber.java.en.When;\n\nimport static org.mockito.BDDMockito.*;\n\npublic class StepDefinitions {\n\n    private final Bar bar = mock(Bar.class);\n\n    private final Foo foo = new Foo(bar);\n\n    @When(\"invoke foo()\")\n    public void invokeFoo() {\n        foo.foo();\n    }\n\n    @Then(\"bar() invoked\")\n    public void verifyBarInvoked() {\n        then(bar).should().bar();\n    }\n}\n```\n\n4. Set up paths to java sources using test suite `@SelectDirectories` or `@SelectFile` and step definitions package\nusing `io.cucumber.junit.platform.engine.Constants.GLUE_PROPERTY_NAME` configuration parameter:\n\n```java\nimport org.junit.platform.suite.api.ConfigurationParameter;\nimport org.junit.platform.suite.api.IncludeEngines;\nimport org.junit.platform.suite.api.SelectDirectories;\nimport org.junit.platform.suite.api.Suite;\n\nimport static io.cucumber.junit.platform.engine.Constants.GLUE_PROPERTY_NAME;\n\n@Suite\n@IncludeEngines(\"jdoc-cucumber\")\n@SelectDirectories(\"src/main/java\")\n@ConfigurationParameter(key = GLUE_PROPERTY_NAME, value = \"step.definitions.package\")\npublic class JdocCucumberTestSuite {\n}\n```\n\n5. Run tests with `jdoc-cucumber` junit engine.\n\n`gradle` example:\n```sh\ngradle test\n```\n\n### jdoc-cucumber-gradle-plugin\n\n---\n\nGradle plugin available on [gradle plugin portal](https://plugins.gradle.org/plugin/io.github.boolivar.jdoctest.jdoc-cucumber) that automates cucumber feature generation and cucumber testing tasks.\n\n#### Minimal configuration:\n`build.gradle`:\n\u003c!-- x-release-please-start-version --\u003e\n```gradle\nplugins {\n    id \"java\"\n    id \"io.github.boolivar.jdoctest.jdoc-cucumber\" version \"0.11.0\"\n}\n\nrepositories {\n    mavenCentral()\n}\n\ncheck.dependsOn jdocCucumberTest\n```\n\u003c!-- x-release-please-end --\u003e\n\n```sh\ngradle check\n```\n\n#### jdocCucumber extension\n`build.gradle` example:\n```gradle\njdocCucumber {\n    gluePackages = [\"org.bool.cucumber.stepdefs\"]\n    cucumberVersion = \"7.18.1\"\n    sources = sourceSets.custom.java\n}\n```\n\n| Extension property | Type | Default value | Description |\n| ------------------ | ---- | ------------- | ----------- |\n| `outputDir` | `Directory` | project.layout.buildDirectory.dir(\"generated/sources/jdoc-cucumber\") | Path to store generated features |\n| `langTag` | `String` | \"gherkin\" | `lang` tag to parse. Only `\u003ccode lang=\"\u003clangTag\u003e\"\u003e` javadoc blocks will be parsed and written as features |\n| `sources` | `FileCollection` | sourceSets.main.java.sourceDirectories | source directories to search java files with jdoc-cucumber comments |\n| `cucumberVersion` | `String` | \"7.17.0\" | `io.cucumber:cucumber-java` dependency version to register in `testImplementation` configuration |\n| `gluePackages` | `List\u003cString\u003e` | | List of packages with cucumber glue code |\n\n#### Tasks\nWhen `java` plugin is applied to a project, `jdoc-cucumber` plugin registers `io.cucumber:cucumber-java` dependency in `testImplementation` configuration and creates 2 tasks:\n- **generateCucumberFeatures** - `JdocCucumberTask`  \n  Generates cucumber features from javadocs and stores them in `jdocCucumber.outputDir` path.\n- **jdocCucumberTest** - `JavaExec`  \n  _Depends on:_ all tasks with type `JdocCucumberTask`. Runs cucumber tests using cucumber CLI Runner. \n\n\u003e [!NOTE]\n\u003e By default `jdocCucumberTest` task is **not a dependency** for `check` task. To include `jdocCucumberTest` in build this should be configured manually.\n\u003e\n\u003e `build.gradle` example:\n\u003e ```gradle\n\u003e check.dependsOn jdocCucumberTest\n\u003e ```\n\n### jdoc-spock-gradle-plugin\n\n---\n\nGradle plugin available on [gradle plugin portal](https://plugins.gradle.org/plugin/io.github.boolivar.jdoctest.jdoc-spock) that automates spockframework specs generation and testing tasks.\n\n#### Configuration example\n`build.gradle`:\n\u003c!-- x-release-please-start-version --\u003e\n```gradle\nplugins {\n    id \"java\"\n    id \"io.github.boolivar.jdoctest.jdoc-spock\" version \"0.11.0\"\n}\n\nrepositories {\n    mavenCentral()\n}\n\njdocSpockTest {\n    testLogging {\n        events \"passed\", \"skipped\", \"failed\"\n    }\n}\n\ncheck.dependsOn jdocSpockTest\n```\n\u003c!-- x-release-please-end --\u003e\n\n```sh\ngradle check\n```\n\n#### Reacting to the java plugin\nWhen `java` plugin is applied to a project, `jdoc-spock` plugin:\n- applies `groovy` plugin\n- creates source set `jdocSpock` with groovy sources configured to outputDir property of extension\n- registers `org.spockframework:spock-core` as implementation dependency for `jdocSpock` source set\n- registers `net.bytebuddy:byte-buddy` and `org.objenesis:objenesis` as runtimeOnly dependencies for `jdocSpock` source set\n- creates `generateSpockSpecs` task\n- creates `jdocSpockTest` task\n- configures `compileJdocSpockGroovy` task to depend on `generateSpockSpecs` task\n\n#### jdocSpock extension\n`build.gradle` example:\n```gradle\njdocSpock {\n    outputDir = project.layout.buildDirectory.dir(\"spock-specs\")\n    spockVersion = \"2.3-groovy-4.0\"\n    byteBuddyVersion = null\n    objenesisVersion = null\n}\n```\n\n| Extension property | Type | Default value | Description |\n| ------------------ | ---- | ------------- | ----------- |\n| `outputDir` | `Directory` | project.layout.buildDirectory.dir(\"generated/sources/jdoc-spock\") | Path to store generated groovy specs |\n| `langTag` | `String` | \"spock\" | `lang` tag to parse. Only `\u003ccode lang=\"\u003clangTag\u003e\"\u003e` javadoc blocks will be parsed and included in spec generation |\n| `sources` | `FileCollection` | sourceSets.main.java.sourceDirectories | source directories to search java files with jdoc-spock comments |\n| `classPath` | `FileCollection` | sourceSets.jdocSpock.compileClasspath | Classpath for mockable constructor search during spec generation. |\n| `spockVersion` | `String` | \"2.3-groovy-4.0\" | `org.spockframework:spock-core` dependency version to register in `jdocSpockImplementation` configuration |\n| `byteBuddyVersion` | `String` | \"1.14.15\" | `net.bytebuddy:byte-buddy` dependency version to register in `jdocSpockRuntimeOnly` configuration, `null` value will exclude dependency. |\n| `objenesisVersion` | `String` | \"3.3\" | `org.objenesis:objenesis` dependency version to register in `jdocSpockRuntimeOnly` configuration, `null` value will exclude dependency. |\n\n#### Tasks\n- **generateSpockSpecs** - `JdocSpockTask`  \n  _Depends on:_ `compileJava`. Generates spockframework test specs from javadocs and stores them in `jdocSpock.outputDir` path.\n- **jdocSpockTest** - `Test`  \nRuns spockframework tests using junit platform . \n\n\u003e [!NOTE]\n\u003e By default `jdocSpockTest` task is **not a dependency** for `check` task. To include `jdocSpockTest` in build this should be configured manually.\n\u003e \n\u003e `build.gradle` example:\n\u003e\n\u003e ```gradle\n\u003e check.dependsOn jdocSpockTest\n\u003e ```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fboolivar%2Fjdoc-test","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fboolivar%2Fjdoc-test","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fboolivar%2Fjdoc-test/lists"}