Skip to content

How to: Run Tests

Overview

SyRF has automated tests for both .NET services (xUnit) and the Angular web service (Vitest). Tests run automatically in CI/CD on pull requests and before deployments.

Test Infrastructure

Service Type Framework Test Count Location
Angular (Web) Vitest 612+ src/services/web/
.NET (API, PM, etc.) xUnit 5 projects src/services/*/, src/libs/*/

Running Tests Locally

Using the Test Script

A unified test runner script is available:

# Run all tests
.github/scripts/run-tests.sh

# Run only Angular tests
.github/scripts/run-tests.sh web

# Run only .NET tests
.github/scripts/run-tests.sh dotnet

# Run with coverage
.github/scripts/run-tests.sh all --coverage

Running Angular Tests Directly

cd src/services/web

# Run tests once
pnpm exec ng test --no-watch

# Run with coverage
pnpm exec ng test --no-watch --coverage

# Run in watch mode (development)
pnpm exec ng test

Coverage output: src/services/web/coverage/

Running Specific Angular Tests

Use --include to run specific test files and --filter to match test names:

# Run a specific test file
pnpm exec ng test --no-watch --include="src/app/core/services/signal-r/signal-r.service.spec.ts"

# Run all tests in a folder (glob pattern)
pnpm exec ng test --no-watch --include="src/app/core/services/**/*.spec.ts"

# Filter by test name (regex matches describe/it blocks)
pnpm exec ng test --no-watch --filter="_connect"

# Combine file and name filtering
pnpm exec ng test --no-watch \
  --include="src/app/core/services/signal-r/signal-r.service.spec.ts" \
  --filter="_connect"

# Watch mode with specific file
pnpm exec ng test --include="src/app/core/services/signal-r/signal-r.service.spec.ts"

Note: Always use pnpm exec ng test (not pnpm exec vitest directly) to ensure Angular's build system properly compiles decorators and handles test teardown.

Running .NET Tests Directly

# Run all .NET tests
dotnet test syrf.sln

# Run with coverage
dotnet test syrf.sln \
  --collect:"XPlat Code Coverage" \
  -- DataCollectionRunSettings.DataCollectors.DataCollector.Configuration.Format=cobertura

# Run specific service tests
dotnet test src/services/api/SyRF.API.Endpoint.Tests/

Running Specific .NET Tests

# Run a specific test project
dotnet test src/services/api/SyRF.API.Endpoint.Tests/

# Filter by test name (supports wildcards)
dotnet test --filter "FullyQualifiedName~SearchImportJob"

# Filter by test class
dotnet test --filter "ClassName=SearchControllerTests"

# Filter by test method
dotnet test --filter "Name=ShouldReturnSearchResults"

# Combine project and filter
dotnet test src/services/project-management/SyRF.ProjectManagement.Endpoint.Tests/ \
  --filter "FullyQualifiedName~SearchImportJobStateMachine"

CI/CD Test Integration

Tests run automatically in two workflows:

1. Pull Request Tests (pr-tests.yml)

Runs on ALL pull requests to main:

PR opened/updated
detect-changes
test-dotnet (if .NET changed) ──┬── test-summary
test-web (if Angular changed) ──┘

Key features:

  • Runs on every PR (not just preview-labeled)
  • Only tests changed services (saves time)
  • Uploads test results and coverage as artifacts
  • Fails PR if tests fail

2. Main Branch Tests (ci-cd.yml)

Runs before deployment on push to main:

detect-changes → version → test-dotnet ──┬── build-docker → deploy
                         → test-web ─────┘

Key features:

  • Tests must pass before Docker builds
  • Blocks deployment if tests fail
  • Coverage reports uploaded as artifacts

Coverage Thresholds

Angular tests have coverage thresholds configured in vitest.config.ts:

Metric Threshold
Statements 50%
Branches 40%
Functions 50%
Lines 50%

Tests will fail if coverage drops below these thresholds.

Code Quality (SonarCloud)

