Skip to content

Commit

Permalink
Merge pull request #56 from jodendaal/AcceptanceTests
Browse files Browse the repository at this point in the history
Acceptance Tests
  • Loading branch information
jodendaal committed Mar 22, 2023
2 parents 6c18c76 + 206110f commit e1912ce
Show file tree
Hide file tree
Showing 19 changed files with 735 additions and 4 deletions.
5 changes: 5 additions & 0 deletions .github/workflows/PullRequestValidate.yml
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,11 @@ jobs:
- name: Execute unit tests
run: dotnet test src/OpenAI.Net.Tests/OpenAI.Net.Tests.csproj --configuration Release /p:CollectCoverage=true /p:CoverletOutputFormat=opencover


# Execute Acceptance tests in the solution
- name: Execute acceptance tests
run: dotnet test src/OpenAI.Net.Acceptance.Tests/OpenAI.Net.Acceptance.Tests.csproj --configuration Release

# Install Stryker
- name: Install Stryker
run: dotnet tool install dotnet-stryker --tool-path src/OpenAI.Net.Tests
Expand Down
4 changes: 4 additions & 0 deletions .github/workflows/dotnet-desktop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,10 @@ jobs:
- name: Execute unit tests
run: dotnet test src/OpenAI.Net.Tests/OpenAI.Net.Tests.csproj --configuration Release /p:CollectCoverage=true /p:CoverletOutputFormat=opencover

# Execute Acceptance tests in the solution
- name: Execute acceptance tests
run: dotnet test src/OpenAI.Net.Acceptance.Tests/OpenAI.Net.Acceptance.Tests.csproj --configuration Release

# Install Stryker
- name: Install Stryker
run: dotnet tool install dotnet-stryker --tool-path src/OpenAI.Net.Tests
Expand Down
42 changes: 42 additions & 0 deletions src/OpenAI.Net.Acceptance.Tests/AudioTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
using FluentAssertions;
using NUnit.Framework;
using OpenAI.Net.Models.Requests;
using OpenAI.Net.Models.Responses;

namespace OpenAI.Net.Acceptance.Tests
{
public class AudioTests : BaseTest
{
[Test]
public async Task GetTranscription()
{
var request = CreateObjectWithRandomData<CreateTranscriptionRequest>();
var responseObject = CreateObjectWithRandomData<AudioReponse>();

ConfigureWireMockPostMultipartFormData("/v1/audio/transcriptions", request, responseObject);

var response = await OpenAIService.Audio.GetTranscription(request);

response.IsSuccess.Should().BeTrue();
response.Result?.Text.Should().NotBeNullOrEmpty();
response.Result.Should().BeEquivalentTo(responseObject);
}

[Test]
public async Task GetTranslation()
{
var request = CreateObjectWithRandomData<CreateTranslationRequest>();
var responseObject = CreateObjectWithRandomData<AudioReponse>();

ConfigureWireMockPostMultipartFormData("/v1/audio/translations", request, responseObject);

var response = await OpenAIService.Audio.GetTranslation(request);

response.IsSuccess.Should().BeTrue();
response.Result?.Text.Should().NotBeNullOrEmpty();
response.Result.Should().BeEquivalentTo(responseObject);
}


}
}
173 changes: 173 additions & 0 deletions src/OpenAI.Net.Acceptance.Tests/BaseTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
using AutoFixture;
using AutoFixture.Dsl;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using System.Linq.Expressions;
using System.Text.Json;
using WireMock.RequestBuilders;
using WireMock.ResponseBuilders;
using WireMock.Server;

