Skip to content

Commit 5427ac2

Browse files
committed
test: add tests
1 parent d2cce55 commit 5427ac2

File tree

4 files changed

+402
-11
lines changed

4 files changed

+402
-11
lines changed

test/Cnblogs.DashScope.Sdk.UnitTests/ChatClientTests.cs

Lines changed: 141 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
using System.Text;
2+
using Cnblogs.DashScope.Core;
23
using Cnblogs.DashScope.Sdk.UnitTests.Utils;
34
using FluentAssertions;
45
using Microsoft.Extensions.AI;
56
using NSubstitute;
7+
using NSubstitute.Extensions;
68

79
namespace Cnblogs.DashScope.Sdk.UnitTests;
810

@@ -12,9 +14,13 @@ public class ChatClientTests
1214
public async Task ChatClient_TextCompletion_SuccessAsync()
1315
{
1416
// Arrange
15-
const bool sse = false;
16-
var testCase = Snapshots.TextGeneration.MessageFormat.SingleMessage;
17-
var (dashScopeClient, handler) = await Sut.GetTestClientAsync(sse, testCase);
17+
var testCase = Snapshots.TextGeneration.MessageFormat.SingleChatClientMessage;
18+
var dashScopeClient = Substitute.For<IDashScopeClient>();
19+
dashScopeClient.Configure()
20+
.GetTextCompletionAsync(
21+
Arg.Any<ModelRequest<TextGenerationInput, ITextGenerationParameters>>(),
22+
Arg.Any<CancellationToken>())
23+
.Returns(Task.FromResult(testCase.ResponseModel));
1824
var client = dashScopeClient.AsChatClient(testCase.RequestModel.Model);
1925
var content = testCase.RequestModel.Input.Messages!.First().Content;
2026
var parameter = testCase.RequestModel.Parameters;
@@ -25,15 +31,20 @@ public async Task ChatClient_TextCompletion_SuccessAsync()
2531
new ChatOptions()
2632
{
2733
FrequencyPenalty = parameter?.RepetitionPenalty,
34+
PresencePenalty = parameter?.PresencePenalty,
2835
ModelId = testCase.RequestModel.Model,
2936
MaxOutputTokens = parameter?.MaxTokens,
3037
Seed = (long?)parameter?.Seed,
3138
Temperature = parameter?.Temperature,
39+
TopK = parameter?.TopK,
40+
TopP = parameter?.TopP,
41+
ToolMode = ChatToolMode.Auto
3242
});
3343

3444
// Assert
35-
handler.Received().MockSend(
36-
Arg.Any<HttpRequestMessage>(),
45+
_ = dashScopeClient.Received().GetTextCompletionAsync(
46+
Arg.Is<ModelRequest<TextGenerationInput, ITextGenerationParameters>>(
47+
m => IsEquivalent(m, testCase.RequestModel)),
3748
Arg.Any<CancellationToken>());
3849
response.Message.Text.Should().Be(testCase.ResponseModel.Output.Choices?.First().Message.Content);
3950
}
@@ -43,8 +54,15 @@ public async Task ChatClient_TextCompletionStream_SuccessAsync()
4354
{
4455
// Arrange
4556
const bool sse = true;
46-
var testCase = Snapshots.TextGeneration.MessageFormat.SingleMessageIncremental;
47-
var (dashScopeClient, handler) = await Sut.GetTestClientAsync(sse, testCase);
57+
var testCase = Snapshots.TextGeneration.MessageFormat.SingleMessageChatClientIncremental;
58+
var dashScopeClient = Substitute.For<IDashScopeClient>();
59+
var returnThis = new[] { testCase.ResponseModel }.ToAsyncEnumerable();
60+
dashScopeClient
61+
.Configure()
62+
.GetTextCompletionStreamAsync(
63+
Arg.Any<ModelRequest<TextGenerationInput, ITextGenerationParameters>>(),
64+
Arg.Any<CancellationToken>())
65+
.Returns(returnThis);
4866
var client = dashScopeClient.AsChatClient(testCase.RequestModel.Model);
4967
var content = testCase.RequestModel.Input.Messages!.First().Content;
5068
var parameter = testCase.RequestModel.Parameters;
@@ -55,10 +73,15 @@ public async Task ChatClient_TextCompletionStream_SuccessAsync()
5573
new ChatOptions()
5674
{
5775
FrequencyPenalty = parameter?.RepetitionPenalty,
76+
PresencePenalty = parameter?.PresencePenalty,
5877
ModelId = testCase.RequestModel.Model,
5978
MaxOutputTokens = parameter?.MaxTokens,
6079
Seed = (long?)parameter?.Seed,
6180
Temperature = parameter?.Temperature,
81+
TopK = parameter?.TopK,
82+
TopP = parameter?.TopP,
83+
StopSequences = ["你好"],
84+
ToolMode = ChatToolMode.Auto
6285
});
6386
var text = new StringBuilder();
6487
await foreach (var update in response)
@@ -67,9 +90,118 @@ public async Task ChatClient_TextCompletionStream_SuccessAsync()
6790
}
6891

