Skip to content
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
2 changes: 2 additions & 0 deletions docs/docs/how-to-write-tests.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ A test is considered **failed** if an exception is thrown within the test body,

> 💁‍♂️ However, the **natively supported assertion library** is `Xunit.Assert`, which is statically imported in all script files. This means you don't need the `Assert.` prefix to access its methods.

> ⚠️ `.csx` scripts **must not contain code that accesses or processes HTTP responses outside of `tp.Test` methods**. Since the script is executed before all HTTP requests, any response‑dependent logic placed outside `tp.Test` methods **may cause errors**.

### Example Test

```csharp
Expand Down
3 changes: 2 additions & 1 deletion docs/docs/test-case/post-response-script.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@

| | |
|----------------------|----------------|
| **Definition** | `.csx` script to be executed after all HTTP requests within test case. |
| **Definition** | `.csx` script containing defined test scenarios. |
| **Naming Convention** | `<test-case-name>-test.csx` |
| **Purpose** | Testing given response(s) and tear-down of data. |
| **Restrictions** | `.csx` scripts must not contain code that accesses or processes HTTP responses outside of `tp.Test` methods. |
| **Example Usage** | [Simple Script](https://github.com/Kros-sk/TeaPie/blob/master/demo/Tests/001-Customers/001-Add-Customer-test.csx), [Manipulation with Body](https://github.com/Kros-sk/TeaPie/blob/master/demo/Tests/002-Cars/001-Add-Car-test.csx), [Another Example](https://github.com/Kros-sk/TeaPie/blob/master/demo/Tests/002-Cars/002-Edit-Car-test.csx), [Advanced Script](https://github.com/Kros-sk/TeaPie/blob/master/demo/Tests/003-Car-Rentals/001-Rent-Car-test.csx) |

## Features
Expand Down
2 changes: 1 addition & 1 deletion src/Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
</PropertyGroup>

<PropertyGroup>
<Version>1.5.1</Version>
<Version>1.5.2</Version>
<Authors>Matej Grochal</Authors>
<Company>KROS a.s.</Company>
<Copyright>Copyright © KROS a.s.</Copyright>
Expand Down
5 changes: 5 additions & 0 deletions src/TeaPie/Reporting/TestResultsSummaryReporter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@ internal class TestResultsSummaryReporter(ITestResultsSummaryAccessor accessor)

public void Initialize()
{
if (_started)
{
return;
}

_summary = GetSummary();
_summary.Start();
_started = true;
Expand Down
2 changes: 1 addition & 1 deletion src/TeaPie/TeaPie.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

<PropertyGroup>
<OutputType>Library</OutputType>
<Version>1.3.0</Version>
<Version>1.5.2</Version>
</PropertyGroup>

<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
Expand Down
9 changes: 8 additions & 1 deletion src/TeaPie/Testing/ExecuteScheduledTestsStep.cs
Original file line number Diff line number Diff line change
@@ -1,15 +1,22 @@
using Microsoft.Extensions.Logging;
using TeaPie.Pipelines;
using TeaPie.Reporting;

namespace TeaPie.Testing;

internal class ExecuteScheduledTestsStep(ITestScheduler scheduler, ITester tester) : IPipelineStep
internal class ExecuteScheduledTestsStep(
ITestScheduler scheduler,
ITester tester,
ITestResultsSummaryReporter resultsSummaryReporter) : IPipelineStep
{
private readonly ITestScheduler _scheduler = scheduler;
private readonly ITester _tester = tester;
private readonly ITestResultsSummaryReporter _resultsSummaryReporter = resultsSummaryReporter;

public async Task Execute(ApplicationContext context, CancellationToken cancellationToken = default)
{
_resultsSummaryReporter.Initialize();

while (_scheduler.HasScheduledTest())
{
var test = _scheduler.Dequeue();
Expand Down
2 changes: 1 addition & 1 deletion src/TeaPie/Testing/Tester.cs
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ private TestResult.Failed CreateFailedResult(Test test, Exception ex, TestCase?
[LoggerMessage(Message = "Skipping test: '{Name}' ({Path})", Level = LogLevel.Information)]
private static partial void LogTestSkip(ILogger logger, string Name, string Path);

[LoggerMessage(Message = "Test '{Name}' ({Path}) was already executed during retry evaluation", Level = LogLevel.Information)]
[LoggerMessage(Message = "Test '{Name}' ({Path}) was already executed during retry evaluation", Level = LogLevel.Debug)]
private static partial void LogTestAlreadyExecuted(ILogger logger, string Name, string Path);

#endregion
Expand Down
2 changes: 1 addition & 1 deletion tests/TeaPie.Tests/ApplicationPipelineShould.cs
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ public async Task ExecuteScheduledTestsBeforeRegisteredTests()
var registeredTest = CreateTest("registered-test", testCase);
testCaseContext.RegisterTest(registeredTest);

var executeScheduledTestsStep = new ExecuteScheduledTestsStep(scheduler, tester);
var executeScheduledTestsStep = new ExecuteScheduledTestsStep(scheduler, tester, reporter);
var runScriptTestsStep = new RunScriptTestsStep(accessor, reporter, tester);

pipeline.AddSteps(executeScheduledTestsStep);
Expand Down
29 changes: 23 additions & 6 deletions tests/TeaPie.Tests/Reporting/TestsResultsSummaryReporterShould.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ namespace TeaPie.Tests.Reporting;
public partial class TestResultsSummaryReporterShould
{
[Fact]
public void NotTriggerReportMethodOnUnregisteredReporter()
public async Task NotTriggerReportMethodOnUnregisteredReporter()
{
var accessor = new TestResultsSummaryAccessor() { Summary = new() };
var compositeReporter = new TestResultsSummaryReporter(accessor);
Expand All @@ -21,14 +21,14 @@ public void NotTriggerReportMethodOnUnregisteredReporter()

compositeReporter.UnregisterReporter(reporter2);

compositeReporter.Report();
await compositeReporter.Report();

reporter1.Received(1).Report(Arg.Any<TestResultsSummary>());
await reporter1.Received(1).Report(Arg.Any<TestResultsSummary>());
False(reporter2.Reported);
}

[Fact]
public void TriggerReportMethodOnAllRegisteredReporters()
public async Task TriggerReportMethodOnAllRegisteredReporters()
{
var accessor = new TestResultsSummaryAccessor() { Summary = new() };
var compositeReporter = new TestResultsSummaryReporter(accessor);
Expand All @@ -38,9 +38,9 @@ public void TriggerReportMethodOnAllRegisteredReporters()
compositeReporter.RegisterReporter(reporter1);
compositeReporter.RegisterReporter(reporter2);

compositeReporter.Report();
await compositeReporter.Report();

reporter1.Received(1).Report(Arg.Any<TestResultsSummary>());
await reporter1.Received(1).Report(Arg.Any<TestResultsSummary>());
True(reporter2.Reported);
}

Expand All @@ -61,6 +61,23 @@ public void ChangeTheStateOfSummaryWhenRegisteringTestResults()
CheckSummary(skippedTestResult, failedTestResult, accessor.Summary);
}

[Fact]
public void ThrowWhenStartIsCalledTwiceOnSummary()
{
var summary = new CollectionTestResultsSummary();
var accessor = new TestResultsSummaryAccessor() { Summary = summary };
var reporter = new TestResultsSummaryReporter(accessor);

reporter.Initialize();
var originalTimestamp = summary.Timestamp;

Thread.Sleep(15);

reporter.Initialize();

Equal(originalTimestamp, summary.Timestamp);
}

private static void CheckSummary(
TestResult.NotRun skippedTestResult,
TestResult.Failed failedTestResult,
Expand Down
73 changes: 73 additions & 0 deletions tests/TeaPie.Tests/Testing/ExecuteScheduledTestsStepShould.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
using NSubstitute;
using TeaPie.Reporting;
using TeaPie.StructureExploration;
using TeaPie.Testing;
using static Xunit.Assert;

namespace TeaPie.Tests.Testing;

public class ExecuteScheduledTestsStepShould
{
[Fact]
public async Task InitializeReporterBeforeExecutingTests()
{
var scheduler = new TestScheduler();
var tester = Substitute.For<ITester>();
var reporter = Substitute.For<ITestResultsSummaryReporter>();

var testCase = new TestCase(new InternalFile("test.http", "test.http", null!));
var test = new Test(
"test-name",
false,
async () => await Task.CompletedTask,
new TestResult.NotRun() { TestName = "test-name" },
testCase);

scheduler.Schedule(test);

var step = new ExecuteScheduledTestsStep(scheduler, tester, reporter);
var context = new ApplicationContextBuilder()
.WithPath(string.Empty)
.Build();

await step.Execute(context);

reporter.Received(1).Initialize();
}

[Fact]
public async Task ExecuteAllScheduledTests()
{
var scheduler = new TestScheduler();
var tester = Substitute.For<ITester>();
var reporter = Substitute.For<ITestResultsSummaryReporter>();

var testCase = new TestCase(new InternalFile("test.http", "test.http", null!));
var test1 = CreateTest("test-1", testCase);
var test2 = CreateTest("test-2", testCase);
var test3 = CreateTest("test-3", testCase);

scheduler.Schedule(test1);
scheduler.Schedule(test2);
scheduler.Schedule(test3);

var step = new ExecuteScheduledTestsStep(scheduler, tester, reporter);
var context = new ApplicationContextBuilder()
.WithPath(string.Empty)
.Build();

await step.Execute(context);

await tester.Received(1).ExecuteOrSkipTest(test1, test1.TestCase);
await tester.Received(1).ExecuteOrSkipTest(test2, test2.TestCase);
await tester.Received(1).ExecuteOrSkipTest(test3, test3.TestCase);

False(scheduler.HasScheduledTest());
}

private static Test CreateTest(string name, TestCase testCase)
{
var result = new TestResult.NotRun { TestName = name, TestCasePath = "test.http" };
return new Test(name, false, () => Task.CompletedTask, result, testCase);
}
}