namespace OpenAI.Net.Acceptance.Tests
{
public class BaseTest : IDisposable
{
public readonly JsonSerializerOptions JsonSerializerOptions = new JsonSerializerOptions()
{
DefaultIgnoreCondition = System.Text.Json.Serialization.JsonIgnoreCondition.WhenWritingNull,
PropertyNamingPolicy = JsonNamingPolicy.CamelCase
};
public readonly WireMockServer? WireMockServer;
public TestConfig Config { get; private set; }

private IServiceProvider _serviceProvider;
public BaseTest()
{
WireMockServer = WireMockServer.Start();
Config = new TestConfig
{
Apikey = "ABC",
ApiUrl = WireMockServer?.Url ?? "",
OrganizationId = "My-Org-Id"
};

var configuration = new ConfigurationBuilder()
.AddUserSecrets<BaseTest>()
.Build();

var serviceCollection = new ServiceCollection();
serviceCollection.AddOpenAIServices(options => {
options.ApiKey = Config.Apikey;
options.ApiUrl = Config.ApiUrl;
options.OrganizationId = Config.OrganizationId;
});

_serviceProvider = serviceCollection.BuildServiceProvider();
}

public IOpenAIService OpenAIService
{
get
{
return _serviceProvider.GetRequiredService<IOpenAIService>();
}
}

public T CreateObjectWithRandomData<T>()
{
var fixture = new Fixture();
return fixture.Create<T>();
}

public void ConfigureWireMockPostJson<TReqeust,TResponse>(string path,TReqeust reqeust,TResponse response)
{
var body = (response is string) ? response as string :
JsonSerializer.Serialize(
response,
this.JsonSerializerOptions);

this.WireMockServer?.Given(
Request.Create()
.WithPath(path)
.WithHeader("Authorization", $"Bearer {Config.Apikey}")
.WithHeader("OpenAI-Organization", $"{Config.OrganizationId}")
.WithHeader("Content-Type", "application/json; charset=utf-8")
.UsingPost()
.WithBody(JsonSerializer.Serialize(
reqeust,
this.JsonSerializerOptions)))
.RespondWith(
Response.Create()
.WithBody(body??""));
}

public void ConfigureWireMockPostMultipartFormData<TReqeust, TResponse>(string path, TReqeust reqeust, TResponse response)//QQQ Come back this this and check if we can validate header and contents
{
var body = (response is string) ? response as string :
JsonSerializer.Serialize(
response,
this.JsonSerializerOptions);

var formData = reqeust?.ToMultipartFormDataContent();

this.WireMockServer?.Given(
Request.Create()
.WithPath(path)
.WithHeader("Authorization", $"Bearer {Config.Apikey}")
.WithHeader("OpenAI-Organization", $"{Config.OrganizationId}")
.UsingPost()
//.WithHeader("Content-Type", "multipart/form-data")
//.WithBody(formData)
)

.RespondWith(
Response.Create()
.WithBody(body ?? ""));
}


public void ConfigureWireMockDelete<TResponse>(string path, TResponse response)
{

var body = (response is string) ? response as string :
JsonSerializer.Serialize(
response,
this.JsonSerializerOptions);

this.WireMockServer?.Given(
Request.Create()
.WithPath(path)
.WithHeader("Authorization", $"Bearer {Config.Apikey}")
.WithHeader("OpenAI-Organization", $"{Config.OrganizationId}")
.UsingDelete())
.RespondWith(
Response.Create()
.WithBody(body ?? ""));
}

public void ConfigureWireMockGet<TResponse>(string path, TResponse response)
{
var body = (response is string) ? response as string :
JsonSerializer.Serialize(
response,
this.JsonSerializerOptions);

this.WireMockServer?.Given(
Request.Create()
.WithPath(path)
.WithHeader("Authorization", $"Bearer {Config.Apikey}")
.WithHeader("OpenAI-Organization", $"{Config.OrganizationId}")
.UsingGet())
.RespondWith(
Response.Create()
.WithBody(body ?? ""));
}

public void Dispose()
{
this.WireMockServer?.Dispose();
}
}


public class TestConfig
{
public string? Apikey { get; set; }
public string? ApiUrl { get; set; }
public string? OrganizationId { get; set; }
}

public static class AutoFixtureExtensions
{
public static IPostprocessComposer<T> WithValues<T, TProperty>(this IPostprocessComposer<T> composer,
Expression<Func<T, TProperty>> propertyPicker,
params TProperty[] values)
{
var queue = new Queue<TProperty>(values);

return composer.With(propertyPicker, () => queue.Dequeue());
}
}


}
74 changes: 74 additions & 0 deletions src/OpenAI.Net.Acceptance.Tests/ChatCompletion.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
using AutoFixture;
using FluentAssertions;
using NUnit.Framework;
using OpenAI.Net.Models.Requests;
using OpenAI.Net.Models.Responses;
using System.Text.Json;

