Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
8bdad4e
ignore failing tests
m-redding Sep 5, 2025
e717cca
move to nunit 4 patterns
m-redding Aug 15, 2025
3416acf
upgrade nunit
m-redding Aug 15, 2025
632549a
first set of tests moved to ClientTestBase (auto sync/async)
m-redding Sep 8, 2025
30f13c7
next set to ClientTestBase
m-redding Sep 8, 2025
16509f5
Merge branch 'main' into addtestframeworktake2
m-redding Sep 8, 2025
a044e6e
last few test files
m-redding Sep 9, 2025
5088ce1
Merge branch 'openai:main' into addtestframeworktake2
m-redding Sep 9, 2025
a0b2c35
move to dev feed version
m-redding Sep 9, 2025
d56bcb8
Merge branch 'openai:main' into addtestframeworktake2
m-redding Sep 12, 2025
74beb44
Merge branch 'addtestframeworktake2' of https://github.com/m-redding/…
m-redding Sep 12, 2025
c4e8c20
add batch/chat tests
m-redding Sep 16, 2025
08cf150
update
m-redding Sep 16, 2025
4325136
Merge branch 'openai:main' into addtestframeworktake2
m-redding Sep 16, 2025
30ea2d0
add chat tests
m-redding Sep 16, 2025
849cbde
add audio tests
m-redding Sep 16, 2025
db74b03
containers, assistants, responses
m-redding Sep 16, 2025
82379a2
models and moderations
m-redding Sep 16, 2025
a95f905
remaining tests
m-redding Sep 17, 2025
cbcd651
be more flexible in test environment
m-redding Sep 17, 2025
ab821f7
changes for pipeline
m-redding Sep 17, 2025
127459c
feedback
m-redding Sep 18, 2025
7442234
bump test proxy and test framework versions
m-redding Sep 22, 2025
a777478
update recordings
m-redding Sep 25, 2025
1f1109c
more recordings updates
m-redding Sep 25, 2025
1f27832
update more recordings
m-redding Sep 26, 2025
d5c5bd0
Merge branch 'main' into addtestframeworktake2
m-redding Sep 26, 2025
565db7d
merge conflicts and new recordings
m-redding Sep 26, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
7 changes: 7 additions & 0 deletions .config/dotnet-tools.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,13 @@
"snippet-generator"
],
"rollForward": false
},
"azure.sdk.tools.testproxy": {
"version": "1.0.0-dev.20250922.2",
"commands": [
"test-proxy"
],
"rollForward": false
}
}
}
426 changes: 124 additions & 302 deletions tests/Assistants/Assistants.VectorStoresTests.cs

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion tests/Assistants/AssistantsSmokeTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ public void ResponseFormatEquality()
Assert.That((AssistantResponseFormat)null != AssistantResponseFormat.CreateTextFormat());
Assert.That(AssistantResponseFormat.CreateTextFormat() != null);
Assert.That(AssistantResponseFormat.CreateTextFormat(), Is.Not.EqualTo(null));
Assert.That(null, Is.Not.EqualTo(AssistantResponseFormat.CreateTextFormat()));
Assert.That(AssistantResponseFormat.CreateTextFormat(), Is.Not.Null);

