Skip to content

Commit ddd38c3

Browse files
authored
Merge pull request #7 from abeckDev/copilot/add-code-coverage-unit-tests
Add unit tests and code coverage for MCP Server
2 parents cdaa0d5 + 2b02287 commit ddd38c3

File tree

12 files changed

+947
-5
lines changed

12 files changed

+947
-5
lines changed

.github/workflows/dotnet-ci.yml

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
name: .NET CI with Code Coverage
2+
3+
on:
4+
push:
5+
branches: [ "main" ]
6+
pull_request:
7+
branches: [ "main" ]
8+
9+
jobs:
10+
build-and-test:
11+
runs-on: ubuntu-latest
12+
permissions:
13+
contents: read
14+
checks: write
15+
16+
steps:
17+
- uses: actions/checkout@v4
18+
19+
- name: Setup .NET
20+
uses: actions/setup-dotnet@v4
21+
with:
22+
dotnet-version: 9.0.x
23+
24+
- name: Restore dependencies
25+
run: dotnet restore
26+
27+
- name: Build
28+
run: dotnet build --no-restore --configuration Release
29+
30+
- name: Test
31+
run: dotnet test --no-build --configuration Release --verbosity normal --collect:"XPlat Code Coverage" --results-directory ./TestResults
32+
33+
- name: Upload coverage reports to Codecov
34+
uses: codecov/codecov-action@v5
35+
with:
36+
directory: ./TestResults
37+
fail_ci_if_error: false
38+
verbose: true
39+
env:
40+
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
41+
42+
- name: Generate Coverage Report
43+
uses: danielpalme/ReportGenerator-GitHub-Action@5.4.2
44+
with:
45+
reports: 'TestResults/**/coverage.cobertura.xml'
46+
targetdir: 'TestResults/CoverageReport'
47+
reporttypes: 'Html;TextSummary;Cobertura;Badges'
48+
49+
- name: Display Coverage Summary
50+
run: |
51+
echo "## Code Coverage Summary" >> $GITHUB_STEP_SUMMARY
52+
echo "" >> $GITHUB_STEP_SUMMARY
53+
cat TestResults/CoverageReport/Summary.txt >> $GITHUB_STEP_SUMMARY
54+
55+
- name: Upload Coverage Report as Artifact
56+
uses: actions/upload-artifact@v4
57+
if: always()
58+
with:
59+
name: coverage-report
60+
path: TestResults/CoverageReport
61+
retention-days: 30
62+
63+
- name: Check Coverage Threshold
64+
run: |
65+
COVERAGE=$(grep -oP 'Line coverage: \K[0-9.]+' TestResults/CoverageReport/Summary.txt)
66+
echo "Current coverage: $COVERAGE%"
67+
THRESHOLD=70.0
68+
if (( $(echo "$COVERAGE < $THRESHOLD" | bc -l) )); then
69+
echo "❌ Coverage ($COVERAGE%) is below threshold ($THRESHOLD%)"
70+
exit 1
71+
else
72+
echo "✅ Coverage ($COVERAGE%) meets threshold ($THRESHOLD%)"
73+
fi

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,9 @@ Generated\ Files/
5555
[Bb]uild[Ll]og.*
5656
*.trx
5757

58+
# Code Coverage Results
59+
TestResults/
60+
5861
# NUnit
5962
*.VisualState.xml
6063
TestResult.xml
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<TargetFramework>net9.0</TargetFramework>
5+
<ImplicitUsings>enable</ImplicitUsings>
6+
<Nullable>enable</Nullable>
7+
8+
<IsPackable>false</IsPackable>
9+
<IsTestProject>true</IsTestProject>
10+
</PropertyGroup>
11+
12+
<ItemGroup>
13+
<PackageReference Include="coverlet.collector" Version="6.0.4">
14+
<PrivateAssets>all</PrivateAssets>
15+
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
16+
</PackageReference>
17+
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.0.0" />
18+
<PackageReference Include="Moq" Version="4.20.72" />
19+
<PackageReference Include="xunit" Version="2.9.3" />
20+
<PackageReference Include="xunit.runner.visualstudio" Version="3.1.5">
21+
<PrivateAssets>all</PrivateAssets>
22+
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
23+
</PackageReference>
24+
</ItemGroup>
25+
26+
<ItemGroup>
27+
<Using Include="Xunit" />
28+
</ItemGroup>
29+
30+
<ItemGroup>
31+
<ProjectReference Include="..\AbeckDev.DbTimetable.Mcp\AbeckDev.DbTimetable.Mcp.csproj" />
32+
</ItemGroup>
33+
34+
</Project>
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
using AbeckDev.DbTimetable.Mcp.Models;
2+
3+
namespace AbeckDev.DbTimetable.Mcp.Test;
4+
5+
public class ConfigurationTests
6+
{
7+
[Fact]
8+
public void Configuration_SectionName_HasCorrectValue()
9+
{
10+
// Arrange & Act & Assert
11+
Assert.Equal("DeutscheBahnApi", Configuration.SectionName);
12+
}
13+
14+
[Fact]
15+
public void Configuration_DefaultValues_AreCorrect()
16+
{
17+
// Arrange & Act
18+
var config = new Configuration();
19+
20+
// Assert
21+
Assert.Equal("https://apis.deutschebahn.com/db-api-marketplace/apis/timetables/v1/", config.BaseUrl);
22+
Assert.Equal(string.Empty, config.ClientId);
23+
Assert.Equal(string.Empty, config.ApiKey);
24+
}
25+
26+
[Fact]
27+
public void Configuration_Properties_CanBeSet()
28+
{
29+
// Arrange
30+
var config = new Configuration();
31+
var expectedBaseUrl = "https://test.api.com/";
32+
var expectedClientId = "test-client-id";
33+
var expectedApiKey = "test-api-key";
34+
35+
// Act
36+
config.BaseUrl = expectedBaseUrl;
37+
config.ClientId = expectedClientId;
38+
config.ApiKey = expectedApiKey;
39+
40+
// Assert
41+
Assert.Equal(expectedBaseUrl, config.BaseUrl);
42+
Assert.Equal(expectedClientId, config.ClientId);
43+
Assert.Equal(expectedApiKey, config.ApiKey);
44+
}
45+
}

0 commit comments

Comments
 (0)