Tools for verifying transitive test coverage proofs.
This namespace provides functions to verify that a function and all its transitive dependencies have declared test coverage. This enables building a provable chain of tests from low-level functions up to application logic.
Additionally, it supports staleness detection: when a function's source code changes after a test was sealed, the coverage is marked as stale until the developer reviews and re-seals the test.
Configuration:
Configuration is automatically loaded from .fulcro-spec.edn in the project root
when first needed. You can also use configure! to set options programmatically:
Example .fulcro-spec.edn: {:scope-ns-prefixes #{"myapp" "myapp.lib"} :enforce? false}
Or programmatically: (proof/configure! {:scope-ns-prefixes #{"myapp"}})
Tools for verifying transitive test coverage proofs.
This namespace provides functions to verify that a function and all its
transitive dependencies have declared test coverage. This enables building
a provable chain of tests from low-level functions up to application logic.
Additionally, it supports staleness detection: when a function's source code
changes after a test was sealed, the coverage is marked as stale until the
developer reviews and re-seals the test.
Configuration:
Configuration is automatically loaded from `.fulcro-spec.edn` in the project root
when first needed. You can also use `configure!` to set options programmatically:
- :scope-ns-prefixes - set of namespace prefix strings to include (e.g. #{"myapp"})
- :enforce? - when true, when-mocking!! and provided!! will throw on missing coverage
Example .fulcro-spec.edn:
{:scope-ns-prefixes #{"myapp" "myapp.lib"}
:enforce? false}
Or programmatically:
(proof/configure! {:scope-ns-prefixes #{"myapp"}})(assert-transitive-coverage! fn-sym)(assert-transitive-coverage! fn-sym opts)Assert that fn-sym has complete transitive coverage (no uncovered or stale deps). Throws an exception if any in-scope dependency lacks coverage or is stale. Used by when-mocking!! at test time.
When called without opts, uses global config. Only throws if :enforce? is true in config (or if opts explicitly passed).
Assert that fn-sym has complete transitive coverage (no uncovered or stale deps). Throws an exception if any in-scope dependency lacks coverage or is stale. Used by when-mocking!! at test time. When called without opts, uses global config. Only throws if :enforce? is true in config (or if opts explicitly passed).
(compare-to-baseline baseline)Compares current function signatures against a saved baseline.
Returns a map showing which functions have changed since the baseline was generated. Useful for determining which tests need to run.
baseline - Map with :signatures {fn-sym signature} as returned by export-baseline
Returns: {:changed #{fn-sym ...} - functions whose signatures differ :added #{fn-sym ...} - functions not in baseline :removed #{fn-sym ...} - functions no longer in scope :unchanged #{fn-sym ...} - functions with matching signatures}
Compares current function signatures against a saved baseline.
Returns a map showing which functions have changed since the baseline
was generated. Useful for determining which tests need to run.
baseline - Map with :signatures {fn-sym signature} as returned by export-baseline
Returns: {:changed #{fn-sym ...} - functions whose signatures differ
:added #{fn-sym ...} - functions not in baseline
:removed #{fn-sym ...} - functions no longer in scope
:unchanged #{fn-sym ...} - functions with matching signatures}(configure! opts)Configure global proof settings. Options:
This overrides any configuration from .fulcro-spec.edn.
Configure global proof settings. Options:
- :scope-ns-prefixes - Set of namespace prefix strings that define which
namespaces are 'in scope' for coverage checking.
E.g., #{"myapp"} includes myapp.core, myapp.db, etc.
- :enforce? - When true, when-mocking!! and provided!! will throw exceptions
if mocked functions lack transitive coverage. When false, they
behave like when-mocking!/provided!. Default: false.
This overrides any configuration from .fulcro-spec.edn.(coverage-stats)(coverage-stats scope-ns-prefixes)Returns coverage statistics for functions in the given namespace scope.
Uses global config if no argument provided.
Returns map with:
Returns coverage statistics for functions in the given namespace scope. Uses global config if no argument provided. Returns map with: - :total - total number of guardrailed functions in scope - :covered - number with declared coverage - :uncovered - number without coverage - :stale - number with stale coverage - :fresh - number with fresh (up-to-date) coverage - :coverage-pct - percentage covered (including stale)
(export-baseline)(export-baseline scope-ns-prefixes)Exports current function signatures as a baseline for future comparison.
Computes signatures for all guardrailed functions in scope and returns them as a map suitable for saving to EDN.
Uses global config if no argument provided.
Returns: {:generated-at timestamp :scope-ns-prefixes #{...} :signatures {fn-sym "abc123" ...}}
Exports current function signatures as a baseline for future comparison.
Computes signatures for all guardrailed functions in scope and returns
them as a map suitable for saving to EDN.
Uses global config if no argument provided.
Returns: {:generated-at timestamp
:scope-ns-prefixes #{...}
:signatures {fn-sym "abc123" ...}}(fresh? fn-sym)(fresh? fn-sym scope-ns-prefixes)Returns true if the function has a sealed signature that matches its current source.
A function is fresh when:
Returns false if:
Use sealed? to check if a function has any signature tracking.
Use stale? to check if a sealed function has changed.
Returns true if the function has a sealed signature that matches its current source. A function is fresh when: - It HAS a sealed signature (from a :covers declaration with signature), AND - The sealed signature matches the current computed signature Returns false if: - The function is not sealed (no signature in :covers), OR - The function is stale (signature doesn't match) Use `sealed?` to check if a function has any signature tracking. Use `stale?` to check if a sealed function has changed.
(fully-tested? fn-sym)(fully-tested? fn-sym opts)Returns true if the function and all its transitive dependencies have declared test coverage within the configured scope AND none are stale.
This is the simple query function for checking coverage status.
Configure scope first with configure! or pass opts.
Examples: (fully-tested? 'myapp.orders/create-order) (fully-tested? 'myapp.orders/create-order {:scope-ns-prefixes #{"myapp"}})
Returns true if the function and all its transitive dependencies have
declared test coverage within the configured scope AND none are stale.
This is the simple query function for checking coverage status.
Configure scope first with `configure!` or pass opts.
Examples:
(fully-tested? 'myapp.orders/create-order)
(fully-tested? 'myapp.orders/create-order {:scope-ns-prefixes #{"myapp"}})(get-config)Returns the current proof configuration.
If not explicitly configured via configure!, attempts to load from
.fulcro-spec.edn in the current directory. Falls back to defaults
if no config file exists (with a warning).
Returns the current proof configuration. If not explicitly configured via `configure!`, attempts to load from `.fulcro-spec.edn` in the current directory. Falls back to defaults if no config file exists (with a warning).
(print-coverage-report fn-sym)(print-coverage-report fn-sym opts)Print a human-readable coverage report for a function.
fn-sym - Fully qualified symbol of the function to check opts - Optional map with :scope-ns-prefixes (uses global config if not provided)
Print a human-readable coverage report for a function. fn-sym - Fully qualified symbol of the function to check opts - Optional map with :scope-ns-prefixes (uses global config if not provided)
(print-reseal-advice)(print-reseal-advice scope-ns-prefixes)Prints human-readable advice for resealing stale tests.
For each stale function, shows the new signature to use. Uses global config if no argument provided.
Prints human-readable advice for resealing stale tests. For each stale function, shows the new signature to use. Uses global config if no argument provided.
(reseal-advice)(reseal-advice scope-ns-prefixes)Returns a map of stale functions with advice for resealing.
For each stale function, returns the new signature to use in the test's :covers declaration. This helps developers update their tests when implementations change.
Uses global config if no argument provided.
Returns: {fn-sym {:current-sig "abc123" :test-sym test/my-test}}
Returns a map of stale functions with advice for resealing.
For each stale function, returns the new signature to use in the test's
:covers declaration. This helps developers update their tests when
implementations change.
Uses global config if no argument provided.
Returns: {fn-sym {:current-sig "abc123" :test-sym test/my-test}}(sealed? fn-sym)Returns true if the function has a sealed signature recorded.
A function is sealed when a test declares coverage with a signature: (specification {:covers {`my-fn "abc123"}} ...)
Unsealed functions have coverage declared but no signature for staleness tracking.
Returns true if the function has a sealed signature recorded.
A function is sealed when a test declares coverage with a signature:
(specification {:covers {`my-fn "abc123"}} ...)
Unsealed functions have coverage declared but no signature for staleness tracking.(signature fn-sym)(signature fn-sym scope-ns-prefixes)Returns the current signature for a function.
Automatically returns the appropriate format based on call graph:
Use this to get the signature when sealing a test.
Example: (signature 'myapp.orders/create-order) ;; => "a1b2c3" (leaf) or "a1b2c3,d4e5f6" (non-leaf)
Returns the current signature for a function. Automatically returns the appropriate format based on call graph: - LEAF functions (no in-scope callees): "xxxxxx" (6-char hash of source) - NON-LEAF functions: "xxxxxx,yyyyyy" (self + callee hash) Use this to get the signature when sealing a test. Example: (signature 'myapp.orders/create-order) ;; => "a1b2c3" (leaf) or "a1b2c3,d4e5f6" (non-leaf)
(stale-coverage)(stale-coverage scope-ns-prefixes)Returns a map of all functions with stale coverage in the given scope.
For each stale function, returns:
Uses global config if no argument provided.
Returns a map of all functions with stale coverage in the given scope. For each stale function, returns: - :sealed-sig - the signature recorded when test was sealed - :current-sig - the current signature of the function - :tested-by - the test(s) covering this function Uses global config if no argument provided.
(stale-functions)(stale-functions scope-ns-prefixes)Returns a set of all functions with stale coverage in scope.
Uses global config if no argument provided.
Returns a set of all functions with stale coverage in scope. Uses global config if no argument provided.
(stale? fn-sym)(stale? fn-sym scope-ns-prefixes)Returns true if the function has a sealed signature that differs from current.
A stale function means its implementation has changed since the covering test was sealed. The test needs review and re-sealing.
Returns false if:
Returns true if the function has a sealed signature that differs from current. A stale function means its implementation has changed since the covering test was sealed. The test needs review and re-sealing. Returns false if: - The function is not sealed (no signature to compare), OR - The function is fresh (signatures match)
(uncovered-in-scope)(uncovered-in-scope scope-ns-prefixes)Find all guardrailed functions in scope that lack test coverage.
Uses global config if no argument provided.
Find all guardrailed functions in scope that lack test coverage. Uses global config if no argument provided.
(verify-transitive-coverage fn-sym)(verify-transitive-coverage fn-sym opts)Verify that fn-sym and all its transitive dependencies have test coverage.
Returns a report map:
Options (optional if global config is set):
Verify that fn-sym and all its transitive dependencies have test coverage. Returns a report map: - :function - the function checked - :scope-ns-prefixes - the namespace scope used - :transitive-deps - all guardrailed functions in the call graph - :covered - set of functions with declared coverage - :uncovered - set of functions without declared coverage - :stale - set of functions with stale coverage (signature mismatch) - :proof-complete? - true if all deps are covered AND none are stale Options (optional if global config is set): - :scope-ns-prefixes - set of namespace prefix strings to include
(why-not-tested? fn-sym)(why-not-tested? fn-sym opts)Returns a map of issues if fn-sym is not fully tested, or nil if fully tested.
The returned map contains:
Examples: (why-not-tested? 'myapp.orders/create-order) ;; => {:uncovered #{myapp.db/save!} :stale #{myapp.validation/check}}
Returns a map of issues if fn-sym is not fully tested, or nil if fully tested.
The returned map contains:
- :uncovered - set of functions without declared coverage
- :stale - set of functions with stale coverage (signature mismatch)
Examples:
(why-not-tested? 'myapp.orders/create-order)
;; => {:uncovered #{myapp.db/save!} :stale #{myapp.validation/check}}cljdoc builds & hosts documentation for Clojure/Script libraries
| Ctrl+k | Jump to recent docs |
| ← | Move to previous article |
| → | Move to next article |
| Ctrl+/ | Jump to the search field |