Skip to content

Commit 1a5a276

Browse files
committed
test: add comprehensive xUnit test project (#4)
Add unit test project with 157 tests covering: - TelemetryConfiguration validation and defaults - ActivitySourceProvider creation and disposal - MetricsProvider instrument caching - LoggerProvider delegation - ExceptionTracker filtering and tracking - VsixTelemetry static facade lifecycle
1 parent c369233 commit 1a5a276

File tree

10 files changed

+2180
-1
lines changed

10 files changed

+2180
-1
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,3 +75,5 @@ CLAUDE.local.md
7575
*.log
7676
.DS_Store
7777
Thumbs.db
78+
79+
.claude/settings.local.json

CodingWithCalvin.Otel4Vsix.slnx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
11
<Solution>
2-
<Project Path="src/CodingWithCalvin.Otel4Vsix/CodingWithCalvin.Otel4Vsix.csproj" />
2+
<Folder Name="/src/">
3+
<Project Path="src/CodingWithCalvin.Otel4Vsix/CodingWithCalvin.Otel4Vsix.csproj" />
4+
</Folder>
5+
<Folder Name="/tests/">
6+
<Project Path="tests/CodingWithCalvin.Otel4Vsix.Tests/CodingWithCalvin.Otel4Vsix.Tests.csproj" />
7+
</Folder>
38
</Solution>

src/CodingWithCalvin.Otel4Vsix/Properties/AssemblyInfo.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System;
22
using System.Reflection;
3+
using System.Runtime.CompilerServices;
34
using System.Runtime.InteropServices;
45

56
[assembly: AssemblyTitle("Otel4Vsix")]
@@ -19,3 +20,5 @@
1920
[assembly: AssemblyVersion("1.0.0.0")]
2021
[assembly: AssemblyFileVersion("1.0.0.0")]
2122
[assembly: AssemblyInformationalVersion("1.0.0")]
23+
24+
[assembly: InternalsVisibleTo("CodingWithCalvin.Otel4Vsix.Tests")]
Lines changed: 246 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,246 @@
1+
using System;
2+
using System.Diagnostics;
3+
using FluentAssertions;
4+
using Otel4Vsix.Tracing;
5+
using Xunit;
6+
7+
namespace CodingWithCalvin.Otel4Vsix.Tests
8+
{
9+
public class ActivitySourceProviderTests : IDisposable
10+
{
11+
private ActivitySourceProvider _provider;
12+
private ActivityListener _listener;
13+
14+
public ActivitySourceProviderTests()
15+
{
16+
// Set up an activity listener so activities are actually created
17+
_listener = new ActivityListener
18+
{
19+
ShouldListenTo = _ => true,
20+
Sample = (ref ActivityCreationOptions<ActivityContext> _) => ActivitySamplingResult.AllData
21+
};
22+
ActivitySource.AddActivityListener(_listener);
23+
}
24+
25+
public void Dispose()
26+
{
27+
_provider?.Dispose();
28+
_listener?.Dispose();
29+
}
30+
31+
[Fact]
32+
public void Constructor_WithNullServiceName_ThrowsArgumentNullException()
33+
{
34+
Action act = () => new ActivitySourceProvider(null, "1.0.0");
35+
36+
act.Should().Throw<ArgumentNullException>()
37+
.And.ParamName.Should().Be("serviceName");
38+
}
39+
40+
[Fact]
41+
public void Constructor_WithEmptyServiceName_ThrowsArgumentNullException()
42+
{
43+
Action act = () => new ActivitySourceProvider(string.Empty, "1.0.0");
44+
45+
act.Should().Throw<ArgumentNullException>();
46+
}
47+
48+
[Fact]
49+
public void Constructor_WithWhitespaceServiceName_ThrowsArgumentNullException()
50+
{
51+
Action act = () => new ActivitySourceProvider(" ", "1.0.0");
52+
53+
act.Should().Throw<ArgumentNullException>();
54+
}
55+
56+
[Fact]
57+
public void Constructor_WithValidName_CreatesActivitySource()
58+
{
59+
_provider = new ActivitySourceProvider("TestService", "1.0.0");
60+
61+
_provider.ActivitySource.Should().NotBeNull();
62+
_provider.ActivitySource.Name.Should().Be("TestService");
63+
_provider.ActivitySource.Version.Should().Be("1.0.0");
64+
}
65+
66+
[Fact]
67+
public void Constructor_WithNullVersion_UsesDefaultVersion()
68+
{
69+
_provider = new ActivitySourceProvider("TestService", null);
70+
71+
_provider.ActivitySource.Should().NotBeNull();
72+
_provider.ActivitySource.Version.Should().Be("1.0.0");
73+
}
74+
75+
[Fact]
76+
public void ActivitySource_BeforeDispose_ReturnsActivitySource()
77+
{
78+
_provider = new ActivitySourceProvider("TestService", "1.0.0");
79+
80+
var activitySource = _provider.ActivitySource;
81+
82+
activitySource.Should().NotBeNull();
83+
}
84+
85+
[Fact]
86+
public void ActivitySource_AfterDispose_ThrowsObjectDisposedException()
87+
{
88+
_provider = new ActivitySourceProvider("TestService", "1.0.0");
89+
_provider.Dispose();
90+
91+
Action act = () => { var _ = _provider.ActivitySource; };
92+
93+
act.Should().Throw<ObjectDisposedException>()
94+
.And.ObjectName.Should().Be(nameof(ActivitySourceProvider));
95+
}
96+
97+
[Fact]
98+
public void StartActivity_CreatesActivity()
99+
{
100+
_provider = new ActivitySourceProvider("TestService", "1.0.0");
101+
102+
using var activity = _provider.StartActivity("TestActivity");
103+
104+
activity.Should().NotBeNull();
105+
activity.OperationName.Should().Be("TestActivity");
106+
}
107+
108+
[Fact]
109+
public void StartActivity_WithKind_SetsActivityKind()
110+
{
111+
_provider = new ActivitySourceProvider("TestService", "1.0.0");
112+
113+
using var activity = _provider.StartActivity("TestActivity", ActivityKind.Client);
114+
115+
activity.Should().NotBeNull();
116+
activity.Kind.Should().Be(ActivityKind.Client);
117+
}
118+
119+
[Fact]
120+
public void StartActivity_AfterDispose_ThrowsObjectDisposedException()
121+
{
122+
_provider = new ActivitySourceProvider("TestService", "1.0.0");
123+
_provider.Dispose();
124+
125+
Action act = () => _provider.StartActivity("TestActivity");
126+
127+
act.Should().Throw<ObjectDisposedException>();
128+
}
129+
130+
[Fact]
131+
public void StartCommandActivity_CreatesActivityWithCorrectName()
132+
{
133+
_provider = new ActivitySourceProvider("TestService", "1.0.0");
134+
135+
using var activity = _provider.StartCommandActivity("MyCommand");
136+
137+
activity.Should().NotBeNull();
138+
activity.OperationName.Should().Be("Command: MyCommand");
139+
}
140+
141+
[Fact]
142+
public void StartCommandActivity_SetsCommandNameTag()
143+
{
144+
_provider = new ActivitySourceProvider("TestService", "1.0.0");
145+
146+
using var activity = _provider.StartCommandActivity("MyCommand");
147+
148+
activity.Should().NotBeNull();
149+
activity.GetTagItem("vs.command.name").Should().Be("MyCommand");
150+
}
151+
152+
[Fact]
153+
public void StartCommandActivity_AfterDispose_ThrowsObjectDisposedException()
154+
{
155+
_provider = new ActivitySourceProvider("TestService", "1.0.0");
156+
_provider.Dispose();
157+
158+
Action act = () => _provider.StartCommandActivity("MyCommand");
159+
160+
act.Should().Throw<ObjectDisposedException>();
161+
}
162+
163+
[Fact]
164+
public void StartToolWindowActivity_CreatesActivityWithCorrectName()
165+
{
166+
_provider = new ActivitySourceProvider("TestService", "1.0.0");
167+
168+
using var activity = _provider.StartToolWindowActivity("SolutionExplorer", "Open");
169+
170+
activity.Should().NotBeNull();
171+
activity.OperationName.Should().Be("ToolWindow: SolutionExplorer.Open");
172+
}
173+
174+
[Fact]
175+
public void StartToolWindowActivity_SetsCorrectTags()
176+
{
177+
_provider = new ActivitySourceProvider("TestService", "1.0.0");
178+
179+
using var activity = _provider.StartToolWindowActivity("SolutionExplorer", "Open");
180+
181+
activity.Should().NotBeNull();
182+
activity.GetTagItem("vs.toolwindow.name").Should().Be("SolutionExplorer");
183+
activity.GetTagItem("vs.toolwindow.operation").Should().Be("Open");
184+
}
185+
186+
[Fact]
187+
public void StartToolWindowActivity_AfterDispose_ThrowsObjectDisposedException()
188+
{
189+
_provider = new ActivitySourceProvider("TestService", "1.0.0");
190+
_provider.Dispose();
191+
192+
Action act = () => _provider.StartToolWindowActivity("Window", "Op");
193+
194+
act.Should().Throw<ObjectDisposedException>();
195+
}
196+
197+
[Fact]
198+
public void StartDocumentActivity_CreatesActivityWithCorrectName()
199+
{
200+
_provider = new ActivitySourceProvider("TestService", "1.0.0");
201+
202+
using var activity = _provider.StartDocumentActivity("C:\\file.cs", "Open");
203+
204+
activity.Should().NotBeNull();
205+
activity.OperationName.Should().Be("Document: Open");
206+
}
207+
208+
[Fact]
209+
public void StartDocumentActivity_SetsCorrectTags()
210+
{
211+
_provider = new ActivitySourceProvider("TestService", "1.0.0");
212+
213+
using var activity = _provider.StartDocumentActivity("C:\\file.cs", "Save");
214+
215+
activity.Should().NotBeNull();
216+
activity.GetTagItem("vs.document.path").Should().Be("C:\\file.cs");
217+
activity.GetTagItem("vs.document.operation").Should().Be("Save");
218+
}
219+
220+
[Fact]
221+
public void StartDocumentActivity_AfterDispose_ThrowsObjectDisposedException()
222+
{
223+
_provider = new ActivitySourceProvider("TestService", "1.0.0");
224+
_provider.Dispose();
225+
226+
Action act = () => _provider.StartDocumentActivity("file.cs", "Open");
227+
228+
act.Should().Throw<ObjectDisposedException>();
229+
}
230+
231+
[Fact]
232+
public void Dispose_MultipleTimes_DoesNotThrow()
233+
{
234+
_provider = new ActivitySourceProvider("TestService", "1.0.0");
235+
236+
Action act = () =>
237+
{
238+
_provider.Dispose();
239+
_provider.Dispose();
240+
_provider.Dispose();
241+
};
242+
243+
act.Should().NotThrow();
244+
}
245+
}
246+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<Project Sdk="Microsoft.NET.Sdk">
3+
4+
<PropertyGroup>
5+
<TargetFramework>net48</TargetFramework>
6+
<LangVersion>latest</LangVersion>
7+
<IsPackable>false</IsPackable>
8+
<IsTestProject>true</IsTestProject>
9+
<RootNamespace>CodingWithCalvin.Otel4Vsix.Tests</RootNamespace>
10+
<AssemblyName>CodingWithCalvin.Otel4Vsix.Tests</AssemblyName>
11+
</PropertyGroup>
12+
13+
<ItemGroup>
14+
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
15+
<PackageReference Include="xunit" Version="2.6.2" />
16+
<PackageReference Include="xunit.runner.visualstudio" Version="2.5.4">
17+
<PrivateAssets>all</PrivateAssets>
18+
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
19+
</PackageReference>
20+
<PackageReference Include="Moq" Version="4.20.70" />
21+
<PackageReference Include="FluentAssertions" Version="6.12.0" />
22+
</ItemGroup>
23+
24+
<ItemGroup>
25+
<ProjectReference Include="..\..\src\CodingWithCalvin.Otel4Vsix\CodingWithCalvin.Otel4Vsix.csproj" />
26+
</ItemGroup>
27+
28+
</Project>

0 commit comments

Comments
 (0)