The test case gets retried 3 times and the other steps will get skipped

This commit is contained in:
Bart Vermeulen 2022-05-03 19:39:22 +02:00
parent 61146d84b2
commit 3772e89b9c
3 changed files with 75 additions and 32 deletions

View File

@ -10,7 +10,8 @@ import 'package:source_gen/source_gen.dart';
class NoOpReporter extends Reporter {}
class GherkinSuiteTestGenerator extends GeneratorForAnnotation<GherkinTestSuite> {
class GherkinSuiteTestGenerator
extends GeneratorForAnnotation<GherkinTestSuite> {
static const String TEMPLATE = '''
class _CustomGherkinIntegrationTestRunner extends GherkinIntegrationTestRunner {
_CustomGherkinIntegrationTestRunner(
@ -45,14 +46,21 @@ void executeTestSuite(
_languageService.initialise(
annotation.read('featureDefaultLanguage').literalValue.toString(),
);
final idx = annotation.read('executionOrder').objectValue.getField('index')!.toIntValue()!;
final idx = annotation
.read('executionOrder')
.objectValue
.getField('index')!
.toIntValue()!;
final executionOrder = ExecutionOrder.values[idx];
final featureFiles = annotation
.read('featurePaths')
.listValue
.map((path) => Glob(path.toStringValue()!))
.map(
(glob) => glob.listSync().map((entity) => File(entity.path).readAsStringSync()).toList(),
(glob) => glob
.listSync()
.map((entity) => File(entity.path).readAsStringSync())
.toList(),
)
.reduce((value, element) => value..addAll(element));
@ -80,7 +88,10 @@ void executeTestSuite(
}
}
return TEMPLATE.replaceAll('{{feature_functions}}', featureExecutionFunctionsBuilder.toString()).replaceAll(
return TEMPLATE
.replaceAll('{{feature_functions}}',
featureExecutionFunctionsBuilder.toString())
.replaceAll(
'{{features_to_execute}}',
featuresToExecute.toString(),
);
@ -123,20 +134,22 @@ class FeatureFileTestGeneratorVisitor extends FeatureFileVisitor {
runScenario(
'{{scenario_name}}',
{{tags}},
(TestDependencies dependencies) async {
[
{{steps}}
},
],
{{onBefore}}
{{onAfter}}
);
''';
static const String STEP_TEMPLATE = '''
await runStep(
(TestDependencies dependencies, bool hasToSkip) async {
return await runStep(
'{{step_name}}',
{{step_multi_line_strings}},
{{step_table}},
dependencies,
);
hasToSkip
);}
''';
static const String ON_BEFORE_SCENARIO_RUN = '''
onBefore: () async => onBeforeRunFeature('{{feature_name}}', {{feature_tags}},),
@ -151,6 +164,7 @@ class FeatureFileTestGeneratorVisitor extends FeatureFileVisitor {
String? _currentScenarioCode;
final StringBuffer _scenarioBuffer = StringBuffer();
final StringBuffer _stepBuffer = StringBuffer();
final _steps = [];
Future<String> generateTests(
int id,
@ -207,7 +221,6 @@ class FeatureFileTestGeneratorVisitor extends FeatureFileVisitor {
Iterable<String> tags,
bool isFirst,
bool isLast,
String path,
) async {
_flushScenario();
_currentScenarioCode = _replaceVariable(
@ -266,6 +279,7 @@ class FeatureFileTestGeneratorVisitor extends FeatureFileVisitor {
);
_stepBuffer.writeln(code);
_steps.add(code);
}
void _flushFeature() {
@ -285,11 +299,11 @@ class FeatureFileTestGeneratorVisitor extends FeatureFileVisitor {
void _flushScenario() {
if (_currentScenarioCode != null) {
if (_stepBuffer.isNotEmpty) {
if (_steps.isNotEmpty) {
_currentScenarioCode = _replaceVariable(
_currentScenarioCode!,
'steps',
_stepBuffer.toString(),
_steps.join(','),
);
}

View File

@ -39,6 +39,7 @@ class FlutterAppRunnerHook extends Hook {
TestConfiguration config,
String scenario,
Iterable<Tag> tags,
bool failed,
) async {
final flutterConfig = _castConfig(config);
haveRunFirstScenario = true;

View File

@ -1,3 +1,5 @@
import 'dart:math';
import 'package:flutter_gherkin/flutter_gherkin.dart';
import 'package:flutter_gherkin/src/flutter/adapters/widget_tester_app_driver_adapter.dart';
import 'package:flutter_gherkin/src/flutter/world/flutter_world.dart';
@ -135,7 +137,8 @@ abstract class GherkinIntegrationTestRunner {
void runScenario(
String name,
Iterable<String>? tags,
Future<void> Function(TestDependencies dependencies) runTest, {
List<Future<StepResult> Function(TestDependencies dependencies, bool skip)>
steps, {
Future<void> Function()? onBefore,
Future<void> Function()? onAfter,
}) {
@ -146,6 +149,7 @@ abstract class GherkinIntegrationTestRunner {
if (onBefore != null) {
await onBefore();
}
var failed = false;
final debugInformation = RunnableDebugInformation('', 0, name);
final scenarioTags =
@ -181,14 +185,26 @@ abstract class GherkinIntegrationTestRunner {
scenarioTags,
),
);
await runTest(dependencies);
var hasToSkip = false;
for (int i = 0; i < steps.length; i++) {
try {
final result = await steps[i](dependencies, hasToSkip);
if (_isNegativeResult(result.result)) {
failed = true;
hasToSkip = true;
}
} catch (e) {
failed = true;
hasToSkip = true;
// rethrow;
}
}
} finally {
await reporter.onScenarioFinished(
ScenarioFinishedMessage(
name,
debugInformation,
true,
!failed,
),
);
@ -196,6 +212,7 @@ abstract class GherkinIntegrationTestRunner {
configuration,
name,
scenarioTags,
!failed,
);
if (onAfter != null) {
@ -254,12 +271,8 @@ abstract class GherkinIntegrationTestRunner {
}
@protected
Future<StepResult> runStep(
String step,
Iterable<String> multiLineStrings,
dynamic table,
TestDependencies dependencies,
) async {
Future<StepResult> runStep(String step, Iterable<String> multiLineStrings,
dynamic table, TestDependencies dependencies, bool hasToSkip) async {
final executable = _executableSteps!.firstWhereOrNull(
(s) => s.expression.isMatch(step),
);
@ -283,28 +296,43 @@ abstract class GherkinIntegrationTestRunner {
multiLineStrings,
);
final result = await executable.step.run(
dependencies.world,
reporter,
configuration.defaultTimeout,
parameters,
);
StepResult? result;
if (hasToSkip) {
result = new StepResult(
0, StepExecutionResult.skipped, "Previous step(s) failed.");
} else {
for (int i = 0; i < 3; i++) {
result = await executable.step.run(
dependencies.world,
reporter,
configuration.defaultTimeout,
parameters,
);
if (!_isNegativeResult(result.result)) {
break;
}
}
}
await _onAfterStepRun(
step,
result,
result!,
dependencies,
);
if (result.result == StepExecutionResult.fail) {
throw TestFailure('Step: $step \n\n${result.resultReason}');
} else if (result is ErroredStepResult) {
throw result.exception;
if (result is ErroredStepResult) {
// result.resultReason = result.exception.toString();
}
return result;
}
bool _isNegativeResult(StepExecutionResult result) {
return result == StepExecutionResult.error ||
result == StepExecutionResult.fail ||
result == StepExecutionResult.timeout;
}
@protected
void cleanupScenarioRun(TestDependencies dependencies) {
_safeInvokeFuture(