6992
// Assert
70-
handler.Received().MockSend(
71-
Arg.Any<HttpRequestMessage>(),
93+
_ = dashScopeClient.Received().GetTextCompletionStreamAsync(
94+
Arg.Is<ModelRequest<TextGenerationInput, ITextGenerationParameters>>(
95+
m => IsEquivalent(m, testCase.RequestModel)),
7296
Arg.Any<CancellationToken>());
7397
text.ToString().Should().Be(testCase.ResponseModel.Output.Choices?.First().Message.Content);
7498
}
99+
100+
[Fact]
101+
public async Task ChatClient_ImageRecognition_SuccessAsync()
102+
{
103+
// Arrange
104+
const bool sse = false;
105+
var testCase = Snapshots.MultimodalGeneration.VlChatClientNoSse;
106+
var dashScopeClient = Substitute.For<IDashScopeClient>();
107+
dashScopeClient.Configure()
108+
.GetMultimodalGenerationAsync(
109+
Arg.Any<ModelRequest<MultimodalInput, IMultimodalParameters>>(),
110+
Arg.Any<CancellationToken>())
111+
.Returns(Task.FromResult(testCase.ResponseModel));
112+
var client = dashScopeClient.AsChatClient(testCase.RequestModel.Model);
113+
var contents = testCase.RequestModel.Input.Messages.Last().Content;
114+
var messages = new List<ChatMessage>
115+
{
116+
new(
117+
ChatRole.User,
118+
[new ImageContent(contents[0].Image!), new TextContent(contents[1].Text)])
119+
};
120+
var parameter = testCase.RequestModel.Parameters;
121+
122+
// Act
123+
var response = await client.CompleteAsync(
124+
messages,
125+
new ChatOptions
126+
{
127+
FrequencyPenalty = parameter?.RepetitionPenalty,
128+
PresencePenalty = parameter?.PresencePenalty,
129+
ModelId = testCase.RequestModel.Model,
130+
MaxOutputTokens = parameter?.MaxTokens,
131+
Seed = (long?)parameter?.Seed,
132+
Temperature = parameter?.Temperature,
133+
TopK = parameter?.TopK,
134+
TopP = parameter?.TopP,
135+
});
136+
137+
// Assert
138+
await dashScopeClient.Received().GetMultimodalGenerationAsync(
139+
Arg.Is<ModelRequest<MultimodalInput, IMultimodalParameters>>(m => IsEquivalent(m, testCase.RequestModel)),
140+
Arg.Any<CancellationToken>());
141+
response.Choices[0].Text.Should()
142+
.BeEquivalentTo(testCase.ResponseModel.Output.Choices[0].Message.Content[0].Text);
143+
}
144+
145+
[Fact]
146+
public async Task ChatClient_ImageRecognitionStream_SuccessAsync()
147+
{
148+
// Arrange
149+
const bool sse = true;
150+
var testCase = Snapshots.MultimodalGeneration.VlChatClientSse;
151+
var dashScopeClient = Substitute.For<IDashScopeClient>();
152+
dashScopeClient.Configure()
153+
.GetMultimodalGenerationStreamAsync(
154+
Arg.Any<ModelRequest<MultimodalInput, IMultimodalParameters>>(),
155+
Arg.Any<CancellationToken>())
156+
.Returns(new[] { testCase.ResponseModel }.ToAsyncEnumerable());
157+
var client = dashScopeClient.AsChatClient(testCase.RequestModel.Model);
158+
var contents = testCase.RequestModel.Input.Messages.Last().Content;
159+
var messages = new List<ChatMessage>
160+
{
161+
new(
162+
ChatRole.User,
163+
[new ImageContent(contents[0].Image!), new TextContent(contents[1].Text)])
164+
};
165+
var parameter = testCase.RequestModel.Parameters;
166+
167+
// Act
168+
var response = client.CompleteStreamingAsync(
169+
messages,
170+
new ChatOptions()
171+
{
172+
FrequencyPenalty = parameter?.RepetitionPenalty,
173+
PresencePenalty = parameter?.PresencePenalty,
174+
ModelId = testCase.RequestModel.Model,
175+
MaxOutputTokens = parameter?.MaxTokens,
176+
Seed = (long?)parameter?.Seed,
177+
Temperature = parameter?.Temperature,
178+
TopK = parameter?.TopK,
179+
TopP = parameter?.TopP,
180+
});
181+
var text = new StringBuilder();
182+
await foreach (var update in response)
183+
{
184+
text.Append(update.Text);
185+
}
186+
187+
// Assert
188+
_ = dashScopeClient.Received().GetMultimodalGenerationStreamAsync(
189+
Arg.Is<ModelRequest<MultimodalInput, IMultimodalParameters>>(m => IsEquivalent(m, testCase.RequestModel)),
190+
Arg.Any<CancellationToken>());
191+
text.ToString().Should().Be(testCase.ResponseModel.Output.Choices.First().Message.Content[0].Text);
192+
}
193+
194+
private bool IsEquivalent<T>(T left, T right)
195+
{
196+
try
197+
{
198+
left.Should().BeEquivalentTo(right);
199+
}
200+
catch (Exception e)
201+
{
202+
return false;
203+
}
204+
205+
return true;
206+
}
75207
}

