Skip to content

Commit 26d11f4

Browse files
[tool] Run config-only build for iOS/macOS native-test (#9080)
Follow-up to #9075. On iOS and macOS, `native-test` also requires an unconditional project file generatino in debug mode now, to ensure that the debug Xcode build of the tests will not fail due to a build mode mismatch. Unblocks the flutter/flutter->flutter/packages roller.
1 parent 2fcc403 commit 26d11f4

File tree

2 files changed

+62
-10
lines changed

2 files changed

+62
-10
lines changed

script/tool/lib/src/native_test_command.dart

Lines changed: 27 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -433,12 +433,12 @@ this command.
433433
}
434434

435435
Future<_PlatformResult> _testIOS(RepositoryPackage plugin, _TestMode mode) {
436-
return _runXcodeTests(plugin, 'iOS', mode,
436+
return _runXcodeTests(plugin, FlutterPlatform.ios, mode,
437437
extraFlags: _iOSDestinationFlags);
438438
}
439439

440440
Future<_PlatformResult> _testMacOS(RepositoryPackage plugin, _TestMode mode) {
441-
return _runXcodeTests(plugin, 'macOS', mode);
441+
return _runXcodeTests(plugin, FlutterPlatform.macos, mode);
442442
}
443443

444444
/// Runs all applicable tests for [plugin], printing status and returning
@@ -448,7 +448,7 @@ this command.
448448
/// usually at "example/{ios,macos}/Runner.xcworkspace".
449449
Future<_PlatformResult> _runXcodeTests(
450450
RepositoryPackage plugin,
451-
String targetPlatform,
451+
FlutterPlatform targetPlatform,
452452
_TestMode mode, {
453453
List<String> extraFlags = const <String>[],
454454
}) async {
@@ -459,6 +459,8 @@ this command.
459459
} else if (mode.integrationOnly) {
460460
testTarget = 'RunnerUITests';
461461
}
462+
final String targetPlatformString =
463+
targetPlatform == FlutterPlatform.ios ? 'iOS' : 'macOS';
462464

463465
bool ranUnitTests = false;
464466
// Assume skipped until at least one test has run.
@@ -472,8 +474,8 @@ this command.
472474
bool exampleHasUnitTests = false;
473475
final String? targetToCheck =
474476
testTarget ?? (mode.unit ? unitTestTarget : null);
475-
final Directory xcodeProject = example.directory
476-
.childDirectory(targetPlatform.toLowerCase())
477+
final Directory xcodeProject = example
478+
.platformDirectory(targetPlatform)
477479
.childDirectory('Runner.xcodeproj');
478480
if (targetToCheck != null) {
479481
final bool? hasTarget =
@@ -490,14 +492,29 @@ this command.
490492
}
491493
}
492494

