Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Fixed
- #39: Fixed bug where results viewer gave divide by zero error when there were 0 executed methods in the covered code

### Added
- #42: Added a listener interface and manager with an associated user parameter, allowing the user to broadcast output on test method/case/suite completion.

## [3.1.0] - 2024-07-05

### Added
Expand Down
8 changes: 8 additions & 0 deletions cls/TestCoverage/Listeners/ListenerInterface.cls
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
Class TestCoverage.Listeners.ListenerInterface Extends %RegisteredObject
{

Method Broadcast(pMessage As %DynamicObject) As %Status [ Abstract ]
{
}

}
48 changes: 48 additions & 0 deletions cls/TestCoverage/Listeners/ListenerManager.cls
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
Class TestCoverage.Listeners.ListenerManager Extends %RegisteredObject
{

Property listeners As list Of TestCoverage.Listeners.ListenerInterface;

Method BroadCastToAll(pMessage As %DynamicObject) As %Status
{
set tSC = $$$OK
try {
for i = 1:1:..listeners.Count() {
set tListener = ..listeners.GetAt(i)
$$$ThrowOnError(tListener.Broadcast(pMessage))
}
}
catch e {
Set tSC = e.AsStatus()
}
quit tSC
}

Method AddListener(pListener As TestCoverage.Listeners.ListenerInterface) As %Status
{
set tSC = $$$OK
try {
do ..listeners.Insert(pListener)
} catch e {
set tSC = e.AsStatus()
}
quit tSC
}

Method RemoveListener(pListener As TestCoverage.Listeners.ListenerInterface) As %Status
{
set tSC = $$$OK
try {
set tIndex = ..listeners.FindOref(pListener)
if (tIndex = "") {
Set tMsg = "Listener not found"
$$$ThrowStatus($$$ERROR($$$GeneralError,tMsg))
}
do ..listeners.RemoveAt(tIndex)
} catch e {
set tSC = e.AsStatus()
}
quit tSC
}

}
51 changes: 51 additions & 0 deletions cls/TestCoverage/Manager.cls
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,9 @@ Property Hashes [ MultiDimensional ];

