Skip to content

Commit ca6ca5f

Browse files
authored
Merge pull request #80 from pavolbetak/master
Fix execution order of scheduled tests
2 parents fc14936 + 18bfe1c commit ca6ca5f

7 files changed

Lines changed: 93 additions & 5 deletions

File tree

demo/.teapie/init.csx

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,27 @@ tp.RegisterTestDirective(
125125
}
126126
);
127127

128+
tp.RegisterTestDirective(
129+
"JSON-HAS-ID-PROPERTY",
130+
TestDirectivePatternBuilder
131+
.Create("JSON-HAS-ID-PROPERTY")
132+
.AddStringParameter("VariableName")
133+
.Build(),
134+
(_) => $"Response should be valid JSON with ID property.",
135+
async (response, parameters) =>
136+
{
137+
try
138+
{
139+
dynamic body = await tp.Response.GetBodyAsExpandoAsync();
140+
tp.SetVariable(parameters["VariableName"], body.Id);
141+
}
142+
catch (Exception ex)
143+
{
144+
Fail($"Response should be valid JSON with ID property. {ex.Message}");
145+
}
146+
}
147+
);
148+
128149
// CUSTOM CLASS DEFINITIONS
129150

130151
// Custom authentication provider definition

demo/Tests/002-Cars/001-Add-Car-req.http

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ Content-Type: application/json
1111
// Separate multiple requests in a single .http file with a line containing '3 hashtags' separator:
1212

1313
# @name GetNewCarRequest
14+
## TEST-JSON-HAS-ID-PROPERTY: IdFromDirective
1415
// Access the body and headers of a named request/response using this syntax.
1516
// For JSON bodies, use JPath to retrieve properties. For XML, use XPath.
1617
GET {{ApiBaseUrl}}{{ApiCarsSection}}/{{AddCarRequest.request.body.$.Id}}

