Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Migrate to xunit v3 #1531

Merged
merged 1 commit into from
Dec 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 2 additions & 4 deletions Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
<PackageVersion Include="coverlet.msbuild" Version="6.0.2" />
<PackageVersion Include="GitHubActionsTestLogger" Version="2.4.1" />
<PackageVersion Include="JustEat.HttpClientInterception" Version="5.0.0" />
<PackageVersion Include="MartinCostello.Logging.XUnit" Version="0.4.0" />
<PackageVersion Include="MartinCostello.Logging.XUnit.v3" Version="0.5.0" />
<PackageVersion Include="MartinCostello.Testing.AwsLambdaTestServer" Version="0.9.0" />
<PackageVersion Include="Microsoft.AspNetCore.WebUtilities" Version="9.0.0" />
<PackageVersion Include="Microsoft.Extensions.Configuration.Binder" Version="9.0.0" />
Expand All @@ -40,9 +40,7 @@
<PackageVersion Include="Shouldly" Version="4.2.1" />
<PackageVersion Include="System.Private.Uri" Version="4.3.2" />
<PackageVersion Include="System.Text.Json" Version="9.0.0" />
<PackageVersion Include="xRetry" Version="1.9.0" />
<PackageVersion Include="xunit" Version="2.9.2" />
<PackageVersion Include="xunit.runner.visualstudio" Version="3.0.0" />
<PackageVersion Include="Xunit.SkippableFact" Version="1.5.23" />
<PackageVersion Include="xunit.v3" Version="1.0.0" />
</ItemGroup>
</Project>
11 changes: 7 additions & 4 deletions test/LondonTravel.Skill.EndToEndTests/CloudWatchLogsFixture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
using Amazon.CloudWatchLogs;
using Amazon.CloudWatchLogs.Model;
using Xunit.Sdk;
using Xunit.v3;

namespace MartinCostello.LondonTravel.Skill.EndToEndTests;

Expand All @@ -16,7 +17,7 @@ public class CloudWatchLogsFixture(IMessageSink diagnosticMessageSink) : IAsyncL

internal Dictionary<string, string> Requests { get; } = [];

public async Task DisposeAsync()
public async ValueTask DisposeAsync()
{
if (Requests.Count < 1)
{
Expand Down Expand Up @@ -96,18 +97,20 @@ regionName is not null &&
.OrderBy((p) => p.Event.Timestamp)
.ToList();

diagnosticMessageSink.OnMessage(new DiagnosticMessage($"Found {events.Count} CloudWatch log events."));
diagnosticMessageSink.OnMessage(new DiagnosticMessage() { Message = $"Found {events.Count} CloudWatch log events." });

foreach ((_, string message) in events)
{
diagnosticMessageSink.OnMessage(new DiagnosticMessage(message));
diagnosticMessageSink.OnMessage(new DiagnosticMessage() { Message = message });
}

await TryPostLogsToPullRequestAsync(events.Select((p) => p.Event));
}

GC.SuppressFinalize(this);
}

public Task InitializeAsync() => Task.CompletedTask;
public ValueTask InitializeAsync() => ValueTask.CompletedTask;

