[flutter_plugin_tools] Build gtest unit tests (#4492)
diff --git a/packages/url_launcher/url_launcher/example/linux/flutter/CMakeLists.txt b/packages/url_launcher/url_launcher/example/linux/flutter/CMakeLists.txt
index 94f43ff..33fd580 100644
--- a/packages/url_launcher/url_launcher/example/linux/flutter/CMakeLists.txt
+++ b/packages/url_launcher/url_launcher/example/linux/flutter/CMakeLists.txt
@@ -78,7 +78,8 @@
COMMAND ${CMAKE_COMMAND} -E env
${FLUTTER_TOOL_ENVIRONMENT}
"${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.sh"
- linux-x64 ${CMAKE_BUILD_TYPE}
+ ${FLUTTER_TARGET_PLATFORM} ${CMAKE_BUILD_TYPE}
+ VERBATIM
)
add_custom_target(flutter_assemble DEPENDS
"${FLUTTER_LIBRARY}"
diff --git a/packages/url_launcher/url_launcher/example/windows/flutter/generated_plugin_registrant.cc b/packages/url_launcher/url_launcher/example/windows/flutter/generated_plugin_registrant.cc
index d9fdd53..4f78848 100644
--- a/packages/url_launcher/url_launcher/example/windows/flutter/generated_plugin_registrant.cc
+++ b/packages/url_launcher/url_launcher/example/windows/flutter/generated_plugin_registrant.cc
@@ -6,9 +6,9 @@
#include "generated_plugin_registrant.h"
-#include <url_launcher_windows/url_launcher_plugin.h>
+#include <url_launcher_windows/url_launcher_windows.h>
void RegisterPlugins(flutter::PluginRegistry* registry) {
- UrlLauncherPluginRegisterWithRegistrar(
- registry->GetRegistrarForPlugin("UrlLauncherPlugin"));
+ UrlLauncherWindowsRegisterWithRegistrar(
+ registry->GetRegistrarForPlugin("UrlLauncherWindows"));
}
diff --git a/packages/url_launcher/url_launcher_linux/example/linux/CMakeLists.txt b/packages/url_launcher/url_launcher_linux/example/linux/CMakeLists.txt
index 1758aac..11219aa 100644
--- a/packages/url_launcher/url_launcher_linux/example/linux/CMakeLists.txt
+++ b/packages/url_launcher/url_launcher_linux/example/linux/CMakeLists.txt
@@ -45,6 +45,8 @@
# Enable the test target.
set(include_url_launcher_linux_tests TRUE)
+# Provide an alias for the test target using the name expected by repo tooling.
+add_custom_target(unit_tests DEPENDS url_launcher_linux_test)
# Generated plugin build rules, which manage building the plugins and adding
# them to the application.
diff --git a/packages/url_launcher/url_launcher_windows/example/windows/CMakeLists.txt b/packages/url_launcher/url_launcher_windows/example/windows/CMakeLists.txt
index 5b1622b..5a5d2e8 100644
--- a/packages/url_launcher/url_launcher_windows/example/windows/CMakeLists.txt
+++ b/packages/url_launcher/url_launcher_windows/example/windows/CMakeLists.txt
@@ -48,6 +48,8 @@
# Enable the test target.
set(include_url_launcher_windows_tests TRUE)
+# Provide an alias for the test target using the name expected by repo tooling.
+add_custom_target(unit_tests DEPENDS url_launcher_windows_test)
# Generated plugin build rules, which manage building the plugins and adding
# them to the application.
diff --git a/script/tool/CHANGELOG.md b/script/tool/CHANGELOG.md
index 5a037c8..31efc28 100644
--- a/script/tool/CHANGELOG.md
+++ b/script/tool/CHANGELOG.md
@@ -1,5 +1,7 @@
## NEXT
+- `native-test` now builds unit tests before running them on Windows and Linux,
+ matching the behavior of other platforms.
- Added `--log-timing` to add timing information to package headers in looping
commands.
diff --git a/script/tool/lib/src/common/cmake.dart b/script/tool/lib/src/common/cmake.dart
new file mode 100644
index 0000000..04ad880
--- /dev/null
+++ b/script/tool/lib/src/common/cmake.dart
@@ -0,0 +1,118 @@
+// Copyright 2013 The Flutter Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import 'package:file/file.dart';
+import 'package:flutter_plugin_tools/src/common/core.dart';
+import 'package:platform/platform.dart';
+
+import 'process_runner.dart';
+
+const String _cacheCommandKey = 'CMAKE_COMMAND:INTERNAL';
+
+/// A utility class for interacting with CMake projects.
+class CMakeProject {
+ /// Creates an instance that runs commands for [project] with the given
+ /// [processRunner].
+ CMakeProject(
+ this.flutterProject, {
+ required this.buildMode,
+ this.processRunner = const ProcessRunner(),
+ this.platform = const LocalPlatform(),
+ });
+
+ /// The directory of a Flutter project to run Gradle commands in.
+ final Directory flutterProject;
+
+ /// The [ProcessRunner] used to run commands. Overridable for testing.
+ final ProcessRunner processRunner;
+
+ /// The platform that commands are being run on.
+ final Platform platform;
+
+ /// The build mode (e.g., Debug, Release).
+ ///
+ /// This is a constructor paramater because on Linux many properties depend
+ /// on the build mode since it uses a single-configuration generator.
+ final String buildMode;
+
+ late final String _cmakeCommand = _determineCmakeCommand();
+
+ /// The project's platform directory name.
+ String get _platformDirName => platform.isWindows ? 'windows' : 'linux';
+
+ /// The project's 'example' build directory for this instance's platform.
+ Directory get buildDirectory {
+ Directory buildDir =
+ flutterProject.childDirectory('build').childDirectory(_platformDirName);
+ if (platform.isLinux) {
+ buildDir = buildDir
+ // TODO(stuartmorgan): Support arm64 if that ever becomes a supported
+ // CI configuration for the repository.
+ .childDirectory('x64')
+ // Linux uses a single-config generator, so the base build directory
+ // includes the configuration.
+ .childDirectory(buildMode.toLowerCase());
+ }
+ return buildDir;
+ }
+
+ File get _cacheFile => buildDirectory.childFile('CMakeCache.txt');
+
+ /// Returns the CMake command to run build commands for this project.
+ ///
+ /// Assumes the project has been built at least once, such that the CMake
+ /// generation step has run.
+ String getCmakeCommand() {
+ return _cmakeCommand;
+ }
+
+ /// Returns the CMake command to run build commands for this project. This is
+ /// used to initialize _cmakeCommand, and should not be called directly.
+ ///
+ /// Assumes the project has been built at least once, such that the CMake
+ /// generation step has run.
+ String _determineCmakeCommand() {
+ // On Linux 'cmake' is expected to be in the path, so doesn't need to
+ // be lookup up and cached.
+ if (platform.isLinux) {
+ return 'cmake';
+ }
+ final File cacheFile = _cacheFile;
+ String? command;
+ for (String line in cacheFile.readAsLinesSync()) {
+ line = line.trim();
+ if (line.startsWith(_cacheCommandKey)) {
+ command = line.substring(line.indexOf('=') + 1).trim();
+ break;
+ }
+ }
+ if (command == null) {
+ printError('Unable to find CMake command in ${cacheFile.path}');
+ throw ToolExit(100);
+ }
+ return command;
+ }
+
+ /// Whether or not the project is ready to have CMake commands run on it
+ /// (i.e., whether the `flutter` tool has generated the necessary files).
+ bool isConfigured() => _cacheFile.existsSync();
+
+ /// Runs a `cmake` command with the given parameters.
+ Future<int> runBuild(
+ String target, {
+ List<String> arguments = const <String>[],
+ }) {
+ return processRunner.runAndStream(
+ getCmakeCommand(),
+ <String>[
+ '--build',
+ buildDirectory.path,
+ '--target',
+ target,
+ if (platform.isWindows) ...<String>['--config', buildMode],
+ ...arguments,
+ ],
+ );
+ }
+}
diff --git a/script/tool/lib/src/common/gradle.dart b/script/tool/lib/src/common/gradle.dart
index e7214bf..9da4e89 100644
--- a/script/tool/lib/src/common/gradle.dart
+++ b/script/tool/lib/src/common/gradle.dart
@@ -14,9 +14,6 @@
class GradleProject {
/// Creates an instance that runs commands for [project] with the given
/// [processRunner].
- ///
- /// If [log] is true, commands run by this instance will long various status
- /// messages.
GradleProject(
this.flutterProject, {
this.processRunner = const ProcessRunner(),
diff --git a/script/tool/lib/src/native_test_command.dart b/script/tool/lib/src/native_test_command.dart
index 4911b4a..0b0dd26 100644
--- a/script/tool/lib/src/native_test_command.dart
+++ b/script/tool/lib/src/native_test_command.dart
@@ -5,6 +5,7 @@
import 'package:file/file.dart';
import 'package:platform/platform.dart';
+import 'common/cmake.dart';
import 'common/core.dart';
import 'common/gradle.dart';
import 'common/package_looping_command.dart';
@@ -456,8 +457,8 @@
file.basename.endsWith('_tests.exe');
}
- return _runGoogleTestTests(plugin,
- buildDirectoryName: 'windows', isTestBinary: isTestBinary);
+ return _runGoogleTestTests(plugin, 'Windows', 'Debug',
+ isTestBinary: isTestBinary);
}
Future<_PlatformResult> _testLinux(
@@ -471,8 +472,16 @@
file.basename.endsWith('_tests');
}
- return _runGoogleTestTests(plugin,
- buildDirectoryName: 'linux', isTestBinary: isTestBinary);
+ // Since Linux uses a single-config generator, building-examples only
+ // generates the build files for release, so the tests have to be run in
+ // release mode as well.
+ //
+ // TODO(stuartmorgan): Consider adding a command to `flutter` that would
+ // generate build files without doing a build, and using that instead of
+ // relying on running build-examples. See
+ // https://github.com/flutter/flutter/issues/93407.
+ return _runGoogleTestTests(plugin, 'Linux', 'Release',
+ isTestBinary: isTestBinary);
}
/// Finds every file in the [buildDirectoryName] subdirectory of [plugin]'s
@@ -482,38 +491,66 @@
/// The binaries are assumed to be Google Test test binaries, thus returning
/// zero for success and non-zero for failure.
Future<_PlatformResult> _runGoogleTestTests(
- RepositoryPackage plugin, {
- required String buildDirectoryName,
+ RepositoryPackage plugin,
+ String platformName,
+ String buildMode, {
required bool Function(File) isTestBinary,
}) async {
final List<File> testBinaries = <File>[];
+ bool hasMissingBuild = false;
+ bool buildFailed = false;
for (final RepositoryPackage example in plugin.getExamples()) {
- final Directory buildDir = example.directory
- .childDirectory('build')
- .childDirectory(buildDirectoryName);
- if (!buildDir.existsSync()) {
+ final CMakeProject project = CMakeProject(example.directory,
+ buildMode: buildMode,
+ processRunner: processRunner,
+ platform: platform);
+ if (!project.isConfigured()) {
+ printError('ERROR: Run "flutter build" on ${example.displayName}, '
+ 'or run this tool\'s "build-examples" command, for the target '
+ 'platform before executing tests.');
+ hasMissingBuild = true;
continue;
}
- testBinaries.addAll(buildDir
+
+ // By repository convention, example projects create an aggregate target
+ // called 'unit_tests' that builds all unit tests (usually just an alias
+ // for a specific test target).
+ final int exitCode = await project.runBuild('unit_tests');
+ if (exitCode != 0) {
+ printError('${example.displayName} unit tests failed to build.');
+ buildFailed = true;
+ }
+
+ testBinaries.addAll(project.buildDirectory
.listSync(recursive: true)
.whereType<File>()
.where(isTestBinary)
.where((File file) {
- // Only run the release build of the unit tests, to avoid running the
- // same tests multiple times. Release is used rather than debug since
- // `build-examples` builds release versions.
+ // Only run the `buildMode` build of the unit tests, to avoid running
+ // the same tests multiple times.
final List<String> components = path.split(file.path);
- return components.contains('release') || components.contains('Release');
+ return components.contains(buildMode) ||
+ components.contains(buildMode.toLowerCase());
}));
}
+ if (hasMissingBuild) {
+ return _PlatformResult(RunState.failed,
+ error: 'Examples must be built before testing.');
+ }
+
+ if (buildFailed) {
+ return _PlatformResult(RunState.failed,
+ error: 'Failed to build $platformName unit tests.');
+ }
+
if (testBinaries.isEmpty) {
final String binaryExtension = platform.isWindows ? '.exe' : '';
printError(
'No test binaries found. At least one *_test(s)$binaryExtension '
'binary should be built by the example(s)');
return _PlatformResult(RunState.failed,
- error: 'No $buildDirectoryName unit tests found');
+ error: 'No $platformName unit tests found');
}
bool passing = true;
diff --git a/script/tool/test/native_test_command_test.dart b/script/tool/test/native_test_command_test.dart
index ba93efc..697cbd4 100644
--- a/script/tool/test/native_test_command_test.dart
+++ b/script/tool/test/native_test_command_test.dart
@@ -8,10 +8,12 @@
import 'package:args/command_runner.dart';
import 'package:file/file.dart';
import 'package:file/memory.dart';
+import 'package:flutter_plugin_tools/src/common/cmake.dart';
import 'package:flutter_plugin_tools/src/common/core.dart';
import 'package:flutter_plugin_tools/src/common/file_utils.dart';
import 'package:flutter_plugin_tools/src/common/plugin_utils.dart';
import 'package:flutter_plugin_tools/src/native_test_command.dart';
+import 'package:platform/platform.dart';
import 'package:test/test.dart';
import 'mocks.dart';
@@ -53,6 +55,16 @@
}
};
+const String _fakeCmakeCommand = 'path/to/cmake';
+
+void _createFakeCMakeCache(Directory pluginDir, Platform platform) {
+ final CMakeProject project = CMakeProject(pluginDir.childDirectory('example'),
+ platform: platform, buildMode: 'Release');
+ final File cache = project.buildDirectory.childFile('CMakeCache.txt');
+ cache.createSync(recursive: true);
+ cache.writeAsStringSync('CMAKE_COMMAND:INTERNAL=$_fakeCmakeCommand');
+}
+
// TODO(stuartmorgan): Rework these tests to use a mock Xcode instead of
// doing all the process mocking and validation.
void main() {
@@ -67,7 +79,10 @@
setUp(() {
fileSystem = MemoryFileSystem();
- mockPlatform = MockPlatform(isMacOS: true);
+ // iOS and macOS tests expect macOS, Linux tests expect Linux; nothing
+ // needs to distinguish between Linux and macOS, so set both to true to
+ // allow them to share a setup group.
+ mockPlatform = MockPlatform(isMacOS: true, isLinux: true);
packagesDir = createPackagesDirectory(fileSystem: fileSystem);
processRunner = RecordingProcessRunner();
final NativeTestCommand command = NativeTestCommand(packagesDir,
@@ -133,6 +148,26 @@
package.path);
}
+ // Returns the ProcessCall to expect for build the Linux unit tests for the
+ // given plugin.
+ ProcessCall _getLinuxBuildCall(Directory pluginDir) {
+ return ProcessCall(
+ 'cmake',
+ <String>[
+ '--build',
+ pluginDir
+ .childDirectory('example')
+ .childDirectory('build')
+ .childDirectory('linux')
+ .childDirectory('x64')
+ .childDirectory('release')
+ .path,
+ '--target',
+ 'unit_tests'
+ ],
+ null);
+ }
+
test('fails if no platforms are provided', () async {
Error? commandError;
final List<String> output = await runCapturingPrint(
@@ -844,15 +879,16 @@
});
group('Linux', () {
- test('runs unit tests', () async {
+ test('builds and runs unit tests', () async {
const String testBinaryRelativePath =
- 'build/linux/foo/release/bar/plugin_test';
+ 'build/linux/x64/release/bar/plugin_test';
final Directory pluginDirectory =
createFakePlugin('plugin', packagesDir, extraFiles: <String>[
'example/$testBinaryRelativePath'
], platformSupport: <String, PlatformDetails>{
kPlatformLinux: const PlatformDetails(PlatformSupport.inline),
});
+ _createFakeCMakeCache(pluginDirectory, mockPlatform);
final File testBinary = childFileWithSubcomponents(pluginDirectory,
<String>['example', ...testBinaryRelativePath.split('/')]);
@@ -874,15 +910,16 @@
expect(
processRunner.recordedCalls,
orderedEquals(<ProcessCall>[
+ _getLinuxBuildCall(pluginDirectory),
ProcessCall(testBinary.path, const <String>[], null),
]));
});
test('only runs release unit tests', () async {
const String debugTestBinaryRelativePath =
- 'build/linux/foo/debug/bar/plugin_test';
+ 'build/linux/x64/debug/bar/plugin_test';
const String releaseTestBinaryRelativePath =
- 'build/linux/foo/release/bar/plugin_test';
+ 'build/linux/x64/release/bar/plugin_test';
final Directory pluginDirectory =
createFakePlugin('plugin', packagesDir, extraFiles: <String>[
'example/$debugTestBinaryRelativePath',
@@ -890,6 +927,7 @@
], platformSupport: <String, PlatformDetails>{
kPlatformLinux: const PlatformDetails(PlatformSupport.inline),
});
+ _createFakeCMakeCache(pluginDirectory, mockPlatform);
final File releaseTestBinary = childFileWithSubcomponents(
pluginDirectory,
@@ -909,15 +947,15 @@
]),
);
- // Only the release version should be run.
expect(
processRunner.recordedCalls,
orderedEquals(<ProcessCall>[
+ _getLinuxBuildCall(pluginDirectory),
ProcessCall(releaseTestBinary.path, const <String>[], null),
]));
});
- test('fails if there are no unit tests', () async {
+ test('fails if CMake has not been configured', () async {
createFakePlugin('plugin', packagesDir,
platformSupport: <String, PlatformDetails>{
kPlatformLinux: const PlatformDetails(PlatformSupport.inline),
@@ -936,22 +974,56 @@
expect(
output,
containsAllInOrder(<Matcher>[
- contains('No test binaries found.'),
+ contains('plugin:\n'
+ ' Examples must be built before testing.')
]),
);
expect(processRunner.recordedCalls, orderedEquals(<ProcessCall>[]));
});
+ test('fails if there are no unit tests', () async {
+ final Directory pluginDirectory = createFakePlugin(
+ 'plugin', packagesDir,
+ platformSupport: <String, PlatformDetails>{
+ kPlatformLinux: const PlatformDetails(PlatformSupport.inline),
+ });
+ _createFakeCMakeCache(pluginDirectory, mockPlatform);
+
+ Error? commandError;
+ final List<String> output = await runCapturingPrint(runner, <String>[
+ 'native-test',
+ '--linux',
+ '--no-integration',
+ ], errorHandler: (Error e) {
+ commandError = e;
+ });
+
+ expect(commandError, isA<ToolExit>());
+ expect(
+ output,
+ containsAllInOrder(<Matcher>[
+ contains('No test binaries found.'),
+ ]),
+ );
+
+ expect(
+ processRunner.recordedCalls,
+ orderedEquals(<ProcessCall>[
+ _getLinuxBuildCall(pluginDirectory),
+ ]));
+ });
+
test('fails if a unit test fails', () async {
const String testBinaryRelativePath =
- 'build/linux/foo/release/bar/plugin_test';
+ 'build/linux/x64/release/bar/plugin_test';
final Directory pluginDirectory =
createFakePlugin('plugin', packagesDir, extraFiles: <String>[
'example/$testBinaryRelativePath'
], platformSupport: <String, PlatformDetails>{
kPlatformLinux: const PlatformDetails(PlatformSupport.inline),
});
+ _createFakeCMakeCache(pluginDirectory, mockPlatform);
final File testBinary = childFileWithSubcomponents(pluginDirectory,
<String>['example', ...testBinaryRelativePath.split('/')]);
@@ -979,6 +1051,7 @@
expect(
processRunner.recordedCalls,
orderedEquals(<ProcessCall>[
+ _getLinuxBuildCall(pluginDirectory),
ProcessCall(testBinary.path, const <String>[], null),
]));
});
@@ -1524,16 +1597,37 @@
runner.addCommand(command);
});
+ // Returns the ProcessCall to expect for build the Windows unit tests for
+ // the given plugin.
+ ProcessCall _getWindowsBuildCall(Directory pluginDir) {
+ return ProcessCall(
+ _fakeCmakeCommand,
+ <String>[
+ '--build',
+ pluginDir
+ .childDirectory('example')
+ .childDirectory('build')
+ .childDirectory('windows')
+ .path,
+ '--target',
+ 'unit_tests',
+ '--config',
+ 'Debug'
+ ],
+ null);
+ }
+
group('Windows', () {
test('runs unit tests', () async {
const String testBinaryRelativePath =
- 'build/windows/foo/Release/bar/plugin_test.exe';
+ 'build/windows/Debug/bar/plugin_test.exe';
final Directory pluginDirectory =
createFakePlugin('plugin', packagesDir, extraFiles: <String>[
'example/$testBinaryRelativePath'
], platformSupport: <String, PlatformDetails>{
kPlatformWindows: const PlatformDetails(PlatformSupport.inline),
});
+ _createFakeCMakeCache(pluginDirectory, mockPlatform);
final File testBinary = childFileWithSubcomponents(pluginDirectory,
<String>['example', ...testBinaryRelativePath.split('/')]);
@@ -1555,15 +1649,16 @@
expect(
processRunner.recordedCalls,
orderedEquals(<ProcessCall>[
+ _getWindowsBuildCall(pluginDirectory),
ProcessCall(testBinary.path, const <String>[], null),
]));
});
- test('only runs release unit tests', () async {
+ test('only runs debug unit tests', () async {
const String debugTestBinaryRelativePath =
- 'build/windows/foo/Debug/bar/plugin_test.exe';
+ 'build/windows/Debug/bar/plugin_test.exe';
const String releaseTestBinaryRelativePath =
- 'build/windows/foo/Release/bar/plugin_test.exe';
+ 'build/windows/Release/bar/plugin_test.exe';
final Directory pluginDirectory =
createFakePlugin('plugin', packagesDir, extraFiles: <String>[
'example/$debugTestBinaryRelativePath',
@@ -1571,10 +1666,10 @@
], platformSupport: <String, PlatformDetails>{
kPlatformWindows: const PlatformDetails(PlatformSupport.inline),
});
+ _createFakeCMakeCache(pluginDirectory, mockPlatform);
- final File releaseTestBinary = childFileWithSubcomponents(
- pluginDirectory,
- <String>['example', ...releaseTestBinaryRelativePath.split('/')]);
+ final File debugTestBinary = childFileWithSubcomponents(pluginDirectory,
+ <String>['example', ...debugTestBinaryRelativePath.split('/')]);
final List<String> output = await runCapturingPrint(runner, <String>[
'native-test',
@@ -1590,15 +1685,15 @@
]),
);
- // Only the release version should be run.
expect(
processRunner.recordedCalls,
orderedEquals(<ProcessCall>[
- ProcessCall(releaseTestBinary.path, const <String>[], null),
+ _getWindowsBuildCall(pluginDirectory),
+ ProcessCall(debugTestBinary.path, const <String>[], null),
]));
});
- test('fails if there are no unit tests', () async {
+ test('fails if CMake has not been configured', () async {
createFakePlugin('plugin', packagesDir,
platformSupport: <String, PlatformDetails>{
kPlatformWindows: const PlatformDetails(PlatformSupport.inline),
@@ -1617,22 +1712,56 @@
expect(
output,
containsAllInOrder(<Matcher>[
- contains('No test binaries found.'),
+ contains('plugin:\n'
+ ' Examples must be built before testing.')
]),
);
expect(processRunner.recordedCalls, orderedEquals(<ProcessCall>[]));
});
+ test('fails if there are no unit tests', () async {
+ final Directory pluginDirectory = createFakePlugin(
+ 'plugin', packagesDir,
+ platformSupport: <String, PlatformDetails>{
+ kPlatformWindows: const PlatformDetails(PlatformSupport.inline),
+ });
+ _createFakeCMakeCache(pluginDirectory, mockPlatform);
+
+ Error? commandError;
+ final List<String> output = await runCapturingPrint(runner, <String>[
+ 'native-test',
+ '--windows',
+ '--no-integration',
+ ], errorHandler: (Error e) {
+ commandError = e;
+ });
+
+ expect(commandError, isA<ToolExit>());
+ expect(
+ output,
+ containsAllInOrder(<Matcher>[
+ contains('No test binaries found.'),
+ ]),
+ );
+
+ expect(
+ processRunner.recordedCalls,
+ orderedEquals(<ProcessCall>[
+ _getWindowsBuildCall(pluginDirectory),
+ ]));
+ });
+
test('fails if a unit test fails', () async {
const String testBinaryRelativePath =
- 'build/windows/foo/Release/bar/plugin_test.exe';
+ 'build/windows/Debug/bar/plugin_test.exe';
final Directory pluginDirectory =
createFakePlugin('plugin', packagesDir, extraFiles: <String>[
'example/$testBinaryRelativePath'
], platformSupport: <String, PlatformDetails>{
kPlatformWindows: const PlatformDetails(PlatformSupport.inline),
});
+ _createFakeCMakeCache(pluginDirectory, mockPlatform);
final File testBinary = childFileWithSubcomponents(pluginDirectory,
<String>['example', ...testBinaryRelativePath.split('/')]);
@@ -1660,6 +1789,7 @@
expect(
processRunner.recordedCalls,
orderedEquals(<ProcessCall>[
+ _getWindowsBuildCall(pluginDirectory),
ProcessCall(testBinary.path, const <String>[], null),
]));
});