> For the complete documentation index, see [llms.txt](https://docs.sealights.io/knowledgebase/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.sealights.io/knowledgebase/setup-and-configuration/sealights-agents-and-plugins/c++-agent/c++-agent-for-windows-beta/capturing-test-events-windows-msvc.md).

# Capturing Test Events (Windows / MSVC)

### Overview

Per-test event capture enables Test Impact Analysis (TIA). SeaLights identifies tests that cover each code path. It can skip tests unaffected by a change.

This page covers three paths:

1. **Scenario 1 — In-process GTest (GTest IS the AUT):** The `run` command captures coverage and test events together.
2. **Scenario 2 — External GTest test framework:** GTest drives a remote AUT. The background listener receives pass, fail, and skip events.
3. **Scenario 3 — Non-GTest frameworks (NUnit, MSTest, XUnit, JUnit):** Upload the XML report after the test run. The AUT listener captures coverage separately. See [Application Under Test](/knowledgebase/setup-and-configuration/sealights-agents-and-plugins/c++-agent/c++-agent-for-windows-beta/application-under-test-windows-msvc.md).

### Prerequisite for GTest scenarios

Pass `integrateMsBuild --gtest` during the MSBuild integration step. The command injects the GTest event-listener shim into application projects that resolve `<gtest/gtest.h>`.

Without the shim, GTest does not report test events.

### Scenario 1: In-process unit tests

The GTest binary is both the test framework and the AUT. Use the `run` command as shown in [Application Under Test → Mode 1](/knowledgebase/setup-and-configuration/sealights-agents-and-plugins/c++-agent/c++-agent-for-windows-beta/application-under-test-windows-msvc.md). The command captures coverage and test events in one process.

{% tabs %}
{% tab title="PowerShell" %}

```powershell
SL.Agent.Cpp.exe startExecution `
  --tokenFile          ./sltoken.txt `
  --labId              ci-main-mycppapp `
  --buildSessionIdFile buildSessionId.txt `
  --testStage          Unit-Tests

try {
  SL.Agent.Cpp.exe run `
    --tokenFile          ./sltoken.txt `
    --labId              ci-main-mycppapp `
    --buildSessionIdFile buildSessionId.txt `
    --testStage          Unit-Tests `
    --target             .\bin\Release\MyCppApp.Tests.exe `
    --targetArgs         "--gtest_output=xml:.\TestResults\results.xml"
} finally {
  SL.Agent.Cpp.exe endExecution `
    --tokenFile          ./sltoken.txt `
    --labId              ci-main-mycppapp `
    --buildSessionIdFile buildSessionId.txt `
    --testStage          Unit-Tests
}
```

{% endtab %}

{% tab title="Azure DevOps" %}

```yaml
- task: PowerShell@2
  displayName: Run in-process GTest binary with coverage
  env:
    SL_TOKEN: $(SL_TOKEN)
  inputs:
    targetType: inline
    script: |
      SL.Agent.Cpp.exe startExecution --token $env:SL_TOKEN --labId ci-main-mycppapp --buildSessionIdFile buildSessionId.txt --testStage Unit-Tests
      try {
        SL.Agent.Cpp.exe run --token $env:SL_TOKEN --labId ci-main-mycppapp --buildSessionIdFile buildSessionId.txt --testStage Unit-Tests --target .\bin\Release\MyCppApp.Tests.exe --targetArgs "--gtest_output=xml:.\TestResults\results.xml"
      } finally {
        SL.Agent.Cpp.exe endExecution --token $env:SL_TOKEN --labId ci-main-mycppapp --buildSessionIdFile buildSessionId.txt --testStage Unit-Tests
      }
```

{% endtab %}
{% endtabs %}

`run` sets `PATH` for the tracer DLL automatically. You need no further configuration.

### Scenario 2: External GTest test framework

GTest drives a remote AUT in a separate process. Start a background listener before the GTest binary runs. The GTest event-listener shim connects automatically and reports pass, fail, and skip events.

Add the agent directory to `PATH` first:

{% tabs %}
{% tab title="PowerShell" %}

```powershell
$env:PATH = "C:\SealightsAgent;$env:PATH"
```

{% endtab %}

{% tab title="Azure DevOps" %}

```yaml
- task: PowerShell@2
  displayName: Set the tracer DLL path
  inputs:
    targetType: inline
    script: $env:PATH = "C:\SealightsAgent;$env:PATH"
```

{% endtab %}
{% endtabs %}

{% tabs %}
{% tab title="PowerShell" %}

```powershell
SL.Agent.Cpp.exe startExecution `
  --tokenFile ./sltoken.txt --labId ci-main-mycppapp --buildSessionIdFile buildSessionId.txt --testStage Functional-Tests

SL.Agent.Cpp.exe startBackgroundTestListener `
  --tokenFile ./sltoken.txt --labId ci-main-mycppapp --buildSessionIdFile buildSessionId.txt `
  --testStage Functional-Tests --agentPort 31031

try {
   .\tests\MyCppApp.Tests.exe --gtest_output=xml:.\TestResults\results.xml
   .\tests\MyCppApp.IntegrationTests.exe --gtest_output=xml:.\TestResults\results2.xml
} finally {
   SL.Agent.Cpp.exe stopBackgroundTestListener `
     --tokenFile ./sltoken.txt --buildSessionIdFile buildSessionId.txt --agentPort 31031
   SL.Agent.Cpp.exe endExecution `
     --tokenFile ./sltoken.txt --labId ci-main-mycppapp --buildSessionIdFile buildSessionId.txt --testStage Functional-Tests
}
```

{% endtab %}

{% tab title="Azure DevOps" %}

```yaml
- task: PowerShell@2
  displayName: Start execution and background listener
  env:
    SL_TOKEN: $(SL_TOKEN)
  inputs:
    targetType: inline
    script: |
      SL.Agent.Cpp.exe startExecution --token $env:SL_TOKEN --labId ci-main-mycppapp --buildSessionIdFile buildSessionId.txt --testStage Functional-Tests
      SL.Agent.Cpp.exe startBackgroundTestListener --token $env:SL_TOKEN --labId ci-main-mycppapp --buildSessionIdFile buildSessionId.txt --testStage Functional-Tests --agentPort 31031

- task: PowerShell@2
  displayName: Run GTest suites
  inputs:
    targetType: inline
    script: |
      .\tests\MyCppApp.Tests.exe --gtest_output=xml:.\TestResults\results.xml
      .\tests\MyCppApp.IntegrationTests.exe --gtest_output=xml:.\TestResults\results2.xml

- task: PowerShell@2
  displayName: Stop listener and end execution
  condition: always()
  env:
    SL_TOKEN: $(SL_TOKEN)
  inputs:
    targetType: inline
    script: |
      SL.Agent.Cpp.exe stopBackgroundTestListener --token $env:SL_TOKEN --buildSessionIdFile buildSessionId.txt --agentPort 31031
      SL.Agent.Cpp.exe endExecution --token $env:SL_TOKEN --labId ci-main-mycppapp --buildSessionIdFile buildSessionId.txt --testStage Functional-Tests
```

{% endtab %}
{% endtabs %}

The listener returns immediately after `startBackgroundTestListener`. Any instrumented GTest binary on the same host connects to `<Port>` and reports events automatically.

**Parallel GTest stages:** Use a distinct `--agentPort` and `--testListenerSessionKey` for each listener. Pass the same key to `startBackgroundTestListener` and `stopBackgroundTestListener`. Each listener and stage pair needs its own `startExecution` and `endExecution`.

{% hint style="info" %}
To capture AUT coverage with GTest test events, run a second listener for the AUT. See [Application Under Test → Mode 2, Option B](/knowledgebase/setup-and-configuration/sealights-agents-and-plugins/c++-agent/c++-agent-for-windows-beta/application-under-test-windows-msvc.md). The listeners can share a port and stage, or use separate ports for independent control.
{% endhint %}

### Scenario 3: Non-GTest frameworks

After the test run completes, upload the XML report. The AUT listener already collects coverage. See [Application Under Test → Mode 2](/knowledgebase/setup-and-configuration/sealights-agents-and-plugins/c++-agent/c++-agent-for-windows-beta/application-under-test-windows-msvc.md).

{% tabs %}
{% tab title="PowerShell" %}

```powershell
SL.Agent.Cpp.exe startExecution `
  --tokenFile ./sltoken.txt --labId ci-main-mycppapp --buildSessionIdFile buildSessionId.txt --testStage NUnit-Tests

try {
   SL.Agent.Cpp.exe uploadReports `
     --tokenFile          ./sltoken.txt `
     --labId              ci-main-mycppapp `
     --buildSessionIdFile buildSessionId.txt `
     --testStage          NUnit-Tests `
     --file               .\TestResults\results.xml
} finally {
   SL.Agent.Cpp.exe endExecution `
     --tokenFile ./sltoken.txt --labId ci-main-mycppapp --buildSessionIdFile buildSessionId.txt --testStage NUnit-Tests
}
```

{% endtab %}

{% tab title="Azure DevOps" %}

```yaml
- task: PowerShell@2
  displayName: Upload non-GTest test report
  env:
    SL_TOKEN: $(SL_TOKEN)
  inputs:
    targetType: inline
    script: |
      SL.Agent.Cpp.exe startExecution --token $env:SL_TOKEN --labId ci-main-mycppapp --buildSessionIdFile buildSessionId.txt --testStage NUnit-Tests
      try {
        SL.Agent.Cpp.exe uploadReports --token $env:SL_TOKEN --labId ci-main-mycppapp --buildSessionIdFile buildSessionId.txt --testStage NUnit-Tests --file .\TestResults\results.xml
      } finally {
        SL.Agent.Cpp.exe endExecution --token $env:SL_TOKEN --labId ci-main-mycppapp --buildSessionIdFile buildSessionId.txt --testStage NUnit-Tests
      }
```

{% endtab %}
{% endtabs %}

`--file` accepts one XML file or a folder of report files. Frameworks with JUnit XML output use the same path. This includes Playwright with its JUnit reporter and Tosca.

Add `--useExistingExecution` when the AUT listener stage already manages `startExecution` and `endExecution`.

**Next step:** [Parameter Reference](/knowledgebase/setup-and-configuration/sealights-agents-and-plugins/c++-agent/c++-agent-for-windows-beta/c++-agent-parameter-reference-windows.md)


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.sealights.io/knowledgebase/setup-and-configuration/sealights-agents-and-plugins/c++-agent/c++-agent-for-windows-beta/capturing-test-events-windows-msvc.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