namespace OpenAI.Net.Acceptance.Tests
{
internal class ChatCompletionTests : BaseTest
{
[Test]
public async Task Get()
{
var fixture = new Fixture();

fixture.Customizations.Add(
new ElementsBuilder<Message>(
Message.Create(ChatRoleType.Assistant, fixture.Create<string>()),
Message.Create(ChatRoleType.User, fixture.Create<string>()),
Message.Create(ChatRoleType.System, fixture.Create<string>())));

var chatCompletionRequest = fixture.Create<ChatCompletionRequest>();
var chatCompletionResponse = fixture.Create<ChatCompletionResponse>();

ConfigureWireMockPostJson("/v1/chat/completions", chatCompletionRequest, chatCompletionResponse);

var response = await OpenAIService.Chat.Get(chatCompletionRequest);

response.IsSuccess.Should().BeTrue();
response.Result?.Choices.Should().HaveCountGreaterThan(1);
response.Result.Should().BeEquivalentTo(chatCompletionResponse);
}

[Test]
public async Task GetStream()
{
var fixture = new Fixture();

fixture.Customizations.Add(
new ElementsBuilder<Message>(
Message.Create(ChatRoleType.Assistant, fixture.Create<string>()),
Message.Create(ChatRoleType.User, fixture.Create<string>()),
Message.Create(ChatRoleType.System, fixture.Create<string>())));

var chatCompletionRequest = fixture.Create<ChatCompletionRequest>();
chatCompletionRequest.Stream = true;

var chatCompletionResponseList = fixture.Create<List<ChatStreamCompletionResponse>>();


var responseBody = "data: ";
foreach (var response in chatCompletionResponseList)
{
var json = JsonSerializer.Serialize(response, this.JsonSerializerOptions).Replace("\r\n", "").Replace("\n", "");
responseBody += $"{json}\r\n";
}
responseBody += "[DONE]";

ConfigureWireMockPostJson("/v1/chat/completions", chatCompletionRequest, responseBody);

int index = 0;
await foreach (var response in OpenAIService.Chat.GetStream(chatCompletionRequest))
{
response.IsSuccess.Should().BeTrue();
response.Result.Should().BeEquivalentTo(chatCompletionResponseList[index]);
response.Result?.Choices.Should().HaveCountGreaterThan(0);
index++;
}

index.Should().Be(chatCompletionResponseList.Count);
}
}
}
25 changes: 25 additions & 0 deletions src/OpenAI.Net.Acceptance.Tests/EmbeddingTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
using FluentAssertions;
using NUnit.Framework;
using OpenAI.Net.Models.Requests;
using OpenAI.Net.Models.Responses;

namespace OpenAI.Net.Acceptance.Tests
{
public class EmbeddingTests : BaseTest
{
[Test]
public async Task Create()
{
var request = CreateObjectWithRandomData<EmbeddingsRequest>();
var responseObject = CreateObjectWithRandomData<EmbeddingsResponse>();

ConfigureWireMockPostJson("/v1/embeddings", request,responseObject);

var response = await OpenAIService.Embeddings.Create(request);

response.IsSuccess.Should().BeTrue();
response.Result?.Data.Should().HaveCountGreaterThan(1);
response.Result.Should().BeEquivalentTo(responseObject);
}
}
}

0 comments on commit e1912ce

Please sign in to comment.