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

Add general testing framework that can be used by projects #428

Merged
merged 3 commits into from
Dec 19, 2023
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
23 changes: 15 additions & 8 deletions GenHTTP.sln
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GenHTTP.Modules.Scriban", "
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Testing", "Testing", "{A7930BE4-0549-4197-B139-B1A73E74B464}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GenHTTP.Testing.Acceptance", "Testing\GenHTTP.Testing.Acceptance.csproj", "{3B00D7C4-B8E9-4163-9E4C-67044BB26B34}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GenHTTP.Modules.Webservices", "Modules\Webservices\GenHTTP.Modules.Webservices.csproj", "{3096F48C-60D7-4471-A7E4-315B6227C351}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GenHTTP.Modules.Razor", "Modules\Razor\GenHTTP.Modules.Razor.csproj", "{9022F8C2-B465-40FD-BC59-428C034C4470}"
Expand Down Expand Up @@ -102,6 +100,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GenHTTP.Modules.Functional"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GenHTTP.Modules.Protobuf", "Modules\Protobuf\GenHTTP.Modules.Protobuf.csproj", "{0D9957DE-8FE2-44A1-B9D7-EADD1DBDBD6E}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GenHTTP.Testing.Acceptance", "Testing\Acceptance\GenHTTP.Testing.Acceptance.csproj", "{C5067243-AFBA-4A17-BD61-DDB503367EA3}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GenHTTP.Testing", "Testing\Testing\GenHTTP.Testing.csproj", "{FC7F7D69-5ED0-4D3B-B201-EDBCEC71B8DB}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand All @@ -120,10 +122,6 @@ Global
{7FA5BD2F-C093-4F30-ACD9-A870C7A0DAF2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7FA5BD2F-C093-4F30-ACD9-A870C7A0DAF2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7FA5BD2F-C093-4F30-ACD9-A870C7A0DAF2}.Release|Any CPU.Build.0 = Release|Any CPU
{3B00D7C4-B8E9-4163-9E4C-67044BB26B34}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3B00D7C4-B8E9-4163-9E4C-67044BB26B34}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3B00D7C4-B8E9-4163-9E4C-67044BB26B34}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3B00D7C4-B8E9-4163-9E4C-67044BB26B34}.Release|Any CPU.Build.0 = Release|Any CPU
{3096F48C-60D7-4471-A7E4-315B6227C351}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3096F48C-60D7-4471-A7E4-315B6227C351}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3096F48C-60D7-4471-A7E4-315B6227C351}.Release|Any CPU.ActiveCfg = Release|Any CPU
Expand Down Expand Up @@ -252,6 +250,14 @@ Global
{0D9957DE-8FE2-44A1-B9D7-EADD1DBDBD6E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0D9957DE-8FE2-44A1-B9D7-EADD1DBDBD6E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0D9957DE-8FE2-44A1-B9D7-EADD1DBDBD6E}.Release|Any CPU.Build.0 = Release|Any CPU
{C5067243-AFBA-4A17-BD61-DDB503367EA3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C5067243-AFBA-4A17-BD61-DDB503367EA3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C5067243-AFBA-4A17-BD61-DDB503367EA3}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C5067243-AFBA-4A17-BD61-DDB503367EA3}.Release|Any CPU.Build.0 = Release|Any CPU
{FC7F7D69-5ED0-4D3B-B201-EDBCEC71B8DB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{FC7F7D69-5ED0-4D3B-B201-EDBCEC71B8DB}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FC7F7D69-5ED0-4D3B-B201-EDBCEC71B8DB}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FC7F7D69-5ED0-4D3B-B201-EDBCEC71B8DB}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand All @@ -260,7 +266,6 @@ Global
{59E1C489-E9E9-4374-8CB9-A2005722152D} = {AFBFE61E-0C33-42F6-9370-9F5088EB8633}
{C2D2B8D0-CA23-4790-8C71-B245A0AB81FB} = {06A861A6-D030-4129-9F8F-4EED698D00A6}
{7FA5BD2F-C093-4F30-ACD9-A870C7A0DAF2} = {23B23225-275E-4F52-8B29-6F44C85B6ACE}
{3B00D7C4-B8E9-4163-9E4C-67044BB26B34} = {A7930BE4-0549-4197-B139-B1A73E74B464}
{3096F48C-60D7-4471-A7E4-315B6227C351} = {23B23225-275E-4F52-8B29-6F44C85B6ACE}
{9022F8C2-B465-40FD-BC59-428C034C4470} = {23B23225-275E-4F52-8B29-6F44C85B6ACE}
{9BB6732E-BFE1-4ABE-B8A6-4522DF72EDDD} = {23B23225-275E-4F52-8B29-6F44C85B6ACE}
Expand Down Expand Up @@ -295,9 +300,11 @@ Global
{69D6CA16-1332-41B6-8994-6AD943915F25} = {23B23225-275E-4F52-8B29-6F44C85B6ACE}
{2A2BCF94-BBDF-49A7-8B87-931E665507F0} = {23B23225-275E-4F52-8B29-6F44C85B6ACE}
{0D9957DE-8FE2-44A1-B9D7-EADD1DBDBD6E} = {23B23225-275E-4F52-8B29-6F44C85B6ACE}
{C5067243-AFBA-4A17-BD61-DDB503367EA3} = {A7930BE4-0549-4197-B139-B1A73E74B464}
{FC7F7D69-5ED0-4D3B-B201-EDBCEC71B8DB} = {A7930BE4-0549-4197-B139-B1A73E74B464}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
LessCompiler = 2603124e-1287-4d61-9540-6ac3efad4eb9
SolutionGuid = {9C67B3AF-0BF6-4E21-8C39-3F74CFCF9632}
LessCompiler = 2603124e-1287-4d61-9540-6ac3efad4eb9
EndGlobalSection
EndGlobal
160 changes: 80 additions & 80 deletions Testing/AssertX.cs → Testing/Acceptance/AssertX.cs
Original file line number Diff line number Diff line change
@@ -1,80 +1,80 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace GenHTTP.Testing.Acceptance
{
/// <summary>
/// Compatibility assertions for XUnit.
/// </summary>
public static class AssertX
{
public static void Contains(string searchFor, string? content) => Assert.IsTrue(content?.Contains(searchFor) ?? false);
public static void DoesNotContain(string searchFor, string? content) => Assert.IsFalse(content?.Contains(searchFor) ?? false);
public static void StartsWith(string searchFor, string? content) => Assert.IsTrue(content?.StartsWith(searchFor) ?? false);
public static void EndsWith(string searchFor, string? content) => Assert.IsTrue(content?.EndsWith(searchFor) ?? false);
public static void Single<T>(IEnumerable<T> collection) => Assert.IsTrue(collection.Count() == 1);
public static void Empty<T>(IEnumerable<T> collection) => Assert.IsFalse(collection.Any());
public static void Contains<T>(T value, IEnumerable<T> collection) => Assert.IsTrue(collection.Contains(value));
public static void DoesNotContain<T>(T value, IEnumerable<T> collection) => Assert.IsFalse(collection.Contains(value));
public static void IsNullOrEmpty(string? value) => Assert.IsTrue(string.IsNullOrEmpty(value));
/// <summary>
/// Raises an assertion expection if the response does not have the expected status code
/// and additionally prints information about the response to be able to further debug
/// issues in workflow runs.
/// </summary>
/// <param name="response">The response to be evaluated</param>
/// <param name="expectedStatus">The expected status code to check for</param>
public static async Task AssertStatusAsync(this HttpResponseMessage response, HttpStatusCode expectedStatus)
{
if (response.StatusCode != expectedStatus)
{
var builder = new StringBuilder();
builder.AppendLine($"Response returned with status '{response.StatusCode}', expected '{expectedStatus}'.");
builder.AppendLine();
builder.AppendLine("Headers");
builder.AppendLine();
foreach (var header in response.Headers)
{
builder.AppendLine($" {header.Key} = {string.Join(',', header.Value.ToList())}");
}
builder.AppendLine();
var content = await response.Content.ReadAsStringAsync();
if (!string.IsNullOrEmpty(content))
{
builder.AppendLine("Body");
builder.AppendLine();
builder.AppendLine(content);
}
throw new AssertFailedException(builder.ToString());
}
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;

using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace GenHTTP.Testing.Acceptance
{

/// <summary>
/// Compatibility assertions for XUnit.
/// </summary>
public static class AssertX
{

public static void Contains(string searchFor, string? content) => Assert.IsTrue(content?.Contains(searchFor) ?? false);

public static void DoesNotContain(string searchFor, string? content) => Assert.IsFalse(content?.Contains(searchFor) ?? false);

public static void StartsWith(string searchFor, string? content) => Assert.IsTrue(content?.StartsWith(searchFor) ?? false);

public static void EndsWith(string searchFor, string? content) => Assert.IsTrue(content?.EndsWith(searchFor) ?? false);

public static void Single<T>(IEnumerable<T> collection) => Assert.IsTrue(collection.Count() == 1);

public static void Empty<T>(IEnumerable<T> collection) => Assert.IsFalse(collection.Any());

public static void Contains<T>(T value, IEnumerable<T> collection) => Assert.IsTrue(collection.Contains(value));

public static void DoesNotContain<T>(T value, IEnumerable<T> collection) => Assert.IsFalse(collection.Contains(value));

public static void IsNullOrEmpty(string? value) => Assert.IsTrue(string.IsNullOrEmpty(value));

/// <summary>
/// Raises an assertion expection if the response does not have the expected status code
/// and additionally prints information about the response to be able to further debug
/// issues in workflow runs.
/// </summary>
/// <param name="response">The response to be evaluated</param>
/// <param name="expectedStatus">The expected status code to check for</param>
public static async Task AssertStatusAsync(this HttpResponseMessage response, HttpStatusCode expectedStatus)
{
if (response.StatusCode != expectedStatus)
{
var builder = new StringBuilder();

builder.AppendLine($"Response returned with status '{response.StatusCode}', expected '{expectedStatus}'.");
builder.AppendLine();

builder.AppendLine("Headers");
builder.AppendLine();

foreach (var header in response.Headers)
{
builder.AppendLine($" {header.Key} = {string.Join(',', header.Value.ToList())}");
}

builder.AppendLine();

var content = await response.Content.ReadAsStringAsync();

if (!string.IsNullOrEmpty(content))
{
builder.AppendLine("Body");
builder.AppendLine();

builder.AppendLine(content);
}

throw new AssertFailedException(builder.ToString());
}
}

}

}
Original file line number Diff line number Diff line change
@@ -1,80 +1,82 @@
using System;
using System.Net;
using System.Threading.Tasks;

using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace GenHTTP.Testing.Acceptance.Engine
{

[TestClass]
public sealed class BasicTests
{

[TestMethod]
public async Task TestBuilder()
{
using var runner = new TestRunner();

runner.Host.RequestMemoryLimit(128)
.TransferBufferSize(128)
.RequestReadTimeout(TimeSpan.FromSeconds(2))
.Backlog(1);

runner.Start();

using var response = await runner.GetResponse();

await response.AssertStatusAsync(HttpStatusCode.NotFound);
}

[TestMethod]
public async Task TestLegacyHttp()
{
using var runner = TestRunner.Run();

using var client = TestRunner.GetClient(version: new Version(1, 0));

using var response = await runner.GetResponse();

await response.AssertStatusAsync(HttpStatusCode.NotFound);
}

[TestMethod]
public async Task TestConnectionClose()
{
using var runner = TestRunner.Run();

var request = runner.GetRequest();
request.Headers.Add("Connection", "close");

using var response = await runner.GetResponse(request);

await response.AssertStatusAsync(HttpStatusCode.NotFound);
Assert.IsTrue(response.Headers.Connection.Contains("Close"));
}

[TestMethod]
public async Task TestEmptyQuery()
{
using var runner = TestRunner.Run();

using var response = await runner.GetResponse("/?");

await response.AssertStatusAsync(HttpStatusCode.NotFound);
}


[TestMethod]
public async Task TestKeepalive()
{
using var runner = TestRunner.Run();

using var response = await runner.GetResponse();

Assert.IsTrue(response.Headers.Connection.Contains("Keep-Alive"));
}

}

}
using System;
using System.Net;
using System.Threading.Tasks;

using GenHTTP.Modules.Layouting;

using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace GenHTTP.Testing.Acceptance.Engine
{

[TestClass]
public sealed class BasicTests
{

[TestMethod]
public async Task TestBuilder()
{
using var runner = new TestHost(Layout.Create());

runner.Host.RequestMemoryLimit(128)
.TransferBufferSize(128)
.RequestReadTimeout(TimeSpan.FromSeconds(2))
.Backlog(1);

runner.Start();

using var response = await runner.GetResponseAsync();

await response.AssertStatusAsync(HttpStatusCode.NotFound);
}

[TestMethod]
public async Task TestLegacyHttp()
{
using var runner = TestHost.Run(Layout.Create());

using var client = TestHost.GetClient(protocolVersion: new Version(1, 0));

using var response = await runner.GetResponseAsync();

await response.AssertStatusAsync(HttpStatusCode.NotFound);
}

[TestMethod]
public async Task TestConnectionClose()
{
using var runner = TestHost.Run(Layout.Create());

var request = runner.GetRequest();
request.Headers.Add("Connection", "close");

using var response = await runner.GetResponseAsync(request);

await response.AssertStatusAsync(HttpStatusCode.NotFound);
Assert.IsTrue(response.Headers.Connection.Contains("Close"));
}

[TestMethod]
public async Task TestEmptyQuery()
{
using var runner = TestHost.Run(Layout.Create());

using var response = await runner.GetResponseAsync("/?");

await response.AssertStatusAsync(HttpStatusCode.NotFound);
}


[TestMethod]
public async Task TestKeepalive()
{
using var runner = TestHost.Run(Layout.Create());

using var response = await runner.GetResponseAsync();

Assert.IsTrue(response.Headers.Connection.Contains("Keep-Alive"));
}

}

}
Loading
Loading