AssistantResponseFormat jsonSchemaFormat = AssistantResponseFormat.CreateJsonSchemaFormat(
name: "test_schema",
Expand Down
999 changes: 183 additions & 816 deletions tests/Assistants/AssistantsTests.cs

Large diffs are not rendered by default.

18 changes: 4 additions & 14 deletions tests/Audio/GenerateSpeechMockTests.cs
Original file line number Diff line number Diff line change
@@ -1,18 +1,16 @@
using System;
using System.ClientModel;
using System.Threading;
using Microsoft.ClientModel.TestFramework;
using NUnit.Framework;
using OpenAI.Audio;
using OpenAI.Tests.Utility;

namespace OpenAI.Tests.Audio;

[TestFixture(true)]
[TestFixture(false)]
[Parallelizable(ParallelScope.All)]
[Category("Audio")]
[Category("Smoke")]
internal class GenerateSpeechMockTests : SyncAsyncTestBase
internal class GenerateSpeechMockTests : ClientTestBase
{
private static readonly ApiKeyCredential s_fakeCredential = new ApiKeyCredential("key");

Expand All @@ -24,19 +22,11 @@ public GenerateSpeechMockTests(bool isAsync)
[Test]
public void GenerateSpeechRespectsTheCancellationToken()
{
AudioClient client = new AudioClient("model", s_fakeCredential);
AudioClient client = CreateProxyFromClient(new AudioClient("model", s_fakeCredential));
using CancellationTokenSource cancellationSource = new();
cancellationSource.Cancel();

if (IsAsync)
{
Assert.That(async () => await client.GenerateSpeechAsync("text", GeneratedSpeechVoice.Echo, cancellationToken: cancellationSource.Token),
Assert.That(async () => await client.GenerateSpeechAsync("text", GeneratedSpeechVoice.Echo, cancellationToken: cancellationSource.Token),
Throws.InstanceOf<OperationCanceledException>());
}
else
{
Assert.That(() => client.GenerateSpeech("text", GeneratedSpeechVoice.Echo, cancellationToken: cancellationSource.Token),
Throws.InstanceOf<OperationCanceledException>());
}
}
}
28 changes: 11 additions & 17 deletions tests/Audio/GenerateSpeechTests.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using NUnit.Framework;
using Microsoft.ClientModel.TestFramework;
using NUnit.Framework;
using OpenAI.Audio;
using OpenAI.Tests.Utility;
using System;
Expand All @@ -8,11 +9,8 @@

namespace OpenAI.Tests.Audio;

[TestFixture(true)]
[TestFixture(false)]
[Parallelizable(ParallelScope.All)]
[Category("Audio")]
public partial class GenerateSpeechTests : SyncAsyncTestBase
public partial class GenerateSpeechTests : OpenAIRecordedTestBase
{
public GenerateSpeechTests(bool isAsync) : base(isAsync)
{
Expand All @@ -21,14 +19,12 @@ public GenerateSpeechTests(bool isAsync) : base(isAsync)
[Test]
public async Task BasicTextToSpeechWorks()
{
AudioClient client = GetTestClient<AudioClient>(TestScenario.Audio_TTS);
AudioClient client = GetProxiedOpenAIClient<AudioClient>(TestScenario.Audio_TTS);

BinaryData audio = IsAsync
? await client.GenerateSpeechAsync("Hello, world! This is a test.", GeneratedSpeechVoice.Shimmer)
: client.GenerateSpeech("Hello, world! This is a test.", GeneratedSpeechVoice.Shimmer);
BinaryData audio = await client.GenerateSpeechAsync("Hello, world! This is a test.", GeneratedSpeechVoice.Shimmer);

Assert.That(audio, Is.Not.Null);
ValidateGeneratedAudio(audio, "hello");
await ValidateGeneratedAudio(audio, "hello");
}

[Test]
Expand All @@ -41,7 +37,7 @@ public async Task BasicTextToSpeechWorks()
[TestCase("pcm")]
public async Task OutputFormatWorks(string responseFormat)
{
AudioClient client = GetTestClient<AudioClient>(TestScenario.Audio_TTS);
AudioClient client = GetProxiedOpenAIClient<AudioClient>(TestScenario.Audio_TTS);

SpeechGenerationOptions options = new();

Expand All @@ -59,9 +55,7 @@ public async Task OutputFormatWorks(string responseFormat)
};
}

BinaryData audio = IsAsync
? await client.GenerateSpeechAsync("Hello, world!", GeneratedSpeechVoice.Alloy, options)
: client.GenerateSpeech("Hello, world!", GeneratedSpeechVoice.Alloy, options);
BinaryData audio = await client.GenerateSpeechAsync("Hello, world!", GeneratedSpeechVoice.Alloy, options);

Assert.That(audio, Is.Not.Null);

Expand All @@ -82,10 +76,10 @@ public async Task OutputFormatWorks(string responseFormat)
}
}

private void ValidateGeneratedAudio(BinaryData audio, string expectedSubstring)
private async Task ValidateGeneratedAudio(BinaryData audio, string expectedSubstring)
{
AudioClient client = GetTestClient<AudioClient>(TestScenario.Audio_Whisper);
AudioTranscription transcription = client.TranscribeAudio(audio.ToStream(), "hello_world.wav");
AudioClient client = GetProxiedOpenAIClient<AudioClient>(TestScenario.Audio_Whisper);
AudioTranscription transcription = await client.TranscribeAudioAsync(audio.ToStream(), "hello_world.wav");

Assert.That(transcription.Text.ToLowerInvariant(), Contains.Substring(expectedSubstring));
}
Expand Down
37 changes: 13 additions & 24 deletions tests/Audio/TranscriptionMockTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,17 @@
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.ClientModel.TestFramework;
using Microsoft.ClientModel.TestFramework.Mocks;
using NUnit.Framework;
using OpenAI.Audio;
using OpenAI.Tests.Utility;

namespace OpenAI.Tests.Audio;

[TestFixture(true)]
[TestFixture(false)]
[Parallelizable(ParallelScope.All)]
[Category("Audio")]
[Category("Smoke")]
public partial class TranscriptionMockTests : SyncAsyncTestBase
public partial class TranscriptionMockTests : ClientTestBase
{
private static readonly ApiKeyCredential s_fakeCredential = new ApiKeyCredential("key");

Expand Down Expand Up @@ -141,53 +140,43 @@ public async Task TranscribeAudioDeserializesSegment(AudioSourceKind audioSource
[Test]
public void TranscribeAudioFromStreamRespectsTheCancellationToken()
{
AudioClient client = new AudioClient("model", s_fakeCredential);
AudioClient client = CreateProxyFromClient(new AudioClient("model", s_fakeCredential));
using Stream stream = new MemoryStream();
using CancellationTokenSource cancellationSource = new();
cancellationSource.Cancel();

if (IsAsync)
{
Assert.That(async () => await client.TranscribeAudioAsync(stream, "filename", cancellationToken: cancellationSource.Token),
Assert.That(async () => await client.TranscribeAudioAsync(stream, "filename", cancellationToken: cancellationSource.Token),
Throws.InstanceOf<OperationCanceledException>());
}
else
{
Assert.That(() => client.TranscribeAudio(stream, "filename", cancellationToken: cancellationSource.Token),
Throws.InstanceOf<OperationCanceledException>());
}
}

private OpenAIClientOptions GetClientOptionsWithMockResponse(int status, string content)
{
MockPipelineResponse response = new MockPipelineResponse(status);
response.SetContent(content);
MockPipelineResponse response = new MockPipelineResponse(status).WithContent(content);

return new OpenAIClientOptions()
{
Transport = new MockPipelineTransport(response)
Transport = new MockPipelineTransport(_ => response)
{
ExpectSyncPipeline = !IsAsync
}
};
}

private async ValueTask<AudioTranscription> InvokeTranscribeAudioSyncOrAsync(OpenAIClientOptions clientOptions, AudioSourceKind audioSourceKind)
{
AudioClient client = new AudioClient("model", s_fakeCredential, clientOptions);
AudioClient client = CreateProxyFromClient(new AudioClient("model", s_fakeCredential, clientOptions));
string filename = "audio_french.wav";
string path = Path.Combine("Assets", filename);

if (audioSourceKind == AudioSourceKind.UsingStream)
{
using FileStream audio = File.OpenRead(path);

return IsAsync
? await client.TranscribeAudioAsync(audio, filename)
: client.TranscribeAudio(audio, filename);
return await client.TranscribeAudioAsync(audio, filename);
}
else if (audioSourceKind == AudioSourceKind.UsingFilePath)
{
return IsAsync
? await client.TranscribeAudioAsync(path)
: client.TranscribeAudio(path);
return await client.TranscribeAudioAsync(path);
}

Assert.Fail("Invalid source kind.");
Expand Down
46 changes: 16 additions & 30 deletions tests/Audio/TranscriptionTests.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using NUnit.Framework;
using Microsoft.ClientModel.TestFramework;
using NUnit.Framework;
using OpenAI.Audio;
using OpenAI.Tests.Utility;
using System;
Expand All @@ -8,16 +9,12 @@
using System.IO;
using System.Text;
using System.Threading.Tasks;
using System.Transactions;
using static OpenAI.Tests.TestHelpers;

namespace OpenAI.Tests.Audio;

[TestFixture(true)]
[TestFixture(false)]
[Parallelizable(ParallelScope.All)]
[Category("Audio")]
public partial class TranscriptionTests : SyncAsyncTestBase
public partial class TranscriptionTests : OpenAIRecordedTestBase
{
public TranscriptionTests(bool isAsync) : base(isAsync)
{
Expand All @@ -34,7 +31,7 @@ public enum AudioSourceKind
[TestCase(AudioSourceKind.UsingFilePath)]
public async Task TranscriptionWorks(AudioSourceKind audioSourceKind)
{
AudioClient client = GetTestClient<AudioClient>(TestScenario.Audio_Whisper);
AudioClient client = GetProxiedOpenAIClient<AudioClient>(TestScenario.Audio_Whisper);
string filename = "audio_hello_world.mp3";
string path = Path.Combine("Assets", filename);
AudioTranscription transcription = null;
Expand All @@ -43,15 +40,11 @@ public async Task TranscriptionWorks(AudioSourceKind audioSourceKind)
{
using FileStream inputStream = File.OpenRead(path);

transcription = IsAsync
? await client.TranscribeAudioAsync(inputStream, filename)
: client.TranscribeAudio(inputStream, filename);
transcription = await client.TranscribeAudioAsync(inputStream, filename);
}
else if (audioSourceKind == AudioSourceKind.UsingFilePath)
{
transcription = IsAsync
? await client.TranscribeAudioAsync(path)
: client.TranscribeAudio(path);
transcription = await client.TranscribeAudioAsync(path);
}

Assert.That(transcription, Is.Not.Null);
Expand All @@ -65,7 +58,7 @@ public async Task TranscriptionWorks(AudioSourceKind audioSourceKind)
[TestCase(AudioTimestampGranularities.Word | AudioTimestampGranularities.Segment)]
public async Task TimestampsWork(AudioTimestampGranularities granularityFlags)
{
AudioClient client = GetTestClient<AudioClient>(TestScenario.Audio_Whisper);
AudioClient client = GetProxiedOpenAIClient<AudioClient>(TestScenario.Audio_Whisper);

using FileStream inputStream = File.OpenRead(Path.Combine("Assets", "audio_hello_world.mp3"));

Expand All @@ -76,9 +69,7 @@ public async Task TimestampsWork(AudioTimestampGranularities granularityFlags)
TimestampGranularities = granularityFlags,
};

ClientResult<AudioTranscription> transcriptionResult = IsAsync
? await client.TranscribeAudioAsync(inputStream, "audio_hello_world.mp3", options)
: client.TranscribeAudio(inputStream, "audio_hello_world.mp3", options);
ClientResult<AudioTranscription> transcriptionResult = await client.TranscribeAudioAsync(inputStream, "audio_hello_world.mp3", options);

PipelineResponse rawResponse = transcriptionResult.GetRawResponse();
Assert.That(rawResponse.Content.ToString(), Is.Not.Null.And.Not.Empty);
Expand Down Expand Up @@ -140,7 +131,7 @@ public async Task TimestampsWork(AudioTimestampGranularities granularityFlags)
[TestCase(null)]
public async Task TranscriptionFormatsWork(string responseFormat)
{
AudioClient client = GetTestClient<AudioClient>(TestScenario.Audio_Whisper);
AudioClient client = GetProxiedOpenAIClient<AudioClient>(TestScenario.Audio_Whisper);
string path = Path.Combine("Assets", "audio_hello_world.mp3");

AudioTranscriptionOptions options = new()
Expand All @@ -156,9 +147,7 @@ public async Task TranscriptionFormatsWork(string responseFormat)
}
};

AudioTranscription transcription = IsAsync
? await client.TranscribeAudioAsync(path, options)
: client.TranscribeAudio(path, options);
AudioTranscription transcription = await client.TranscribeAudioAsync(path, options);

Assert.That(transcription?.Text?.ToLowerInvariant(), Does.Contain("hello"));

Expand All @@ -180,7 +169,6 @@ public async Task TranscriptionFormatsWork(string responseFormat)

Assert.That(segment.Id, Is.EqualTo(i));
Assert.That(segment.EndTime, Is.GreaterThanOrEqualTo(segment.StartTime));
Assert.That(segment.TokenIds, Is.Not.Null);
Assert.That(segment.TokenIds.Length, Is.GreaterThan(0));

Assert.That(segment.AverageLogProbability, Is.LessThan(-0.001f).Or.GreaterThan(0.001f));
Expand All @@ -200,7 +188,7 @@ public async Task TranscriptionFormatsWork(string responseFormat)
[Test]
public async Task IncludesWork()
{
AudioClient client = GetTestClient<AudioClient>(TestScenario.Audio_Gpt_4o_Mini_Transcribe);
AudioClient client = GetProxiedOpenAIClient<AudioClient>(TestScenario.Audio_Gpt_4o_Mini_Transcribe);
string filename = "audio_hello_world.mp3";
string path = Path.Combine("Assets", filename);

Expand All @@ -218,7 +206,7 @@ public async Task IncludesWork()
[Test]
public async Task StreamingIncludesWork()
{
AudioClient client = GetTestClient<AudioClient>(TestScenario.Audio_Gpt_4o_Mini_Transcribe);
AudioClient client = GetProxiedOpenAIClient<AudioClient>(TestScenario.Audio_Gpt_4o_Mini_Transcribe);
string filename = "audio_hello_world.mp3";
string path = Path.Combine("Assets", filename);

Expand Down Expand Up @@ -252,7 +240,7 @@ in client.TranscribeAudioStreamingAsync(
[Test]
public async Task BadTranscriptionRequest()
{
AudioClient client = GetTestClient<AudioClient>(TestScenario.Audio_Whisper);
AudioClient client = GetProxiedOpenAIClient<AudioClient>(TestScenario.Audio_Whisper);

string path = Path.Combine("Assets", "audio_hello_world.mp3");

Expand All @@ -265,9 +253,7 @@ public async Task BadTranscriptionRequest()

try
{
_ = IsAsync
? await client.TranscribeAudioAsync(path, options)
: client.TranscribeAudio(path, options);
await client.TranscribeAudioAsync(path, options);
}
catch (Exception ex)
{
Expand All @@ -283,7 +269,7 @@ public async Task BadTranscriptionRequest()
[TestCase(AudioSourceKind.UsingFilePath)]
public async Task StreamingTranscriptionWorks(AudioSourceKind audioSourceKind)
{
AudioClient client = GetTestClient<AudioClient>(TestScenario.Audio_Gpt_4o_Mini_Transcribe);
AudioClient client = GetProxiedOpenAIClient<AudioClient>(TestScenario.Audio_Gpt_4o_Mini_Transcribe);
string filename = "audio_hello_world.mp3";
string path = Path.Combine("Assets", filename);

Expand Down Expand Up @@ -328,7 +314,7 @@ public async Task StreamingTranscriptionWorks(AudioSourceKind audioSourceKind)
[TestCase(AudioSourceKind.UsingFilePath)]
public void StreamingTranscriptionThrowsForWhisperModel(AudioSourceKind audioSourceKind)
{
AudioClient client = GetTestClient<AudioClient>(TestScenario.Audio_Whisper);
AudioClient client = GetProxiedOpenAIClient<AudioClient>(TestScenario.Audio_Whisper);
string filename = "audio_hello_world.mp3";
string path = Path.Combine("Assets", filename);

Expand Down
Loading