test/Cnblogs.DashScope.Sdk.UnitTests/Cnblogs.DashScope.Sdk.UnitTests.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
1212
</PackageReference>
1313
<PackageReference Include="FluentAssertions" Version="6.12.2" />
14+
<PackageReference Include="Microsoft.Extensions.AI" Version="9.0.1-preview.1.24570.5" />
1415
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.12.0" />
1516
<PackageReference Include="NSubstitute" Version="5.3.0" />
1617
<PackageReference Include="System.Linq.Async" Version="6.0.1" />

test/Cnblogs.DashScope.Sdk.UnitTests/TextGenerationSerializationTests.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,8 @@ public async Task ConversationCompletion_MessageFormatSse_SuccessAsync(
141141
public static readonly TheoryData<RequestSnapshot<ModelRequest<TextGenerationInput, ITextGenerationParameters>,
142142
ModelResponse<TextGenerationOutput, TextGenerationTokenUsage>>> SingleGenerationMessageFormatData = new(
143143
Snapshots.TextGeneration.MessageFormat.SingleMessage,
144-
Snapshots.TextGeneration.MessageFormat.SingleMessageWithTools);
144+
Snapshots.TextGeneration.MessageFormat.SingleMessageWithTools,
145+
Snapshots.TextGeneration.MessageFormat.SingleMessageJson);
145146

146147
public static readonly TheoryData<RequestSnapshot<ModelRequest<TextGenerationInput, ITextGenerationParameters>,
147148
ModelResponse<TextGenerationOutput, TextGenerationTokenUsage>>> ConversationMessageFormatSseData = new(

0 commit comments

Comments
 (0)