UnitAutogen

0.16.1

PowerShell module for UnitAutogen - auto-generated tSQLt unit tests with real branch coverage for SQL Server. Installs the framework AND the in-database (SQLCLR) predicate parser, runs generation and coverage, and exports Cobertura XML, JUnit XML, and HTML reports for Azure DevOps, GitHub Actions, Jenkins, GitLab CI, and SonarQube. The single C# predicate parser runs
PowerShell module for UnitAutogen - auto-generated tSQLt unit tests with real branch coverage for SQL Server. Installs the framework AND the in-database (SQLCLR) predicate parser, runs generation and coverage, and exports Cobertura XML, JUnit XML, and HTML reports for Azure DevOps, GitHub Actions, Jenkins, GitLab CI, and SonarQube. The single C# predicate parser runs inside SQL Server (no PowerShell-side parser); installation registers it and requires sysadmin once plus 'clr enabled'=1.
Show more

Minimum PowerShell version

5.1

Installation Options

Copy and Paste the following command to install this package using PowerShellGet More Info

Install-Module -Name UnitAutogen -RequiredVersion 0.16.1

Copy and Paste the following command to install this package using Microsoft.PowerShell.PSResourceGet More Info

Install-PSResource -Name UnitAutogen -Version 0.16.1

You can deploy this package directly to Azure Automation. Note that deploying packages with dependencies will deploy all the dependencies to Azure Automation. Learn More

Manually download the .nupkg file to your system's default download location. Note that the file won't be unpacked, and won't include any dependencies. Learn More

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

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
Show more