Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
91 changes: 91 additions & 0 deletions .github/workflows/dotnet.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
name: .NET Tests

on:
push:
branches: [main]
pull_request:
branches: [main]
workflow_dispatch:

defaults:
run:
working-directory: dotnet-examples

jobs:
test:
name: .NET TRX Reports
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: "8.0.x"

- name: Restore dependencies
run: dotnet restore

- name: Build
run: dotnet build --no-restore

- name: Create reports directory
run: mkdir -p reports

- name: Run xUnit tests
run: dotnet test tests/Calculator.XUnit.Tests --no-build --logger "trx;LogFileName=xunit-results.trx" --results-directory ./reports
continue-on-error: true

- name: Run NUnit tests
run: dotnet test tests/Calculator.NUnit.Tests --no-build --logger "trx;LogFileName=nunit-results.trx" --results-directory ./reports
continue-on-error: true

- name: Run MSTest tests
run: dotnet test tests/Calculator.MSTest.Tests --no-build --logger "trx;LogFileName=mstest-results.trx" --results-directory ./reports
continue-on-error: true

# Upload xUnit TRX to Gaffer
- name: Upload xUnit TRX to Gaffer
if: always() && github.actor != 'dependabot[bot]'
uses: gaffer-sh/gaffer-uploader@v0.3.0
with:
gaffer_api_key: ${{ secrets.GAFFER_API_KEY }}
report_path: dotnet-examples/reports/xunit-results.trx
commit_sha: ${{ github.event.pull_request.head.sha || github.sha }}
branch: ${{ github.ref_name }}
test_framework: dotnet
test_suite: xunit

# Upload NUnit TRX to Gaffer
- name: Upload NUnit TRX to Gaffer
if: always() && github.actor != 'dependabot[bot]'
uses: gaffer-sh/gaffer-uploader@v0.3.0
with:
gaffer_api_key: ${{ secrets.GAFFER_API_KEY }}
report_path: dotnet-examples/reports/nunit-results.trx
commit_sha: ${{ github.event.pull_request.head.sha || github.sha }}
branch: ${{ github.ref_name }}
test_framework: dotnet
test_suite: nunit

# Upload MSTest TRX to Gaffer
- name: Upload MSTest TRX to Gaffer
if: always() && github.actor != 'dependabot[bot]'
uses: gaffer-sh/gaffer-uploader@v0.3.0
with:
gaffer_api_key: ${{ secrets.GAFFER_API_KEY }}
report_path: dotnet-examples/reports/mstest-results.trx
commit_sha: ${{ github.event.pull_request.head.sha || github.sha }}
branch: ${{ github.ref_name }}
test_framework: dotnet
test_suite: mstest

# Store artifacts for parser development
- name: Upload test artifacts
if: always()
uses: actions/upload-artifact@v4
with:
name: dotnet-reports-${{ github.sha }}
path: dotnet-examples/reports/
retention-days: 30
20 changes: 19 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

