Skip to content

Commit

Permalink
implement PatrolAppService.addSetUpAll and remembering setUpAlls
Browse files Browse the repository at this point in the history
Problem: not all tests are "falling through" during the initial run
  • Loading branch information
bartekpacia committed Oct 10, 2023
1 parent 7ed9235 commit 56dca3b
Show file tree
Hide file tree
Showing 5 changed files with 62 additions and 36 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ public Object[] listDartTests() {
* Throws AssertionError if the test fails.
*/
public RunDartTestResponse runDartTest(String name) {
final String TAG = "PatrolJUnitRunner.runDartTest(" + name + "): ";
final String TAG = "PatrolJUnitRunner.runDartTest(\"" + name + "\"): ";

try {
Logger.INSTANCE.i(TAG + "Requested execution");
Expand Down
33 changes: 26 additions & 7 deletions packages/patrol/lib/src/common.dart
Original file line number Diff line number Diff line change
Expand Up @@ -49,19 +49,35 @@ void patrolTearDown(Future<void> Function() body) {
}

/// A modification of [setUpAll] that works with Patrol's native automation.
///
/// It keeps track of calls made to setUpAll.
void patrolSetUpAll(Future<void> Function() body) {
setUpAll(() async {
final patrolAppService = PatrolBinding.instance.patrolAppService;

final parentGroupsName = global_state.currentGroupFullName;
patrolAppService.addSetUpAll(parentGroupsName);
final setUpAllName = patrolAppService.addSetUpAll(parentGroupsName);

if (await global_state.isInitialRun) {
// Skip calling body if we're in test discovery phase
print(
"PATROL_DEBUG: Skipping setUpAll '$setUpAllName' because it's test discovery phase",
);
return;
}

// TODO: Skip calling body if it this setUpAll was already executed

final requestedTest = await patrolAppService.testExecutionRequested;

// Skip calling if parentGroupName is not a substring of requestedTestName
if (!requestedTest.startsWith(parentGroupsName)) {
// This is not exhaustive.
return;
}

// final requestedToExecute = await PatrolBinding.instance.patrolAppService
// .waitForExecutionRequest(currentSetUpAllIndex);
await body();

// if (requestedToExecute) {
// await body();
// }
// TODO: Mark this setUpAll as executed
});
}

Expand Down Expand Up @@ -142,6 +158,9 @@ void patrolTest(
(widgetTester) async {
if (!constants.hotRestartEnabled) {
if (await global_state.isInitialRun) {
print(
'PATROL_DEBUG: falling through test "${global_state.currentTestFullName}"',
);
// Fall through tests during the initial run that discovers tests.
//
// This is required to be able to find all setUpAll callbacks.
Expand Down
4 changes: 3 additions & 1 deletion packages/patrol/lib/src/global_state.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// ignore: implementation_imports
import 'package:flutter/services.dart';
// ignore: implementation_imports
import 'package:test_api/src/backend/invoker.dart';

/// Maximum test case length for ATO, after transformations.
Expand Down Expand Up @@ -46,6 +46,8 @@ bool get isCurrentTestPassing {

const _channel = MethodChannel('pl.leancode.patrol/main');

/// Returns whether this is the first run of the app under test during which
/// test discovery happens.
Future<bool> get isInitialRun async {
return await _channel.invokeMethod('isInitialRun') as bool;
}
54 changes: 29 additions & 25 deletions packages/patrol/lib/src/native/patrol_app_service.dart
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,9 @@ class PatrolAppService extends PatrolAppServiceServer {
/// setUpAlls, unlike setUps, aren't executed in the [LiveTest] context.
/// Because of this, we can't depend on the [LiveTest]'s name, so we identify
/// them by the parent group ID instead.
///
/// This is a list of groups containing setUpAllCallbacks with an index
/// appended.
final List<String> setUpAlls = [];

/// A completer that completes with the name of the Dart test file that was
Expand All @@ -83,28 +86,26 @@ class PatrolAppService extends PatrolAppServiceServer {
}

/// Adds a setUpAll callback to the list of all setUpAll callbacks.
void addSetUpAll(String group) {
// Not very optimal, but good enough for now.

setUpAlls.add('$group + ${group.hashCode}');

// for (final setUpAll in setUpAlls) {
// final parts = setUpAll.split(' ');
// final groupName = parts.sublist(0, parts.length - 1).join(' ');

// if (groupName == group) {

// }
///
/// Returns the name under which this setUpAll callback was added.
String addSetUpAll(String group) {
// Not optimal, but good enough for now.

// Go over all groups, checking if the group is already in the list.
var groupIndex = 0;
for (final setUpAll in setUpAlls) {
final parts = setUpAll.split(' ');
final groupName = parts.sublist(0, parts.length - 1).join(' ');

if (groupName == group) {
groupIndex++;
}
}

// final index = parts.last;
// if (setUpAll == group) {
// return;
// }
// }
final name = '$group $groupIndex';

// add an index at the end of setUpAlls
// parent testA 1
// parent testA 2
setUpAlls.add(name);
return name;
}

/// Marks [dartFileName] as completed with the given [passed] status.
Expand Down Expand Up @@ -167,15 +168,13 @@ class PatrolAppService extends PatrolAppServiceServer {
@override
Future<ListDartTestsResponse> listDartTests() async {
print('PatrolAppService.listDartTests() called');
print('PATROL_DEBUG: setUpAlls: $setUpAlls');

return ListDartTestsResponse(group: topLevelDartTestGroup);
}

@override
Future<RunDartTestResponse> runDartTest(RunDartTestRequest request) async {
assert(_testExecutionCompleted.isCompleted == false);
// patrolTest() always calls this method.

print('PatrolAppService.runDartTest(${request.name}) called');
_testExecutionRequested.complete(request.name);
Expand All @@ -190,8 +189,13 @@ class PatrolAppService extends PatrolAppServiceServer {
}

@override
Future<ListDartLifecycleCallbacksResponse> listDartLifecycleCallbacks() {
// TODO: implement listDartLifecycleCallbacks
throw UnimplementedError();
Future<ListDartLifecycleCallbacksResponse>
listDartLifecycleCallbacks() async {
print('PatrolAppService.listDartLifecycleCallbacks() called');

return ListDartLifecycleCallbacksResponse(
setUpAlls: setUpAlls,
tearDownAlls: [],
);
}
}
5 changes: 3 additions & 2 deletions packages/patrol_cli/lib/src/test_bundler.dart
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ Future<void> main() async {
await nativeAutomator.initialize();
final binding = PatrolBinding.ensureInitialized();
final testExplorationCompleter = Completer<DartGroupEntry>();
late final PatrolAppService appService;
// A special test to expore the hierarchy of groups and tests. This is a hack
// around https://github.com/dart-lang/test/issues/1998.
Expand All @@ -94,11 +95,11 @@ ${generateGroupsCode(testFilePaths).split('\n').map((e) => ' $e').join('\n')}
// An additional callback to discover setUpAlls.
tearDownAll(() {
print('PATROL_DEBUG: calling tearDownAll to print setUpAlls');
print('PATROL_DEBUG: tearDownAll(): setUpAlls: \${appService.setUpAlls}');
});
final dartTestGroup = await testExplorationCompleter.future;
final appService = PatrolAppService(topLevelDartTestGroup: dartTestGroup);
appService = PatrolAppService(topLevelDartTestGroup: dartTestGroup);
binding.patrolAppService = appService;
await runAppService(appService);
Expand Down

0 comments on commit 56dca3b

Please sign in to comment.