UnitAutogen
0.16.1
Minimum PowerShell version
5.1
Installation Options
Owners
Copyright
(C) 2026 Munaf Ibrahim Khatri. Licensed under AGPL-3.0.
Package Details
Author(s)
- Munaf Ibrahim Khatri
Tags
SQL SQLServer tSQLt Coverage CI-CD Cobertura JUnit AzureDevOps Testing UnitTest CodeCoverage BranchCoverage DatabaseTesting AutomatedTesting
Functions
Install-UnitAutogenDatabase Invoke-UnitAutogen Export-CoverageCoberturaXml Export-TestResultsJunitXml Export-CoverageHtmlReport Export-UnitAutogenTests
Dependencies
This module has no dependencies.
Release Notes
## v0.16.1 (beta) - 2026-06-15
Two narrower derived-value and aggregate shapes are now seeded to full branch coverage.
- A derived local that uses SUBTRACTION (e.g. value = qty * price - fee, or qty * price
- 100) is now covered. A subtracted column is neutralised to 0 like any other term; a
subtracted (or added) numeric constant is folded into the knob so the driving term
still crosses the threshold exactly.
- An aggregate gate whose source has a NON-equality filter is now satisfied: numeric
>, >=, <, <= seed a value just inside the bound; IN (...) seeds the first list value;
BETWEEN seeds the low bound. (Equality and date ">=" windows were already handled.)
- Validated on a synthetic loop procedure (100% line + branch); full regression on
AdventureWorks2025 (PredicateZoo aggregate/scalar gates), a JSON/MERGE/transaction
procedure, and a multi-procedure analytics DB all unchanged. No C#/CLR change.
## v0.16.0 (beta) - 2026-06-15
Two more derived-value and aggregate shapes are now seeded to full branch coverage.
- A derived local that MIXES multiplication and addition (e.g. value = qty * price +
fee) is now covered. The generator splits the expression into additive terms, drives
the term holding the chosen column and neutralises the rest, so the computed value
crosses the threshold exactly. Pure-product and pure-sum cases are unchanged.
- An aggregate gate whose source has a NON-date filter (e.g. AVG(Score) FROM Metrics
WHERE Status='ACTIVE') now seeds a row that PASSES the filter instead of a placeholder
the filter excluded (which left the aggregate NULL and the branch uncovered). This also
fixes compound gates that reuse such an aggregate to set a flag.
- Validated on a synthetic loop procedure (100% line + branch); full regression on
AdventureWorks2025 (PredicateZoo aggregate/scalar gates), a JSON/MERGE/transaction
procedure, and a multi-procedure analytics DB all unchanged. No C#/CLR change.
## v0.15.9 (beta) - 2026-06-15
A correctness fix to derived-arithmetic seeding, plus several seeding bug fixes.
- FIX: a witness for a derived-arithmetic branch could PASS without actually COVERING
its arm when the value was derived through an aggregate over another table - the
test's baseline seed row for that table shifted the aggregate, so the computed value
missed the threshold. The generator now clears such aggregate-source tables after the
baseline seeding, so the witness's own seed controls the aggregate. On a trade-
reconciliation procedure this lifted branch coverage from 62.5% to 93.8%.
- More gate shapes are now seeded: an aggregate-band gate over a date-windowed table (a
previous illegal EXEC-argument expression is fixed), an operand assigned from a loop
#temp, and an OR of column comparisons.
- Validated; full regression on AdventureWorks2025 (PredicateZoo), a JSON/MERGE/
transaction procedure, and a multi-procedure analytics DB all unchanged. No C#/CLR change.
## v0.15.8 (beta) - 2026-06-15
Reverse seeding for derived arithmetic locals now also handles compound conditions
and sum / multi-step expressions.
- A compound branch like "IF @AdjustedValue > 100000 AND @WavePatternPhase = 'C'",
where the second test depends on a different source (a flag set from an aggregate
over another table), is now seeded by coordinating BOTH sources: the arithmetic
driver as before, plus a synthesised seed for the aggregate that sets the flag (one
row past the threshold, with any date-window filter satisfied). A compound gate
whose extra condition cannot be satisfied still stays honestly NOT_TESTABLE.
- Derived locals built with addition (a + b) are now handled alongside products, and
the driver is traced through intermediate locals (a = b; b = c * Col) - multi-hop -
to its source column.
- Validated: a trade-reconciliation proc's compound risk-limit branch went from
skipped to covered, and a synthetic loop proc's sum and multi-hop branches reached
100%. Full regression on AdventureWorks2025 (PredicateZoo), a JSON/MERGE/transaction
proc, and a multi-procedure analytics DB all unchanged. No C#/CLR change.
## v0.15.7 (beta) - 2026-06-15
Reverse seeding now covers a branch whose condition compares a DERIVED arithmetic
local to a literal - e.g. "IF @AdjustedValue > 50000" where
@AdjustedValue = @Volume * @Price * @RiskMultiplier is computed from per-row loop
columns and other locals.
- Such a gate was previously skipped NOT_TESTABLE ("comparison does not involve an
aggregate/scalar subquery"). The seeder now traces the operand through its arithmetic
to the source columns, neutralises the co-factor columns (so the product reduces to a
single driving column), pins non-row factors via the existing FakeTable of every
referenced table, and sets the driving column deterministically just past the literal -
covering the arm without a search (which also avoids the per-gate sweep timeout on loop
procedures).
- Restricted to a simple single comparison; a compound gate (e.g. "@v > 100000 AND
@phase = 'C'") with a conjunct the path cannot satisfy stays honestly NOT_TESTABLE.
- Validated on a trade-reconciliation loop procedure (two derived-local arms skip ->
covered, with verified seeds + an OUTPUT assertion); full regression on
AdventureWorks2025 (PredicateZoo), a JSON/MERGE/transaction procedure, and a
multi-procedure analytics database all unchanged. No C#/CLR change.
## v0.15.6 (beta) - 2026-06-15
Statement-aware coverage instrumentation - dense one-liner procedures now report
honest branch coverage instead of a false 0%.
- A procedure written with an IF, its THEN body, and its ELSE all on one physical
line (or several statements separated by ; on one line) previously defeated the
line-based coverage walker: the branch arms shared the predicate's line, so none
could be measured (0% branch) even though the generated tests exercised them all.
- A new normalization pass (run before instrumentation) reformats such lines onto
canonical one-statement-per-line form so every arm is measured. It is quote /
comment / bracket / paren / CASE aware (a CASE expression's WHEN/THEN/ELSE/END is
never mistaken for control flow), idempotent, and a no-op on already-well-formatted
procedures - so it changes nothing for procedures that already measured correctly.
- Validated: a dense IF/ELSE procedure went from a false 0% branch to a true 100%
(6/6) with no source change; full regression on AdventureWorks2025 (PredicateZoo),
a JSON/MERGE/transaction procedure, and a multi-procedure analytics database all
unchanged. No C#/CLR change.
## v0.15.5 (beta) - 2026-06-14
Auto-generation now drives JSON-shredding, transaction-managing procedures to full
coverage - deterministic "deep-gate" witnesses for the branch shapes the iterative
search could not reach.
- A new derivation (TestGen.DeriveDeepGateWitnesses) reads the procedure's own structure -
the key-lookup SELECT (table, key column/param, the local-to-column map), and the
OPENJSON(@param) WITH(...) shred + catalog JOIN + filter - and synthesises a valid JSON
parameter literal plus coordinated real-table seeds. It then emits verified witness tests for:
parameter NULL-guards, @@ROWCOUNT "not found" checks, key-lookup status scalars
(e.g. an "is active" flag), and aggregate gates over a table VARIABLE populated by the JSON
shred (e.g. total-due vs a credit-limit column, or a shortage count) - pivoting the seed to
the comparand's real source column instead of the un-seedable table variable - plus a
happy-path scenario that falls through every gate.
- These run BEFORE the iterative search, which now skips any gate already witnessed - so this
whole class of procedure is covered deterministically and fast (no per-candidate sweep).
- Self-contained witnesses (which provide their own arguments + seeds) no longer get a
spurious ExpectException when the procedure catches its own RAISERROR internally.
- The generic base tests are also more robust on this proc shape: a parameter consumed by
OPENJSON gets valid JSON in the smoke tests (not arbitrary text that breaks parsing); the
"raises"/"rejects" error-expectation tests are skipped when the procedure swallows its own
errors in a non-rethrowing CATCH; and the OUTPUT constant-skeleton no longer mashes a literal
that is a substring of a longer one (e.g. ''SUCCESS'' inside ''FULL_SUCCESS'').
- Validated: a complex order-processing proc (OPENJSON shred + window CTEs + MERGE + a
self-managed transaction with several rejection paths) goes from a partial result to
100% line (35/35) and 100% branch (6/6), with the whole generated suite green
(11 passed / 0 failed / 0 errored / 8 honest skips).
PredicateZoo regression on AdventureWorks2025 green (deep-gate derivation is a no-op on
procedures without that shape). No C#/CLR change.
- The generic boundary "accepts" tests are no longer falsely skipped on a procedure that manages
its own transaction: the generation-time probe now recognises that a "mismatching BEGIN and
COMMIT" error (266) is the procedure's own transaction control, not a rejected input.
- NEW TestGen.RunTests @SchemaName, @ProcName runs a procedure's generated tests and returns
pass/fail. It handles a procedure that manages its OWN transactions - which a direct tSQLt.Run
cannot, because the procedure's ROLLBACK collapses tSQLt's per-test transaction and FakeTable
setup - by running those tests against the transaction-neutralized shadow (reusing the coverage
swap; no coverage permission required, it degrades gracefully). Plain procedures run directly.
## Earlier releases
Full release history (v0.12.0 back to v0.9.0) is in CHANGES.md and on the GitHub
Releases page: https://github.com/unitautogen/unitautogen-public-repo/releases
FileList
- UnitAutogen.nuspec
- UnitAutogen.psd1
- UnitAutogen.psm1
- sql\Install-UnitAutogenClr.SSMS.sql
- sql\Install_UnitAutogen.sql
Version History
| Version | Downloads | Last updated |
|---|---|---|
| 0.16.8 | 5 | 6/22/2026 |
| 0.16.7 | 5 | 6/18/2026 |
| 0.16.1 (current version) | 4 | 6/15/2026 |
| 0.14.1 | 6 | 6/13/2026 |
| 0.14.0 | 4 | 6/12/2026 |
| 0.13.0 | 5 | 6/11/2026 |
| 0.12.0 | 8 | 6/7/2026 |
| 0.11.1 | 5 | 6/7/2026 |
| 0.11.0 | 8 | 6/6/2026 |
| 0.10.0 | 10 | 6/5/2026 |
| 0.9.14 | 18 | 6/4/2026 |
| 0.9.12 | 6 | 6/4/2026 |
| 0.9.11 | 9 | 6/4/2026 |
| 0.9.10 | 10 | 6/4/2026 |
| 0.9.9 | 9 | 6/3/2026 |
| 0.9.2 | 4 | 6/1/2026 |
| 0.9.1 | 4 | 5/30/2026 |
| 0.9.0 | 6 | 5/29/2026 |