Example test projects demonstrating [Gaffer](https://gaffer.sh) integration for various test frameworks.

Parser Check: December 4 2025 - 20:41
Parser Check: December 17 2025 - 8:31

## Examples

Expand All @@ -11,13 +11,15 @@ Parser Check: December 4 2025 - 20:41
| Jest | JSON, HTML | [`jest-example/`](./jest-example/) |
| pytest | HTML | [`pytest-example/`](./pytest-example/) |
| Vitest | JSON | [`vitest-example/`](./vitest-example/) |
| .NET (xUnit, NUnit, MSTest) | TRX | [`dotnet-examples/`](./dotnet-examples/) |

## Quick Start

### Prerequisites

- Node.js 22+ (Jest, Vitest)
- Python 3.9+ (pytest)
- Docker or .NET 8.0 SDK (xUnit, NUnit, MSTest)
- [Gaffer API key](https://app.gaffer.sh)

### Running Examples Locally
Expand Down Expand Up @@ -46,6 +48,19 @@ npm install
npm run test:json # Generates JSON report
```

#### .NET (via Docker)

```bash
cd dotnet-examples
mkdir -p reports
docker run --rm -v "$(pwd):/app" -w /app mcr.microsoft.com/dotnet/sdk:8.0 sh -c "
dotnet restore && dotnet build && \
dotnet test tests/Calculator.XUnit.Tests --logger 'trx;LogFileName=xunit-results.trx' --results-directory ./reports && \
dotnet test tests/Calculator.NUnit.Tests --logger 'trx;LogFileName=nunit-results.trx' --results-directory ./reports && \
dotnet test tests/Calculator.MSTest.Tests --logger 'trx;LogFileName=mstest-results.trx' --results-directory ./reports
"
```

## Uploading to Gaffer

### Using the GitHub Action (Recommended)
Expand Down Expand Up @@ -90,6 +105,9 @@ See the workflows in [`.github/workflows/`](./.github/workflows/).
| Jest | HTML | `reports/jest-report.html` | `jest-html` |
| pytest | HTML | `reports/pytest-report.html` | `pytest-html` |
| Vitest | JSON | `reports/vitest-results.json` | `vitest-json` |
| xUnit | TRX | `reports/xunit-results.trx` | `trx` |
| NUnit | TRX | `reports/nunit-results.trx` | `trx` |
| MSTest | TRX | `reports/mstest-results.trx` | `trx` |

## Accessing Artifacts

Expand Down
17 changes: 17 additions & 0 deletions dotnet-examples/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Build outputs
bin/
obj/

# Reports (generated)
reports/
*.trx

# IDE
.vs/
.idea/
*.user
*.suo

# OS
.DS_Store
Thumbs.db
37 changes: 37 additions & 0 deletions dotnet-examples/DotnetExamples.sln
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.0.31903.59
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Calculator", "src\Calculator\Calculator.csproj", "{A1B2C3D4-E5F6-7890-ABCD-EF1234567890}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Calculator.XUnit.Tests", "tests\Calculator.XUnit.Tests\Calculator.XUnit.Tests.csproj", "{B2C3D4E5-F6A7-8901-BCDE-F12345678901}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Calculator.NUnit.Tests", "tests\Calculator.NUnit.Tests\Calculator.NUnit.Tests.csproj", "{C3D4E5F6-A7B8-9012-CDEF-123456789012}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Calculator.MSTest.Tests", "tests\Calculator.MSTest.Tests\Calculator.MSTest.Tests.csproj", "{D4E5F6A7-B8C9-0123-DEF0-234567890123}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{A1B2C3D4-E5F6-7890-ABCD-EF1234567890}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A1B2C3D4-E5F6-7890-ABCD-EF1234567890}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A1B2C3D4-E5F6-7890-ABCD-EF1234567890}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A1B2C3D4-E5F6-7890-ABCD-EF1234567890}.Release|Any CPU.Build.0 = Release|Any CPU
{B2C3D4E5-F6A7-8901-BCDE-F12345678901}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B2C3D4E5-F6A7-8901-BCDE-F12345678901}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B2C3D4E5-F6A7-8901-BCDE-F12345678901}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B2C3D4E5-F6A7-8901-BCDE-F12345678901}.Release|Any CPU.Build.0 = Release|Any CPU
{C3D4E5F6-A7B8-9012-CDEF-123456789012}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C3D4E5F6-A7B8-9012-CDEF-123456789012}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C3D4E5F6-A7B8-9012-CDEF-123456789012}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C3D4E5F6-A7B8-9012-CDEF-123456789012}.Release|Any CPU.Build.0 = Release|Any CPU
{D4E5F6A7-B8C9-0123-DEF0-234567890123}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D4E5F6A7-B8C9-0123-DEF0-234567890123}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D4E5F6A7-B8C9-0123-DEF0-234567890123}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D4E5F6A7-B8C9-0123-DEF0-234567890123}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal
142 changes: 142 additions & 0 deletions dotnet-examples/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
# .NET Test Examples

Example .NET 8.0 test projects demonstrating TRX report generation for [Gaffer](https://gaffer.sh).

This directory contains three test projects using different .NET test frameworks:
- **xUnit** - Popular open-source testing framework
- **NUnit** - Well-established testing framework
- **MSTest** - Microsoft's official testing framework

## Prerequisites

- [Docker](https://www.docker.com/get-started) (recommended)
- OR [.NET 8.0 SDK](https://dotnet.microsoft.com/download/dotnet/8.0)
- [Gaffer API key](https://app.gaffer.sh)

## Running Tests with Docker (Recommended)

No local .NET installation required.

```bash
cd dotnet-examples

# Create reports directory
mkdir -p reports

# Run all tests and generate TRX reports
docker run --rm -v "$(pwd):/app" -w /app mcr.microsoft.com/dotnet/sdk:8.0 sh -c "
dotnet restore && \
dotnet build && \
dotnet test tests/Calculator.XUnit.Tests --logger 'trx;LogFileName=xunit-results.trx' --results-directory ./reports && \
dotnet test tests/Calculator.NUnit.Tests --logger 'trx;LogFileName=nunit-results.trx' --results-directory ./reports && \
dotnet test tests/Calculator.MSTest.Tests --logger 'trx;LogFileName=mstest-results.trx' --results-directory ./reports
"
```

### Run individual frameworks

```bash
# xUnit only
docker run --rm -v "$(pwd):/app" -w /app mcr.microsoft.com/dotnet/sdk:8.0 \
dotnet test tests/Calculator.XUnit.Tests --logger "trx;LogFileName=xunit-results.trx" --results-directory ./reports

# NUnit only
docker run --rm -v "$(pwd):/app" -w /app mcr.microsoft.com/dotnet/sdk:8.0 \
dotnet test tests/Calculator.NUnit.Tests --logger "trx;LogFileName=nunit-results.trx" --results-directory ./reports

# MSTest only
docker run --rm -v "$(pwd):/app" -w /app mcr.microsoft.com/dotnet/sdk:8.0 \
dotnet test tests/Calculator.MSTest.Tests --logger "trx;LogFileName=mstest-results.trx" --results-directory ./reports
```

## Running Tests with Local .NET SDK

```bash
cd dotnet-examples
dotnet restore
mkdir -p reports

# Run xUnit tests
dotnet test tests/Calculator.XUnit.Tests --logger "trx;LogFileName=xunit-results.trx" --results-directory ./reports

# Run NUnit tests
dotnet test tests/Calculator.NUnit.Tests --logger "trx;LogFileName=nunit-results.trx" --results-directory ./reports

# Run MSTest tests
dotnet test tests/Calculator.MSTest.Tests --logger "trx;LogFileName=mstest-results.trx" --results-directory ./reports

# Or run all at once
dotnet test --logger "trx;LogFileName=test-results.trx" --results-directory reports
```

## Report Output

| Framework | Output Path |
|-----------|-------------|
| xUnit | `reports/xunit-results.trx` |
| NUnit | `reports/nunit-results.trx` |
| MSTest | `reports/mstest-results.trx` |

## TRX Format Notes

TRX (Test Results XML) is the native .NET test report format. Key characteristics:
- Root element: `<TestRun>`
- File extension: `.trx`
- Test results in `<UnitTestResult>` elements
- Outcomes: `Passed`, `Failed`, `NotExecuted`, `Inconclusive`
- Duration in `HH:mm:ss.fffffff` format
- Error details in `<Output><ErrorInfo><Message>` and `<StackTrace>`

## Test Cases

Each test project includes various test types to demonstrate TRX output:

| Test Type | xUnit | NUnit | MSTest | TRX Outcome |
|-----------|-------|-------|--------|-------------|
| Passing tests | `[Fact]` | `[Test]` | `[TestMethod]` | `Passed` |
| Failing test | `[Fact]` | `[Test]` | `[TestMethod]` | `Failed` |
| Skipped test | `[Fact(Skip="...")]` | `[Ignore("...")]` | `[Ignore("...")]` | `NotExecuted` |
| Inconclusive | N/A | `Assert.Inconclusive()` | `Assert.Inconclusive()` | `Inconclusive` |
| Parameterized | `[Theory]` | `[TestCase]` | `[DataRow]` | Multiple results |
| Exception tests | `Assert.Throws<>` | `Assert.Throws<>` | `[ExpectedException]` | `Passed` |

## Uploading to Gaffer

### Using curl

```bash
# Upload xUnit TRX
curl -X POST https://app.gaffer.sh/api/upload \
-H "X-API-Key: $GAFFER_API_KEY" \
-F "files=@reports/xunit-results.trx"

# Upload NUnit TRX
curl -X POST https://app.gaffer.sh/api/upload \
-H "X-API-Key: $GAFFER_API_KEY" \
-F "files=@reports/nunit-results.trx"

# Upload MSTest TRX
curl -X POST https://app.gaffer.sh/api/upload \
-H "X-API-Key: $GAFFER_API_KEY" \
-F "files=@reports/mstest-results.trx"
```

### Using GitHub Action

See `.github/workflows/dotnet.yml` for the full CI/CD workflow.

## Project Structure

```
dotnet-examples/
├── src/Calculator/ # Shared source code
│ ├── Calculator.cs
│ └── Calculator.csproj
├── tests/
│ ├── Calculator.XUnit.Tests/
│ ├── Calculator.NUnit.Tests/
│ └── Calculator.MSTest.Tests/
├── DotnetExamples.sln
├── .gitignore
└── README.md
```
35 changes: 35 additions & 0 deletions dotnet-examples/src/Calculator/Calculator.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
namespace Calculator;

public class Calculator
{
public double Add(double a, double b) => a + b;

public double Subtract(double a, double b) => a - b;

public double Multiply(double a, double b) => a * b;

public double Divide(double a, double b)
{
if (b == 0)
throw new DivideByZeroException("Cannot divide by zero");
return a / b;
}
}

public static class StringUtils
{
public static string Reverse(string input)
{
if (input == null)
throw new ArgumentNullException(nameof(input));
return new string(input.Reverse().ToArray());
}

public static bool IsPalindrome(string input)
{
if (input == null)
throw new ArgumentNullException(nameof(input));
var cleaned = input.ToLower().Replace(" ", "");
return cleaned == new string(cleaned.Reverse().ToArray());
}
}
7 changes: 7 additions & 0 deletions dotnet-examples/src/Calculator/Calculator.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
</Project>
Loading
Loading