private static async Task TryPostLogsToPullRequestAsync(IEnumerable<LogEvent> events)
{
Expand Down
18 changes: 10 additions & 8 deletions test/LondonTravel.Skill.EndToEndTests/LambdaTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

namespace MartinCostello.LondonTravel.Skill.EndToEndTests;

[Collection(CloudWatchLogsFixtureCollection.Name)]
[Collection<CloudWatchLogsFixtureCollection>]
public class LambdaTests(CloudWatchLogsFixture fixture, ITestOutputHelper outputHelper)
{
public static TheoryData<string> Payloads()
Expand All @@ -24,22 +24,24 @@ public static TheoryData<string> Payloads()
return payloads;
}

[SkippableTheory]
[Theory]
[MemberData(nameof(Payloads))]
public async Task Can_Invoke_Intent_Can_Get_Json_Response(string payloadName)
{
var credentials = TestConfiguration.GetCredentials();

Skip.If(credentials is null, "No AWS credentials are configured.");
Assert.SkipWhen(credentials is null, "No AWS credentials are configured.");

string? functionName = TestConfiguration.FunctionName;
string? regionName = TestConfiguration.RegionName;

Skip.If(string.IsNullOrEmpty(functionName), "No Lambda function name is configured.");
Skip.If(string.IsNullOrEmpty(regionName), "No AWS region name is configured.");
Assert.SkipWhen(string.IsNullOrEmpty(functionName), "No Lambda function name is configured.");
Assert.SkipWhen(string.IsNullOrEmpty(regionName), "No AWS region name is configured.");

// Arrange
string payload = await File.ReadAllTextAsync(Path.Combine("Payloads", $"{payloadName}.json"));
var cancellationToken = TestContext.Current.CancellationToken;

string payload = await File.ReadAllTextAsync(Path.Combine("Payloads", $"{payloadName}.json"), cancellationToken);

var region = RegionEndpoint.GetBySystemName(regionName);

Expand All @@ -57,7 +59,7 @@ public async Task Can_Invoke_Intent_Can_Get_Json_Response(string payloadName)
outputHelper.WriteLine($"Payload: {request.Payload}");

// Act
var invocation = await client.InvokeAsync(request);
var invocation = await client.InvokeAsync(request, cancellationToken);

// Assert
invocation.ShouldNotBeNull();
Expand All @@ -66,7 +68,7 @@ public async Task Can_Invoke_Intent_Can_Get_Json_Response(string payloadName)
fixture.Requests[invocation.ResponseMetadata.RequestId] = payloadName;

using var reader = new StreamReader(invocation.Payload);
string responsePayload = await reader.ReadToEndAsync();
string responsePayload = await reader.ReadToEndAsync(cancellationToken);

outputHelper.WriteLine($"ExecutedVersion: {invocation.ExecutedVersion}");
outputHelper.WriteLine($"FunctionError: {invocation.FunctionError}");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,14 @@
<PackageReference Include="GitHubActionsTestLogger" NoWarn="RT0003" />
<PackageReference Include="Microsoft.NET.Test.Sdk" />
<PackageReference Include="Shouldly" />
<PackageReference Include="xunit" />
<PackageReference Include="xunit.runner.visualstudio" />
<PackageReference Include="Xunit.SkippableFact" />
<PackageReference Include="xunit.v3" />
</ItemGroup>
<ItemGroup>
<Content Include="xunit.runner.json;Payloads\*.json" CopyToOutputDirectory="PreserveNewest" />
</ItemGroup>
<ItemGroup>
<Using Include="Shouldly" />
<Using Include="Xunit" />
<Using Include="Xunit.Abstractions" />
</ItemGroup>
</Project>
16 changes: 8 additions & 8 deletions test/LondonTravel.Skill.EndToEndTests/SkillTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ namespace MartinCostello.LondonTravel.Skill.EndToEndTests;

public class SkillTests(ITestOutputHelper outputHelper)
{
[SkippableTheory]
[Theory]
[InlineData("Alexa, ask London Travel if there is any disruption today.")]
[InlineData("Alexa, ask London Travel about the DLR.")]
[InlineData("Alexa, ask London Travel about the Elizabeth line.")]
Expand All @@ -24,10 +24,10 @@ public async Task Can_Invoke_Skill_And_Get_Valid_Response(string content)
string? skillId = TestConfiguration.SkillId;
string? stage = TestConfiguration.SkillStage;

Skip.If(string.IsNullOrEmpty(functionName), "No Lambda function name is configured.");
Skip.If(string.IsNullOrEmpty(regionName), "No AWS region name is configured.");
Skip.If(string.IsNullOrEmpty(skillId), "No skill ID is configured.");
Skip.If(string.IsNullOrEmpty(stage), "No skill stage is configured.");
Assert.SkipWhen(string.IsNullOrEmpty(functionName), "No Lambda function name is configured.");
Assert.SkipWhen(string.IsNullOrEmpty(regionName), "No AWS region name is configured.");
Assert.SkipWhen(string.IsNullOrEmpty(skillId), "No skill ID is configured.");
Assert.SkipWhen(string.IsNullOrEmpty(stage), "No skill stage is configured.");

using var client = await CreateHttpClientAsync();

Expand Down Expand Up @@ -83,9 +83,9 @@ private static async Task<string> GenerateAccessTokenAsync()
string? clientSecret = TestConfiguration.AlexaClientSecret;
string? refreshToken = TestConfiguration.AlexaRefreshToken;

Skip.If(string.IsNullOrEmpty(clientId), "No client ID is configured.");
Skip.If(string.IsNullOrEmpty(clientSecret), "No client secret is configured.");
Skip.If(string.IsNullOrEmpty(refreshToken), "No refresh token is configured.");
Assert.SkipWhen(string.IsNullOrEmpty(clientId), "No client ID is configured.");
Assert.SkipWhen(string.IsNullOrEmpty(clientSecret), "No client secret is configured.");
Assert.SkipWhen(string.IsNullOrEmpty(refreshToken), "No refresh token is configured.");

// See https://developer.amazon.com/docs/login-with-amazon/authorization-code-grant.html#using-refresh-tokens
var parameters = new Dictionary<string, string>()
Expand Down
22 changes: 15 additions & 7 deletions test/LondonTravel.Skill.Tests/CommuteTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,9 @@ public async Task Can_Invoke_Function_When_The_Skill_Is_Not_Linked()
public async Task Can_Invoke_Function_When_The_Skill_Token_Is_Invalid()
{
// Arrange
await Interceptor.RegisterBundleFromResourceStreamAsync<CommuteTests>("skill-api-invalid-token.json");
await Interceptor.RegisterBundleFromResourceStreamAsync<CommuteTests>(
"skill-api-invalid-token.json",
cancellationToken: TestContext.Current.CancellationToken);

var function = await CreateFunctionAsync();
var request = CreateIntentRequestWithToken(accessToken: "invalid-access-token");
Expand Down Expand Up @@ -84,8 +86,10 @@ public async Task Can_Invoke_Function_When_The_Skill_Api_Fails()
public async Task Can_Invoke_Function_When_The_Skill_Is_Linked_And_Has_No_Favorite_Lines()
{
// Arrange
await Interceptor.RegisterBundleFromResourceStreamAsync<CommuteTests>("skill-api-no-favorites.json");
await Interceptor.RegisterBundleFromResourceStreamAsync<CommuteTests>("tfl-line-statuses.json");
var cancellationToken = TestContext.Current.CancellationToken;

await Interceptor.RegisterBundleFromResourceStreamAsync<CommuteTests>("skill-api-no-favorites.json", cancellationToken: cancellationToken);
await Interceptor.RegisterBundleFromResourceStreamAsync<CommuteTests>("tfl-line-statuses.json", cancellationToken: cancellationToken);

var function = await CreateFunctionAsync();
var request = CreateIntentRequestWithToken(accessToken: "token-for-no-favorites");
Expand All @@ -105,8 +109,10 @@ public async Task Can_Invoke_Function_When_The_Skill_Is_Linked_And_Has_No_Favori
public async Task Can_Invoke_Function_When_The_Skill_Is_Linked_And_Has_One_Favorite_Line()
{
// Arrange
await Interceptor.RegisterBundleFromResourceStreamAsync<CommuteTests>("skill-api-one-favorite.json");
await Interceptor.RegisterBundleFromResourceStreamAsync<CommuteTests>("tfl-line-statuses.json");
var cancellationToken = TestContext.Current.CancellationToken;

await Interceptor.RegisterBundleFromResourceStreamAsync<CommuteTests>("skill-api-one-favorite.json", cancellationToken: cancellationToken);
await Interceptor.RegisterBundleFromResourceStreamAsync<CommuteTests>("tfl-line-statuses.json", cancellationToken: cancellationToken);

var function = await CreateFunctionAsync();
var request = CreateIntentRequestWithToken(accessToken: "token-for-one-favorite");
Expand All @@ -126,8 +132,10 @@ public async Task Can_Invoke_Function_When_The_Skill_Is_Linked_And_Has_One_Favor
public async Task Can_Invoke_Function_When_The_Skill_Is_Linked_And_Has_Two_Favorite_Lines()
{
// Arrange
await Interceptor.RegisterBundleFromResourceStreamAsync<CommuteTests>("skill-api-two-favorites.json");
await Interceptor.RegisterBundleFromResourceStreamAsync<CommuteTests>("tfl-line-statuses.json");
var cancellationToken = TestContext.Current.CancellationToken;

await Interceptor.RegisterBundleFromResourceStreamAsync<CommuteTests>("skill-api-two-favorites.json", cancellationToken: cancellationToken);
await Interceptor.RegisterBundleFromResourceStreamAsync<CommuteTests>("tfl-line-statuses.json", cancellationToken: cancellationToken);

var function = await CreateFunctionAsync();
var request = CreateIntentRequestWithToken(accessToken: "token-for-two-favorites");
Expand Down
12 changes: 9 additions & 3 deletions test/LondonTravel.Skill.Tests/DisruptionTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@ public class DisruptionTests(ITestOutputHelper outputHelper) : FunctionTests(out
public async Task Can_Invoke_Function_When_There_Are_No_Disruptions()
{
// Arrange
await Interceptor.RegisterBundleFromResourceStreamAsync<DisruptionTests>("tfl-no-disruptions.json");
await Interceptor.RegisterBundleFromResourceStreamAsync<DisruptionTests>(
"tfl-no-disruptions.json",
cancellationToken: TestContext.Current.CancellationToken);

var function = await CreateFunctionAsync();
var request = CreateIntentRequest();
Expand All @@ -32,7 +34,9 @@ public async Task Can_Invoke_Function_When_There_Are_No_Disruptions()
public async Task Can_Invoke_Function_When_There_Is_One_Disruption()
{
// Arrange
await Interceptor.RegisterBundleFromResourceStreamAsync<DisruptionTests>("tfl-one-disruption.json");
await Interceptor.RegisterBundleFromResourceStreamAsync<DisruptionTests>(
"tfl-one-disruption.json",
cancellationToken: TestContext.Current.CancellationToken);

var function = await CreateFunctionAsync();
var request = CreateIntentRequest();
Expand All @@ -52,7 +56,9 @@ public async Task Can_Invoke_Function_When_There_Is_One_Disruption()
public async Task Can_Invoke_Function_When_There_Are_Multiple_Disruptions()
{
// Arrange
await Interceptor.RegisterBundleFromResourceStreamAsync<DisruptionTests>("tfl-multiple-disruptions.json");
await Interceptor.RegisterBundleFromResourceStreamAsync<DisruptionTests>(
"tfl-multiple-disruptions.json",
cancellationToken: TestContext.Current.CancellationToken);

var function = await CreateFunctionAsync();
var request = CreateIntentRequest();
Expand Down
16 changes: 8 additions & 8 deletions test/LondonTravel.Skill.Tests/EndToEndTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ public class EndToEndTests(ITestOutputHelper outputHelper) : FunctionTests(outpu
{
private const int TimeoutMilliseconds = 15_000;

[xRetry.RetryTheory(Timeout = TimeoutMilliseconds)]
[Theory(Timeout = TimeoutMilliseconds)]
[InlineData("AMAZON.CancelIntent")]
[InlineData("AMAZON.StopIntent")]
public async Task Alexa_Function_Can_Process_Intent_Request(string name)
Expand All @@ -34,7 +34,7 @@ public async Task Alexa_Function_Can_Process_Intent_Request(string name)
response.Reprompt.ShouldBeNull();
}

[xRetry.RetryFact(Timeout = TimeoutMilliseconds)]
[Fact(Timeout = TimeoutMilliseconds)]
public async Task Alexa_Function_Can_Process_Intent_Request_For_Help()
{
// Arrange
Expand All @@ -54,7 +54,7 @@ public async Task Alexa_Function_Can_Process_Intent_Request_For_Help()
response.OutputSpeech.Ssml.ShouldBe("<speak><p>This skill allows you to check for the status of a specific line, or for disruption in general. You can ask about any London Underground line, London Overground, the Docklands Light Railway or the Elizabeth line.</p><p>Asking about disruption in general provides information about any lines that are currently experiencing issues, such as any delays or planned closures.</p><p>Asking for the status for a specific line provides a summary of the current service, such as whether there is a good service or if there are any delays.</p><p>If you link your account and setup your preferences in the London Travel website, you can ask about your commute to quickly find out the status of the lines you frequently use.</p><p>What would you like to do?</p></speak>");
}

[xRetry.RetryFact(Timeout = TimeoutMilliseconds)]
[Fact(Timeout = TimeoutMilliseconds)]
public async Task Alexa_Function_Can_Process_Intent_Request_With_Unknown_Intent()
{
// Arrange
Expand All @@ -74,7 +74,7 @@ public async Task Alexa_Function_Can_Process_Intent_Request_With_Unknown_Intent(
response.OutputSpeech.Ssml.ShouldBe("<speak>Sorry, I don't understand how to do that.</speak>");
}

[xRetry.RetryFact(Timeout = TimeoutMilliseconds)]
[Fact(Timeout = TimeoutMilliseconds)]
public async Task Alexa_Function_Can_Process_Intent_Request_For_Disruption()
{
// Arrange
Expand All @@ -95,7 +95,7 @@ public async Task Alexa_Function_Can_Process_Intent_Request_For_Disruption()
response.OutputSpeech.Ssml.ShouldBe("<speak>There is currently no disruption on the tube, London Overground, the D.L.R. or the Elizabeth line.</speak>");
}

[xRetry.RetryTheory(Timeout = TimeoutMilliseconds)]
[Theory(Timeout = TimeoutMilliseconds)]
[InlineData("Northern", "There is a good service on the Northern line.")]
[InlineData("Windrush", "There is a good service on the Windrush line.")]
public async Task Alexa_Function_Can_Process_Intent_Request_For_Line_Status(
Expand All @@ -122,7 +122,7 @@ public async Task Alexa_Function_Can_Process_Intent_Request_For_Line_Status(
response.OutputSpeech.Ssml.ShouldBe($"<speak>{expected}</speak>");
}

[xRetry.RetryFact(Timeout = TimeoutMilliseconds)]
[Fact(Timeout = TimeoutMilliseconds)]
public async Task Alexa_Function_Can_Process_Launch_Request()
{
// Arrange
Expand All @@ -142,7 +142,7 @@ public async Task Alexa_Function_Can_Process_Launch_Request()
response.OutputSpeech.Ssml.ShouldBe("<speak>Welcome to London Travel. You can ask me about disruption or for the status of any tube line, London Overground, the D.L.R. or the Elizabeth line.</speak>");
}

[xRetry.RetryFact(Timeout = TimeoutMilliseconds)]
[Fact(Timeout = TimeoutMilliseconds)]
public async Task Alexa_Function_Can_Process_Session_Ended_Request()
{
// Arrange
Expand Down Expand Up @@ -172,7 +172,7 @@ public async Task Alexa_Function_Can_Process_Session_Ended_Request()
response.OutputSpeech.Ssml.ShouldBe("<speak>Goodbye.</speak>");
}

[xRetry.RetryFact(Timeout = TimeoutMilliseconds)]
[Fact(Timeout = TimeoutMilliseconds)]
public async Task Alexa_Function_Can_Process_System_Exception_Request()
{
// Arrange
Expand Down
2 changes: 1 addition & 1 deletion test/LondonTravel.Skill.Tests/InteractionModelTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public static async Task Interaction_Model_Is_Valid_Json()
using var model = assembly.GetManifestResourceStream(type.Namespace + ".interaction-model.json")!;
using var stream = new MemoryStream();

await model.CopyToAsync(stream);
await model.CopyToAsync(stream, TestContext.Current.CancellationToken);
model.Seek(0, SeekOrigin.Begin);

var reader = new Utf8JsonReader(stream.ToArray());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
<IsTestProject>true</IsTestProject>
<JsonSerializerIsReflectionEnabledByDefault>false</JsonSerializerIsReflectionEnabledByDefault>
<NoWarn>$(NoWarn);CA1062;CA1707;CA2007;CA2234;SA1600</NoWarn>
<OutputType>Exe</OutputType>
<RootNamespace>MartinCostello.LondonTravel.Skill</RootNamespace>
<TargetFramework>net9.0</TargetFramework>
</PropertyGroup>
Expand All @@ -15,14 +16,13 @@
<PackageReference Include="coverlet.msbuild" />
<PackageReference Include="GitHubActionsTestLogger" NoWarn="RT0003" />
<PackageReference Include="JustEat.HttpClientInterception" />
<PackageReference Include="MartinCostello.Logging.XUnit" />
<PackageReference Include="MartinCostello.Logging.XUnit.v3" />
<PackageReference Include="MartinCostello.Testing.AwsLambdaTestServer" />
<PackageReference Include="Microsoft.NET.Test.Sdk" />
<PackageReference Include="ReportGenerator" />
<PackageReference Include="Shouldly" />
<PackageReference Include="xRetry" />
<PackageReference Include="xunit" />
<PackageReference Include="xunit.runner.visualstudio" />
<PackageReference Include="xunit.v3" />
</ItemGroup>
<ItemGroup>
<Content Include="testsettings.json;xunit.runner.json;Samples\*.json" CopyToOutputDirectory="PreserveNewest" />
Expand All @@ -31,7 +31,6 @@
<ItemGroup>
<Using Include="Shouldly" />
<Using Include="Xunit" />
<Using Include="Xunit.Abstractions" />
</ItemGroup>
<PropertyGroup>
<CollectCoverage>true</CollectCoverage>
Expand Down
Loading
Loading