Code quality and coverage analysis is performed by SonarCloud on every PR.

What You Get

  • Quality Gate: Pass/fail status on PRs based on quality thresholds
  • Coverage Analysis: Line and branch coverage visualization
  • Code Smells: Detect maintainability issues
  • Security Hotspots: Identify potential security vulnerabilities
  • Duplications: Find duplicated code blocks
  • PR Decoration: Inline comments on issues in changed code

Setup (One-Time)

  1. Create SonarCloud Account: Go to sonarcloud.io and sign in with GitHub
  2. Projects are already configured in SonarCloud:
  3. syrf-web - Angular frontend
  4. syrf-api - API service
  5. syrf-project-management - PM service
  6. Add Secrets in GitHub repo settings → Secrets → Actions:
  7. SONAR_TOKEN_WEB - Token for syrf-web project
  8. SONAR_TOKEN_API - Token for syrf-api project
  9. SONAR_TOKEN_PM - Token for syrf-project-management project

Coverage Sources

Language Format Report Path
.NET Cobertura XML coverage/dotnet/**/coverage.cobertura.xml
Angular LCOV coverage/web/lcov.info

Quality Gate Badges

Add to your service README:

Web (Angular):

[![Quality Gate](https://sonarcloud.io/api/project_badges/measure?project=syrf-web&metric=alert_status)](https://sonarcloud.io/summary/new_code?id=syrf-web)
[![Coverage](https://sonarcloud.io/api/project_badges/measure?project=syrf-web&metric=coverage)](https://sonarcloud.io/summary/new_code?id=syrf-web)

API:

[![Quality Gate](https://sonarcloud.io/api/project_badges/measure?project=syrf-api&metric=alert_status)](https://sonarcloud.io/summary/new_code?id=syrf-api)
[![Coverage](https://sonarcloud.io/api/project_badges/measure?project=syrf-api&metric=coverage)](https://sonarcloud.io/summary/new_code?id=syrf-api)

Project Management:

[![Quality Gate](https://sonarcloud.io/api/project_badges/measure?project=syrf-project-management&metric=alert_status)](https://sonarcloud.io/summary/new_code?id=syrf-project-management)
[![Coverage](https://sonarcloud.io/api/project_badges/measure?project=syrf-project-management&metric=coverage)](https://sonarcloud.io/summary/new_code?id=syrf-project-management)

Timeouts

Test Suite CI Timeout Rationale
Angular 5 minutes Tests run in ~10s, pnpm install adds overhead
.NET 10 minutes Includes restore, build, and test

.NET Test Projects

Project Tests
SyRF.API.Endpoint.Tests API service tests
SyRF.ProjectManagement.Endpoint.Tests PM service tests
SyRF.AppServices.Tests AppServices library tests
SyRF.ProjectManagement.Core.Tests PM Core library tests
SyRF.WebHostConfig.Common.Tests WebHostConfig library tests

Troubleshooting

Angular Tests Fail in CI but Pass Locally

Common causes:

  1. Missing PDF.js mocks: The vitest-setup.ts includes mocks for PDF.js
  2. Circular dependencies: Some components have placeholder tests due to circular imports
  3. Timing issues: Use fakeAsync and tick for async operations

.NET Tests Fail

Common causes:

  1. Missing dependencies: Run dotnet restore syrf.sln first
  2. Build errors: Run dotnet build syrf.sln before testing
  3. Database dependencies: Tests should mock MongoDB connections

Coverage Below Threshold

Fix: Add tests for uncovered code paths. Check src/services/web/coverage/lcov-report/index.html for coverage report.

Viewing Test Results

In GitHub Actions

  1. Go to Actions tab
  2. Select the workflow run
  3. Check test-dotnet or test-web job
  4. Download artifacts for detailed reports

Artifact Contents

Artifact Contents
dotnet-test-results .trx test result files
dotnet-coverage Cobertura XML coverage
web-coverage lcov, cobertura, text coverage
web-test-results JUnit XML test results