Automated tests
With Pororoca, you can make automated tests with .NET testing tools, such as xUnit. These tests can be executed in a pipeline or via command line, sending requests to a server.
To create and run these tests, you need to have .NET SDK in your computer.
Creating the test project
Create a test project through Visual Studio or via command line. For this latter option, type the following command on your console:
mkdir MyPororocaTest
cd ./MyPororocaTest/
dotnet new xunit
# other testing libraries can be used
After that, in the created test project, the .csproj file must be edited to include the Pororoca.Test NuGet package.
Be aware that if you will run your unit tests on a Linux machine and those tests include HTTP/3, msquic needs to be installed. Check the Download page for the appropriate version.
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<!-- Pororoca.Test v3 uses .net8.0 -->
<TargetFramework>net8.0</TargetFramework>
<!-- line below is required -->
<EnablePreviewFeatures>True</EnablePreviewFeatures>
…
</PropertyGroup>
<ItemGroup>
<!-- The line below adds Pororoca.Test package to the project -->
<PackageReference Include="Pororoca.Test" Version="3.7.0" />
…
</ItemGroup>
</Project>
Making your first test
The code below shows how to use the Pororoca.Test
in a xUnit test. First, it loads a Pororoca collection from a file. Then, defines the environment that will be used.
using Xunit;
using System.Net;
using Pororoca.Test;
namespace Pororoca.Test.Tests;
public class MyPororocaTest
{
private readonly PororocaTest pororocaTest;
public MyPororocaTest()
{
string filePath = @"C:\Tests\MyCollection.pororoca_collection.json";
pororocaTest = PororocaTest.LoadCollectionFromFile(filePath)
.AndUseTheEnvironment("Local");
}
[Fact]
public async Task Should_get_JSON_successfully()
{
var res = await pororocaTest.SendRequestAsync("Get JSON");
Assert.NotNull(res);
Assert.Equal(HttpStatusCode.OK, res.StatusCode);
Assert.Equal("application/json; charset=utf-8", res.ContentType);
Assert.Contains("\"id\": 1", res.GetBodyAsText());
}
}
There are methods in the PororocaTest class to set values of variables during the tests executions. They can be used to set an authentication token, for example:
pororocaTest.SetCollectionVariable("MyAuthenticationToken", "token_auth");
The test project Pororoca.Test.Tests can guide you - it shows how to use the Pororoca.Test
package, how to load the collection file and how to set variables.
WebSocket tests
INFO
Starting at version 3.7.0, Pororoca.Test uses a Channel<T> to collect the messages sent and received through the WebSocket. In prior versions, an ObservableCollection<T> was used, on property ws.ExchangedMessages
.
You can also make Pororoca tests for WebSockets. The code below shows an example:
using System.Net.WebSockets;
using Pororoca.Infrastructure.Features.WebSockets;
[Fact]
public async Task WebSocket_conversation_should_be_successful()
{
// connecting
var ws = await this.pororocaTest.ConnectWebSocketAsync("My WebSocket");
Assert.Equal(WebSocketConnectorState.Connected, ws.State);
// sending 1st msg
// must be before the foreach if the client initiates the conversation
await ws.SendMessageAsync("Hello");
// conversation and assertions
int msgCount = 0;
await foreach (var msg in ws.ExchangedMessagesCollector!.ReadAllAsync())
{
msgCount++; // counter
if (msgCount == 1)
{
Assert.Equal(WebSocketMessageDirection.FromClient, msg.Direction);
Assert.Equal(WebSocketMessageType.Text, msg.Type);
Assert.Equal("Hello, how are you?", msg.ReadAsUtf8Text());
}
else if (msgCount == 2)
{
Assert.Equal(WebSocketMessageDirection.FromServer, msg.Direction);
Assert.Equal(WebSocketMessageType.Text, msg.Type);
Assert.Equal("Hi, I'm fine, and you?", msg.ReadAsUtf8Text());
await ws.SendMessageAsync("SeeYa"); // sending 3rd msg
}
else if (msgCount == 3)
{
Assert.Equal(WebSocketMessageDirection.FromClient, msg.Direction);
Assert.Equal(WebSocketMessageType.Close, msg.Type);
Assert.Equal("I'm great. See ya!", msg.ReadAsUtf8Text());
}
}
// connection closure assertions
Assert.Equal(WebSocketConnectorState.Disconnected, ws.State);
}
The WebSocket closure can be initiated by a closing message, either from the client or the server, or by disconnection, with the method await ws.DisconnectAsync()
. The closure will make the execution leave the await foreach
loop.
Repeaters tests
Below is an example of a repeater test. The channelReader
is an object for receiving the results of the repetitions, that run in background threads. The await foreach
line is required to wait until all requests are finished.
[Fact]
public async Task Should_run_repetition_successfully()
{
var channelReader = await this.pororocaTest.StartHttpRepetitionAsync("My repetition");
Stopwatch sw = new();
sw.Start();
await foreach (var result in channelReader.ReadAllAsync())
{
// assertions here
}
sw.Stop();
// sw.Elapsed --> total execution time
}
It is your decision how to inspect the results.
If you want to run and generate a report at the end:
using Pororoca.Domain.Feature.Entities.Pororoca.Repetition;
using static Pororoca.Domain.Features.RequestRepeater.HttpRepetitionReporter;
...
[Fact]
public async Task Should_run_repetition_successfully_and_generate_report()
{
var channelReader = await this.pororocaTest.StartHttpRepetitionAsync("My repetition");
List<PororocaHttpRepetitionResult> results = new();
await foreach (var result in channelReader.ReadAllAsync())
{
results.Add(result);
}
string reportFilePath = "C:\\Tests\\report.csv";
await WriteReportAsync(results, reportFilePath);
}
Running the tests
You can run the tests on Visual Studio or executing dotnet test
through the command line.
Why automated tests outside the GUI?
Other HTTP inspection tools, like Postman and SoapUI, have their testing areas inside the GUI. In Pororoca, the choice was to have tests done outside the GUI, for the following reasons:
Automated tests often require a setup, like running scripts in a database to pre-add or pre-remove data, or pulling information from an external data source, to compare with responses from the APIs. Testing in a GUI does not allow to easily do that, whereas testing in an isolated program does.
You can freely choose your assertion and testing frameworks, such as xUnit and FluentAssertions.
By having the tests in a dotnet project, they are already prepared to be run in a CI, only requiring a
dotnet test
step to execute them.