Class AffectedTestsExtension

java.lang.Object
io.affectedtests.gradle.AffectedTestsExtension

public abstract class AffectedTestsExtension extends Object
DSL extension for configuring the Affected Tests plugin.

Usage in build.gradle:


 affectedTests {
     baseRef = "origin/master"
     // Defaults are COMMITTED-ONLY (both flags default to false) so
     // local runs match CI. Flip to true if you want WIP to seed the
     // diff while iterating on tests locally.
     includeUncommitted = false
     includeStaged = false
     // v2: per-situation actions. See README.md for the full table.
     mode = "ci"
     onEmptyDiff          = "full_suite"
     onAllFilesOutOfScope = "skipped"
     onUnmappedFile       = "full_suite"
     onDiscoveryEmpty     = "full_suite"
     ignorePaths = ["**/generated/**"]
     outOfScopeTestDirs = ["api-test/src/test/java"]
     strategies = ["naming", "usage", "impl", "transitive"]
     transitiveDepth = 4
     parallelDiscovery = true
     testSuffixes = ["Test", "IT", "ITTest", "IntegrationTest"]
     sourceDirs = ["src/main/java"]
     testDirs = ["src/test/java"]
     includeImplementationTests = true
     implementationNaming = ["Impl", "Default"]
 }
 
  • Constructor Summary

    Constructors
    Constructor
    Description
     
  • Method Summary

    Modifier and Type
    Method
    Description
    abstract org.gradle.api.provider.Property<String>
    Git base ref to diff against.
    abstract org.gradle.api.provider.Property<Long>
    Wall-clock timeout in seconds for the nested ./gradlew invocation that executes the affected / full test suite.
    abstract org.gradle.api.provider.Property<Integer>
    Issue #132 — how many header-edge hops the strategy walks from each changed class.
    abstract org.gradle.api.provider.Property<Boolean>
    Issue #132 — kill switch for the headerEdges discovery strategy.
    abstract org.gradle.api.provider.ListProperty<String>
    Issue #132 — header-edge categories whose contributions are skipped during augmentation.
    abstract org.gradle.api.provider.ListProperty<String>
    Issue #132 — globs (Java-style **-prefixed FQN patterns) for types whose header-edge contributions are ignored.
    abstract org.gradle.api.provider.Property<Integer>
    Issue #132 — sibling-cap on the explosion vector.
    abstract org.gradle.api.provider.ListProperty<String>
    Glob patterns for files that must never influence test selection — for purely documentation, build metadata, or generated artifacts.
    abstract org.gradle.api.provider.ListProperty<String>
    Implementation naming prefixes/suffixes (e.g.
    abstract org.gradle.api.provider.Property<Boolean>
    Include tests for implementations of changed interfaces/base classes.
    abstract org.gradle.api.provider.Property<Boolean>
    Include staged changes.
    abstract org.gradle.api.provider.Property<Boolean>
    Include uncommitted (unstaged) changes.
    abstract org.gradle.api.provider.Property<Boolean>
    Whether to register the Kotlin AST-driven parser for .kt files (issue #76 Phase 2, PR #4).
    abstract org.gradle.api.provider.Property<String>
    Execution profile ("auto", "local", "ci", or "strict").
    abstract org.gradle.api.provider.Property<String>
    Action to take when every file in the diff matched getIgnorePaths().
    abstract org.gradle.api.provider.Property<String>
    Action to take when every file in the diff sat under getOutOfScopeTestDirs() or getOutOfScopeSourceDirs().
    abstract org.gradle.api.provider.Property<String>
    Action to take when discovery completes but returns no tests.
    abstract org.gradle.api.provider.Property<String>
    Action to take when discovery ran but at least one scanned Java file failed to parse — see Situation.DISCOVERY_INCOMPLETE on the core module for the full rationale.
    abstract org.gradle.api.provider.Property<String>
    Action to take on an empty git diff.
    abstract org.gradle.api.provider.Property<String>
    Action to take when the diff contains at least one unmapped file (non-Java, outside configured source/test dirs).
    abstract org.gradle.api.provider.ListProperty<String>
    Production source directories the plugin must treat as out-of-scope.
    abstract org.gradle.api.provider.ListProperty<String>
    Test source directories (e.g.
    abstract org.gradle.api.provider.Property<Boolean>
    Whether to fan the four discovery strategies out across a small thread pool (default true) or run them serially.
    abstract org.gradle.api.provider.ListProperty<String>
    Production source directories (relative to each module root).
    abstract org.gradle.api.provider.ListProperty<String>
    Strategies to use for test discovery.
    abstract org.gradle.api.provider.ListProperty<String>
    Test source directories (relative to each module root).
    abstract org.gradle.api.provider.ListProperty<String>
    Test class suffixes used by the naming strategy.
    abstract org.gradle.api.provider.ListProperty<String>
    Names of the Gradle test tasks the dispatch path may invoke (one nested ./gradlew call per module × taskName pair).
    abstract org.gradle.api.provider.Property<Integer>
    How many levels of transitive dependencies to follow when the transitive strategy is enabled.
    void
    setExcludePaths(List<?> ignored)
    Migration shim: excludePaths was removed in v2.0.
    void
    Migration shim: runAllIfNoMatches was removed in v2.0.
    void
    Migration shim: runAllOnNonJavaChange was removed in v2.0.

    Methods inherited from class java.lang.Object

    clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
  • Constructor Details

    • AffectedTestsExtension

      public AffectedTestsExtension()
  • Method Details

    • getBaseRef

      public abstract org.gradle.api.provider.Property<String> getBaseRef()
      Git base ref to diff against. Default: "origin/master".
      Returns:
      the base ref property
    • getIncludeUncommitted

      public abstract org.gradle.api.provider.Property<Boolean> getIncludeUncommitted()
      Include uncommitted (unstaged) changes. Default: false — committed-only semantics match CI. Set to true if you iterate on WIP locally and want the unstaged edits to seed the diff boundary.
      Returns:
      the include uncommitted property
    • getIncludeStaged

      public abstract org.gradle.api.provider.Property<Boolean> getIncludeStaged()
      Include staged changes. Default: false. See getIncludeUncommitted() for the rationale.
      Returns:
      the include staged property
    • getStrategies

      public abstract org.gradle.api.provider.ListProperty<String> getStrategies()
      Strategies to use for test discovery. Valid values: "naming", "usage", "impl", "transitive". Default: all four.

      The transitive strategy additionally respects transitiveDepth.

      Returns:
      the strategies list property
    • getTransitiveDepth

      public abstract org.gradle.api.provider.Property<Integer> getTransitiveDepth()
      How many levels of transitive dependencies to follow when the transitive strategy is enabled. Default: 4 — matches the depth most Java controller → service → repository chains actually reach in Modulr-shaped codebases while leaving one level of margin. Range: 0–5.
      Returns:
      the transitive depth property
    • getParallelDiscovery

      public abstract org.gradle.api.provider.Property<Boolean> getParallelDiscovery()
      Whether to fan the four discovery strategies out across a small thread pool (default true) or run them serially. Engine- level parallelism is the Stage 1 win for issue #42; on the workloads we've measured it cuts discovery wall time by ~2x with no algorithmic change. Adopters can flip to false if a custom strategy fork or a JavaParser regression we have not seen yet introduces a race; the serial path remains a one-line fallback.

      The Gradle property -PaffectedTestsParallelDiscovery=false provides the same kill switch without touching the DSL. The property accepts true|false|1|0|on|off|yes|no (case-insensitive); typo'd values are rejected with a build-log WARN rather than silently flipping the switch.

      Returns:
      the parallel-discovery property
    • getKotlinEnabled

      public abstract org.gradle.api.provider.Property<Boolean> getKotlinEnabled()
      Whether to register the Kotlin AST-driven parser for .kt files (issue #76 Phase 2, PR #4). Defaults to true — Kotlin sources participate in AST-driven discovery (Usage / Implementation / Transitive) on every run.

      When true, KotlinLanguageParser is registered with the per-engine LanguageParsers registry; AST-driven strategies start producing matches for Kotlin files; embeddable bootstrap failures fail closed via DISCOVERY_INCOMPLETE (the WARN is logged once and every .kt in the run is treated as unparseable).

      When false, .kt files fall back to the Phase 1 (PR #1) shape: path-derived FQN routing on the diff side, no AST-driven strategy participation, no DISCOVERY_INCOMPLETE on unparsed Kotlin — the absence is "by design" rather than a parse failure. Use this kill switch only as a regression escape hatch; PR #4 removed the -Daffected-tests.kotlin.enabled system property because the rollout window closed and the AST path is now first-class.

      Returns:
      the Kotlin-enabled property
    • getHeaderEdgesEnabled

      public abstract org.gradle.api.provider.Property<Boolean> getHeaderEdgesEnabled()
      Issue #132 — kill switch for the headerEdges discovery strategy. true (default) walks class-header type references (extends / implements / permits / generic bounds / record components / class-level annotations) and augments the changed-class set with the resolved targets before the four pre-existing strategies (naming / usage / impl / transitive) run. false disables every category at once and reverts plugin behaviour to byte-for-byte identical to pre-issue-#132. Adopters who want per-category opt-out use getHeaderEdgesExclude() instead so the rest of the strategy keeps firing.
      Returns:
      the headerEdges-enabled property
    • getHeaderEdgesExclude

      public abstract org.gradle.api.provider.ListProperty<String> getHeaderEdgesExclude()
      Issue #132 — header-edge categories whose contributions are skipped during augmentation. Adopters EXCLUDE (not include) — every category is on by default; this list is the surgical opt-out. Valid entries: "extends", "implements", "permits", "type-bounds", "record-components", "annotations". Entries are case-insensitive; unknown entries are rejected at config time (a silent ignore of a typo would leave the adopter expecting their opt-out applied when it wasn't).

      Common opt-out shapes:

      • headerEdgesExclude = ["annotations"] — adopter uses many custom class-level annotations that don't carry test-relevant behaviour. Most frequent opt-out.
      • headerEdgesExclude = ["record-components"] — DTO-heavy codebases where record components are pure data carriers.
      Returns:
      the headerEdgesExclude list property
    • getHeaderEdgesDepth

      public abstract org.gradle.api.provider.Property<Integer> getHeaderEdgesDepth()
      Issue #132 — how many header-edge hops the strategy walks from each changed class. 1 (default) walks the immediate header-declared types only; 2 walks one more level. Clamped to [0, 2] at the builder gate; higher values rapidly approach FULL_SUITE selection on real codebases because almost every concrete class transitively reaches Object's consumer base. 0 is treated identically to headerEdgesEnabled = false.
      Returns:
      the headerEdges depth property
    • getHeaderEdgesMaxSiblings

      public abstract org.gradle.api.provider.Property<Integer> getHeaderEdgesMaxSiblings()
      Issue #132 — sibling-cap on the explosion vector. When a header-edge-added type has more direct subtypes than this value, the impl strategy's downward walk from THAT added type is suppressed; the added type still contributes via naming / usage / transitive. Default: 5.

      Motivating case: PaymentController extends BaseController with BaseController owning 52 subclasses. Without the cap, walking extends would add BaseController to the changed set and the impl strategy would then walk DOWN through all 52 subtypes, selecting every *ControllerTest in the codebase. The cap is the surgical fix — BaseController still adds BaseControllerTest via naming, but the 52-way fan-out is skipped and recorded in --explain as SKIPPED downward impl-walk from BaseController (52 subtypes > headerEdgesMaxSiblings=5).

      Set to 0 to suppress every downward walk from a header-edge-added type. Setting it negative is rejected at config time.

      Returns:
      the headerEdgesMaxSiblings property
    • getHeaderEdgesIgnore

      public abstract org.gradle.api.provider.ListProperty<String> getHeaderEdgesIgnore()
      Issue #132 — globs (Java-style **-prefixed FQN patterns) for types whose header-edge contributions are ignored. Default covers framework / JDK / Lombok / JUnit / Mockito / Kotlin / Groovy types that pollute selection without contributing signal: java.lang.**, java.util.**, org.springframework.**, org.junit.**, lombok.**, kotlin.**, groovy.lang.**, and the javax / jakarta equivalents.

      When unset, the core AffectedTestsConfig default list applies. Adopters typically EXTEND rather than replace: setting an explicit list overrides the default entirely, so a project that wants to add a single extra glob should concatenate with the default rather than supply only the one entry.

      Returns:
      the headerEdgesIgnore list property
    • getTestSuffixes

      public abstract org.gradle.api.provider.ListProperty<String> getTestSuffixes()
      Test class suffixes used by the naming strategy. Default: ["Test", "IT", "ITTest", "IntegrationTest"].
      Returns:
      the test suffixes list property
    • getSourceDirs

      public abstract org.gradle.api.provider.ListProperty<String> getSourceDirs()
      Production source directories (relative to each module root). Default: ["src/main/java"].
      Returns:
      the source dirs list property
    • getTestDirs

      public abstract org.gradle.api.provider.ListProperty<String> getTestDirs()
      Test source directories (relative to each module root). Default: ["src/test/java"].
      Returns:
      the test dirs list property
    • getTestTaskNames

      public abstract org.gradle.api.provider.ListProperty<String> getTestTaskNames()
      Names of the Gradle test tasks the dispatch path may invoke (one nested ./gradlew call per module × taskName pair). Default: ["test"].

      Adopters with extra source sets opt them in here: testTaskNames = ["test", "integrationTest"]. The dispatch path routes each discovered FQN to the task whose source-set directory the FQN's file sits under, by the standard Gradle convention src/<taskName>/java. When setting this knob, callers typically also extend getTestDirs() to include the corresponding source-set directories so the discovery passes scan them — otherwise the extra source sets stay invisible to discovery and the new task name has nothing to dispatch.

      Returns:
      the test task names list property
    • getIgnorePaths

      public abstract org.gradle.api.provider.ListProperty<String> getIgnorePaths()
      Glob patterns for files that must never influence test selection — for purely documentation, build metadata, or generated artifacts. A diff consisting entirely of ignored paths routes through Situation.ALL_FILES_IGNORED.

      When unset, the core AffectedTestsConfig default list applies (markdown, generated/, text/licence/changelog, images).

      Returns:
      the ignore paths list property
    • getOutOfScopeTestDirs

      public abstract org.gradle.api.provider.ListProperty<String> getOutOfScopeTestDirs()
      Test source directories (e.g. "api-test/src/test/java") whose contents the plugin must not dispatch via the affectedTest task. A diff entirely under these directories routes through Situation.ALL_FILES_OUT_OF_SCOPE. Intended for Cucumber/api-test, performance, or other non-unit-test source sets.
      Returns:
      the out-of-scope test dirs list property
    • getOutOfScopeSourceDirs

      public abstract org.gradle.api.provider.ListProperty<String> getOutOfScopeSourceDirs()
      Production source directories the plugin must treat as out-of-scope. A diff entirely under these dirs routes through Situation.ALL_FILES_OUT_OF_SCOPE.
      Returns:
      the out-of-scope source dirs list property
    • getIncludeImplementationTests

      public abstract org.gradle.api.provider.Property<Boolean> getIncludeImplementationTests()
      Include tests for implementations of changed interfaces/base classes. Default: true.
      Returns:
      the include implementation tests property
    • getImplementationNaming

      public abstract org.gradle.api.provider.ListProperty<String> getImplementationNaming()
      Implementation naming prefixes/suffixes (e.g. "Impl" matches FooBarImpl for FooBar; "Default" matches DefaultFooBar for FooBar). Default: ["Impl", "Default"].
      Returns:
      the implementation naming list property
    • getMode

      public abstract org.gradle.api.provider.Property<String> getMode()
      Execution profile ("auto", "local", "ci", or "strict"). Controls per-situation default actions when the explicit onXxx setting is not set.

      Default: unset — which resolves to Mode.AUTO on the core config. AUTO detects CI via common env vars and picks the CI defaults there, and the LOCAL defaults otherwise.

      Returns:
      the mode property
    • getOnEmptyDiff

      public abstract org.gradle.api.provider.Property<String> getOnEmptyDiff()
      Action to take on an empty git diff. One of "selected", "full_suite", "skipped" (case-insensitive).
      Returns:
      the on-empty-diff property
    • getOnAllFilesIgnored

      public abstract org.gradle.api.provider.Property<String> getOnAllFilesIgnored()
      Action to take when every file in the diff matched getIgnorePaths(). One of "selected", "full_suite", "skipped".
      Returns:
      the on-all-files-ignored property
    • getOnAllFilesOutOfScope

      public abstract org.gradle.api.provider.Property<String> getOnAllFilesOutOfScope()
      Action to take when every file in the diff sat under getOutOfScopeTestDirs() or getOutOfScopeSourceDirs(). One of "selected", "full_suite", "skipped".
      Returns:
      the on-all-files-out-of-scope property
    • getOnUnmappedFile

      public abstract org.gradle.api.provider.Property<String> getOnUnmappedFile()
      Action to take when the diff contains at least one unmapped file (non-Java, outside configured source/test dirs). One of "selected", "full_suite", "skipped". When set to "selected" the engine treats the unmapped file as if it weren't there and continues to discovery — matching pre-v2 runAllOnNonJavaChange=false behaviour.
      Returns:
      the on-unmapped-file property
    • getOnDiscoveryEmpty

      public abstract org.gradle.api.provider.Property<String> getOnDiscoveryEmpty()
      Action to take when discovery completes but returns no tests. One of "selected", "full_suite", "skipped".
      Returns:
      the on-discovery-empty property
    • getOnDiscoveryIncomplete

      public abstract org.gradle.api.provider.Property<String> getOnDiscoveryIncomplete()
      Action to take when discovery ran but at least one scanned Java file failed to parse — see Situation.DISCOVERY_INCOMPLETE on the core module for the full rationale. One of "selected", "full_suite", "skipped".

      Unset falls through to the mode default (CI and STRICT escalate to full_suite; LOCAL keeps the partial selection).

      Returns:
      the on-discovery-incomplete property
    • getGradlewTimeoutSeconds

      public abstract org.gradle.api.provider.Property<Long> getGradlewTimeoutSeconds()
      Wall-clock timeout in seconds for the nested ./gradlew invocation that executes the affected / full test suite. 0 disables the timeout (pre-v1.9.22 default — wait indefinitely). Positive values deadline the child process: the plugin destroys the process tree after the interval and fails the build with a clear error.

      Recommended values: 1800 (30 min) for merge-gate unit-test runs, 3600 (1 hour) for suites that include integration tests. Must be >= 0; the plugin rejects negative values at afterEvaluate (configuration) time and again at task-execution time as belt-and-braces.

      Returns:
      the gradlew timeout property in seconds
    • setRunAllIfNoMatches

      public void setRunAllIfNoMatches(Object ignored)
      Migration shim: runAllIfNoMatches was removed in v2.0. Intercepts a v1-style assignment in Groovy DSL and raises a targeted migration error instead of Gradle's generic "unknown property" failure.
      Parameters:
      ignored - v1 boolean value (never read)
      Throws:
      org.gradle.api.GradleException - always, with a v2 replacement hint
    • setRunAllOnNonJavaChange

      public void setRunAllOnNonJavaChange(Object ignored)
      Migration shim: runAllOnNonJavaChange was removed in v2.0.
      Parameters:
      ignored - v1 boolean value (never read)
      Throws:
      org.gradle.api.GradleException - always, with a v2 replacement hint
    • setExcludePaths

      public void setExcludePaths(List<?> ignored)
      Migration shim: excludePaths was removed in v2.0.
      Parameters:
      ignored - v1 list value (never read)
      Throws:
      org.gradle.api.GradleException - always, with a v2 replacement hint