demo/Tests/002-Cars/001-Add-Car-test.csx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,9 @@ await tp.Test("Identifiers of added and retrieved cars should match.", async ()
2525
dynamic requestJson = await tp.Requests["AddCarRequest"].GetBodyAsExpandoAsync();
2626
dynamic responseJson = await tp.Responses["GetNewCarRequest"].GetBodyAsExpandoAsync();
2727

28+
var idFromDirective = tp.GetVariable<long>("IdFromDirective");
2829
Equal(requestJson.Id, responseJson.Id);
30+
Equal(requestJson.Id, idFromDirective);
2931

3032
// Each variable can have none or multiple tags ('cars', 'ids' in this case).
3133
tp.SetVariable("NewCarId", requestJson.Id, "cars", "ids");

docs/docs/directives.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,15 @@ If no retry strategy is explicitly selected, the **default strategy from `Polly.
9494
| **Purpose** | Sets the maximum allowed delay between retries. |
9595
| **Parameters** | `hh:mm:ss.fff` – The maximum delay time before retrying a failed request. |
9696

97+
#### `## RETRY-UNTIL-TEST-PASS` Directive
98+
99+
| | |
100+
|----------------------|----------------|
101+
| **Syntax** | `## RETRY-UNTIL-TEST-PASS: <test-name>` |
102+
| **Example Usage** | `## RETRY-UNTIL-TEST-PASS: Identifier should be a positive integer` |
103+
| **Purpose** | Retries the request until the defined test passes. |
104+
| **Parameters** | `test-name` – The name of test defined in post-response .csx script. (tp.Test(`test-name`, () => )) |
105+
97106
### Testing Directives
98107

99108
#### `## TEST-EXPECT-STATUS` Directive

src/Directory.Build.props

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
</PropertyGroup>
1818

1919
<PropertyGroup>
20-
<Version>1.5.0</Version>
20+
<Version>1.5.1</Version>
2121
<Authors>Matej Grochal</Authors>
2222
<Company>KROS a.s.</Company>
2323
<Copyright>Copyright © KROS a.s.</Copyright>

src/TeaPie/Testing/ExecuteScheduledTestsStep.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,17 @@
33

44
namespace TeaPie.Testing;
55

6-
internal class ExecuteScheduledTestsStep(ITestScheduler scheduler, IRegistrator tester) : IPipelineStep
6+
internal class ExecuteScheduledTestsStep(ITestScheduler scheduler, ITester tester) : IPipelineStep
77
{
88
private readonly ITestScheduler _scheduler = scheduler;
9-
private readonly IRegistrator _tester = tester;
9+
private readonly ITester _tester = tester;
1010

1111
public async Task Execute(ApplicationContext context, CancellationToken cancellationToken = default)
1212
{
1313
while (_scheduler.HasScheduledTest())
1414
{
1515
var test = _scheduler.Dequeue();
16-
await _tester.Test(test.Name, test.Function);
16+
await _tester.ExecuteOrSkipTest(test, test.TestCase);
1717

1818
context.Logger.LogDebug("Scheduled test with name '{TestName}' was executed.", test.Name);
1919
}

tests/TeaPie.Tests/ApplicationPipelineShould.cs

Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
1-
using NSubstitute;
1+
using FluentAssertions;
2+
using NSubstitute;
23
using TeaPie.Pipelines;
4+
using TeaPie.Reporting;
5+
using TeaPie.Scripts;
6+
using TeaPie.StructureExploration;
7+
using TeaPie.TestCases;
8+
using TeaPie.Testing;
39
using TeaPie.Tests.Pipelines;
410

511
namespace TeaPie.Tests;
@@ -96,6 +102,55 @@ public async Task EnableAddingStepsDuringPipelineRun()
96102
await pipeline.Run(context);
97103
}
98104

105+
[Fact]
106+
public async Task ExecuteScheduledTestsBeforeRegisteredTests()
107+
{
108+
var pipeline = new ApplicationPipeline();
109+
var executionOrder = new List<string>();
110+
111+
var testCase = new TestCase(new InternalFile("test.http", "test.http", null!));
112+
var testCaseContext = new TestCaseExecutionContext(testCase);
113+
114+
var accessor = Substitute.For<ITestCaseExecutionContextAccessor>();
115+
accessor.Context.Returns(testCaseContext);
116+
117+
var reporter = Substitute.For<ITestResultsSummaryReporter>();
118+
119+
var tester = Substitute.For<ITester>();
120+
tester.ExecuteOrSkipTest(Arg.Any<Test>(), Arg.Any<TestCase?>())
121+
.Returns(callInfo =>
122+
{
123+
var test = callInfo.Arg<Test>();
124+
executionOrder.Add(test.Name);
125+
return Task.FromResult(test);
126+
});
127+
128+
var scheduler = new TestScheduler();
129+
var scheduledTest = CreateTest("scheduled-test", testCase);
130+
scheduler.Schedule(scheduledTest);
131+
132+
var registeredTest = CreateTest("registered-test", testCase);
133+
testCaseContext.RegisterTest(registeredTest);
134+
135+
var executeScheduledTestsStep = new ExecuteScheduledTestsStep(scheduler, tester);
136+
var runScriptTestsStep = new RunScriptTestsStep(accessor, reporter, tester);
137+
138+
pipeline.AddSteps(executeScheduledTestsStep);
139+
pipeline.AddSteps(runScriptTestsStep);
140+
141+
await pipeline.Run(CreateApplicationContext(string.Empty));
142+
143+
executionOrder.Should().HaveCount(2);
144+
executionOrder[0].Should().Be("scheduled-test");
145+
executionOrder[1].Should().Be("registered-test");
146+
}
147+
148+
private static Test CreateTest(string name, TestCase testCase)
149+
{
150+
var result = new TestResult.NotRun { TestName = name, TestCasePath = "test.http" };
151+
return new Test(name, false, () => Task.CompletedTask, result, testCase);
152+
}
153+
99154
private static ApplicationContext CreateApplicationContext(string path)
100155
=> new ApplicationContextBuilder()
101156
.WithPath(path)

0 commit comments

Comments
 (0)