Property Monitor As TestCoverage.Utils.LineByLineMonitor [ InitialExpression = {##class(TestCoverage.Utils.LineByLineMonitor).%New()}, Private ];

/// keeps track of all the listeners that may need information broadcasted about the unit test progress
Property ListenerManager As TestCoverage.Listeners.ListenerManager;

/// Runs unit tests that have been loaded, with code coverage enabled. <br />
/// Note that if coverage is to be tracked for lots of code, it may be necessary to increase the "gmheap" setting
/// (under Configuration - Additional Settings - Advanced Memory in the Management Portal). <br />
Expand Down Expand Up @@ -563,6 +566,7 @@ ClassMethod OnBeforeAllTests(manager As TestCoverage.Manager, dir As %String, By
Set tCoverageRoutines = $Get(userparam("CoverageRoutines"))
Set tCoverageDetail = $Get(userparam("CoverageDetail"))
Set tSourceNamespace = $Get(userparam("SourceNamespace"),$Namespace)
Set tListenerManager = $Get(userparam("ListenerManager"))
Set tProcessIDs = $Get(userparam("ProcessIDs"),$ListBuild($Job))
If (tProcessIDs = "*") {
Set tProcessIDs = ""
Expand All @@ -584,6 +588,7 @@ ClassMethod OnBeforeAllTests(manager As TestCoverage.Manager, dir As %String, By
Set manager.ProcessIDs = tProcessIDs
Set manager.Timing = tTiming
Do manager.SetCoverageTargets(tCoverageClasses,tCoverageRoutines,1)
Set manager.ListenerManager = tListenerManager
If (tCoverageDetail '= "") {
If (tCoverageDetail '= +tCoverageDetail) {
// If we were passed a display value...
Expand Down Expand Up @@ -619,6 +624,10 @@ ClassMethod OnBeforeAllTests(manager As TestCoverage.Manager, dir As %String, By
}

If (manager.CoverageDetail = 0) {
if (manager.ListenerManager) {
set tObj = {"message": "Starting tests"}
Do manager.ListenerManager.BroadCastToAll(tObj)
}
Set tSC = manager.StartCoverageTracking()
$$$ThrowOnError(tSC)
}
Expand All @@ -637,6 +646,10 @@ ClassMethod OnAfterAllTests(manager As TestCoverage.Manager, dir As %String, ByR
Try {
If (manager.CoverageDetail = 0) {
Set tSC = manager.EndCoverageTracking()
if (manager.ListenerManager) {
set tObj = {"message": "All tests complete"}
Do manager.ListenerManager.BroadCastToAll(tObj)
}
}
Do manager.Monitor.Stop()
} Catch e {
Expand Down Expand Up @@ -673,9 +686,15 @@ Method OnBeforeTestSuite(dir As %String, suite As %String, testspec As %String,
Set ..CurrentTestSuite = $Case(suite,"":"(root)",:suite)
Set ..CurrentTestClass = ""
Set ..CurrentTestMethod = ""
if (..ListenerManager) {
set tObj = {"message": "Starting test suite: "}
do tObj.%Set("suite", suite)
Do ..ListenerManager.BroadCastToAll(tObj)
}
If (..CoverageDetail = 1) {
Set tSC = ..StartCoverageTracking()
}

} Catch e {
Set tSC = e.AsStatus()
}
Expand All @@ -688,9 +707,15 @@ Method OnAfterTestSuite(dir As %String, suite As %String, testspec As %String, B
{
Set tSC = $$$OK
Try {

If (..CoverageDetail = 1) {
Set tSC = ..EndCoverageTracking($Case(suite,"":"(root)",:suite))
}
if (..ListenerManager) {
set tObj = {"message": "Finished test suite: "}
do tObj.%Set("suite", suite)
Do ..ListenerManager.BroadCastToAll(tObj)
}
} Catch e {
Set tSC = e.AsStatus()
}
Expand All @@ -705,6 +730,12 @@ Method OnBeforeTestCase(suite As %String, class As %String) As %Status
Try {
Set ..CurrentTestClass = class
Set ..CurrentTestMethod = ""
if (..ListenerManager) {
set tObj = {"message": "Starting test case: "}
do tObj.%Set("suite", suite)
do tObj.%Set("class", class)
Do ..ListenerManager.BroadCastToAll(tObj)
}
If (..CoverageDetail = 2) {
Set tSC = ..StartCoverageTracking()
}
Expand All @@ -723,6 +754,12 @@ Method OnAfterTestCase(suite As %String, class As %String) As %Status
If (..CoverageDetail = 2) {
Set tSC = ..EndCoverageTracking(suite, class)
}
if (..ListenerManager) {
set tObj = {"message": "Finished test case: "}
do tObj.%Set("suite", suite)
do tObj.%Set("class", class)
Do ..ListenerManager.BroadCastToAll(tObj)
}
} Catch e {
Set tSC = e.AsStatus()
}
Expand All @@ -736,6 +773,13 @@ Method OnBeforeOneTest(suite As %String, class As %String, method As %String) As
Set tSC = $$$OK
Try {
Set ..CurrentTestMethod = method
if (..ListenerManager) {
set tObj = {"message": "Starting test method: "}
do tObj.%Set("suite", suite)
do tObj.%Set("class", class)
do tObj.%Set("method", method)
Do ..ListenerManager.BroadCastToAll(tObj)
}
If (..CoverageDetail = 3) {
Set tSC = ..StartCoverageTracking()
}
Expand All @@ -754,6 +798,13 @@ Method OnAfterOneTest(suite As %String, class As %String, method As %String) As
If (..CoverageDetail = 3) {
Set tSC = ..EndCoverageTracking(suite, class, method)
}
if (..ListenerManager) {
set tObj = {"message": "Finished test method: "}
do tObj.%Set("suite", suite)
do tObj.%Set("class", class)
do tObj.%Set("method", method)
Do ..ListenerManager.BroadCastToAll(tObj)
}
} Catch e {
Set tSC = e.AsStatus()
}
Expand Down
Loading