493-
_printRunningExampleTestsMessage(example, targetPlatform);
495+
// Ensure that the native project files are configured for a debug build,
496+
// otherwise the Xcode build step will fail due to mode mismatch.
497+
final bool buildSuccess = await runConfigOnlyBuild(
498+
example,
499+
processRunner,
500+
platform,
501+
targetPlatform,
502+
buildDebug: true,
503+
);
504+
if (!buildSuccess) {
505+
printError('Unable to generate debug Xcode project files');
506+
overallResult = RunState.failed;
507+
continue;
508+
}
509+
510+
_printRunningExampleTestsMessage(example, targetPlatformString);
494511
final int exitCode = await _xcode.runXcodeBuild(
495512
example.directory,
496-
targetPlatform,
513+
targetPlatformString,
497514
// Clean before testing to remove cached swiftmodules from previous
498515
// runs, which can cause conflicts.
499516
actions: <String>['clean', 'test'],
500-
workspace: '${targetPlatform.toLowerCase()}/Runner.xcworkspace',
517+
workspace: '${targetPlatformString.toLowerCase()}/Runner.xcworkspace',
501518
scheme: 'Runner',
502519
configuration: 'Debug',
503520
hostPlatform: platform,
@@ -513,10 +530,10 @@ this command.
513530
const int xcodebuildNoTestExitCode = 66;
514531
switch (exitCode) {
515532
case xcodebuildNoTestExitCode:
516-
_printNoExampleTestsMessage(example, targetPlatform);
533+
_printNoExampleTestsMessage(example, targetPlatformString);
517534
case 0:
518535
printSuccess(
519-
'Successfully ran $targetPlatform xctest for $exampleName');
536+
'Successfully ran $targetPlatformString xctest for $exampleName');
520537
// If this is the first test, assume success until something fails.
521538
if (overallResult == RunState.skipped) {
522539
overallResult = RunState.succeeded;

script/tool/test/native_test_command_test.dart

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,21 @@ void main() {
135135
null);
136136
}
137137

138+
// Returns the ProcessCall to expect for generating the native project files
139+
// with a --config-only build on iOS or macOS.
140+
ProcessCall getConfigOnlyDarwinBuildCall(
141+
Directory package, FlutterPlatform platform) {
142+
return ProcessCall(
143+
'flutter',
144+
<String>[
145+
'build',
146+
if (platform == FlutterPlatform.ios) 'ios' else 'macos',
147+
'--debug',
148+
'--config-only',
149+
],
150+
package.path);
151+
}
152+
138153
// Returns the ProcessCall to expect for running the tests in the
139154
// workspace [platform]/Runner.xcworkspace, with the given extra flags.
140155
ProcessCall getRunTestCall(
@@ -246,6 +261,8 @@ void main() {
246261
processRunner.recordedCalls,
247262
orderedEquals(<ProcessCall>[
248263
getTargetCheckCall(pluginExampleDirectory, 'macos'),
264+
getConfigOnlyDarwinBuildCall(
265+
pluginExampleDirectory, FlutterPlatform.macos),
249266
getRunTestCall(pluginExampleDirectory, 'macos',
250267
extraFlags: <String>['-only-testing:RunnerUITests']),
251268
]));
@@ -317,6 +334,8 @@ void main() {
317334
processRunner.recordedCalls,
318335
orderedEquals(<ProcessCall>[
319336
getTargetCheckCall(pluginExampleDirectory, 'ios'),
337+
getConfigOnlyDarwinBuildCall(
338+
pluginExampleDirectory, FlutterPlatform.ios),
320339
getRunTestCall(pluginExampleDirectory, 'ios',
321340
destination: 'foo_destination'),
322341
]));
@@ -354,6 +373,8 @@ void main() {
354373
],
355374
null),
356375
getTargetCheckCall(pluginExampleDirectory, 'ios'),
376+
getConfigOnlyDarwinBuildCall(
377+
pluginExampleDirectory, FlutterPlatform.ios),
357378
getRunTestCall(pluginExampleDirectory, 'ios',
358379
destination: 'id=$_simulatorDeviceId'),
359380
]));
@@ -421,6 +442,8 @@ void main() {
421442
processRunner.recordedCalls,
422443
orderedEquals(<ProcessCall>[
423444
getTargetCheckCall(pluginExampleDirectory, 'macos'),
445+
getConfigOnlyDarwinBuildCall(
446+
pluginExampleDirectory, FlutterPlatform.macos),
424447
getRunTestCall(pluginExampleDirectory, 'macos'),
425448
]));
426449
});
@@ -1305,6 +1328,8 @@ public class FlutterActivityTest {
13051328
processRunner.recordedCalls,
13061329
orderedEquals(<ProcessCall>[
13071330
getTargetCheckCall(pluginExampleDirectory, 'macos'),
1331+
getConfigOnlyDarwinBuildCall(
1332+
pluginExampleDirectory, FlutterPlatform.macos),
13081333
getRunTestCall(pluginExampleDirectory, 'macos',
13091334
extraFlags: <String>['-only-testing:RunnerTests']),
13101335
]));
@@ -1340,6 +1365,8 @@ public class FlutterActivityTest {
13401365
processRunner.recordedCalls,
13411366
orderedEquals(<ProcessCall>[
13421367
getTargetCheckCall(pluginExampleDirectory, 'macos'),
1368+
getConfigOnlyDarwinBuildCall(
1369+
pluginExampleDirectory, FlutterPlatform.macos),
13431370
getRunTestCall(pluginExampleDirectory, 'macos',
13441371
extraFlags: <String>['-only-testing:RunnerUITests']),
13451372
]));
@@ -1609,9 +1636,13 @@ public class FlutterActivityTest {
16091636
],
16101637
androidFolder.path),
16111638
getTargetCheckCall(pluginExampleDirectory, 'ios'),
1639+
getConfigOnlyDarwinBuildCall(
1640+
pluginExampleDirectory, FlutterPlatform.ios),
16121641
getRunTestCall(pluginExampleDirectory, 'ios',
16131642
destination: 'foo_destination'),
16141643
getTargetCheckCall(pluginExampleDirectory, 'macos'),
1644+
getConfigOnlyDarwinBuildCall(
1645+
pluginExampleDirectory, FlutterPlatform.macos),
16151646
getRunTestCall(pluginExampleDirectory, 'macos'),
16161647
]));
16171648
});
@@ -1648,6 +1679,8 @@ public class FlutterActivityTest {
16481679
processRunner.recordedCalls,
16491680
orderedEquals(<ProcessCall>[
16501681
getTargetCheckCall(pluginExampleDirectory, 'macos'),
1682+
getConfigOnlyDarwinBuildCall(
1683+
pluginExampleDirectory, FlutterPlatform.macos),
16511684
getRunTestCall(pluginExampleDirectory, 'macos'),
16521685
]));
16531686
});
@@ -1684,6 +1717,8 @@ public class FlutterActivityTest {
16841717
processRunner.recordedCalls,
16851718
orderedEquals(<ProcessCall>[
16861719
getTargetCheckCall(pluginExampleDirectory, 'ios'),
1720+
getConfigOnlyDarwinBuildCall(
1721+
pluginExampleDirectory, FlutterPlatform.ios),
16871722
getRunTestCall(pluginExampleDirectory, 'ios',
16881723
destination: 'foo_destination'),
16891724
]));

0 commit comments

Comments
 (0)