Testing topic
Testing
A real temporary repository
Facades are implemented by the engines maintained with the package, so a test
that needs one opens a real temporary repository through the process backend.
Isolate git from the machine's configuration: set GIT_CONFIG_NOSYSTEM=1, point
GIT_CONFIG_GLOBAL at an empty file, fix the local identity and set
core.autocrlf=false. Remove the sandbox when the test ends; on Windows, retry
the deletion while git may still hold file locks.
Tests that drive the installed git are tagged git; dart test skips them and
dart test --run-skipped runs them where git 2.28 or newer is on the PATH.
import 'dart:io';
import 'package:git_engine/git_engine.dart';
import 'package:git_engine/process.dart';
Future<void> main() async {
final Directory sandbox =
await Directory.systemTemp.createTemp('engine_test_');
final File globalConfig = File('${sandbox.path}/gitconfig');
await globalConfig.writeAsString('');
try {
final ProcessGitEngine engine = ProcessGitEngine(
globalEnvironment: <String, String>{
'GIT_CONFIG_NOSYSTEM': '1',
'GIT_CONFIG_GLOBAL': globalConfig.path,
},
);
final GitWorkingRepository repository =
await engine.init('${sandbox.path}/repo', initialBranch: 'main');
print(await repository.branches.current());
} finally {
await sandbox.delete(recursive: true);
}
}
Implementable contracts
A test may implement a capability contract only: provide the members the test
uses and leave the others unimplemented. The repository-side contracts are
GitObjectReader, GitObjectWriter, GitObjectStore, GitRefReader,
GitRevisionResolver, GitHistoryReader, GitRefTransaction,
GitRepositoryReader and GitRepositoryWriter. The server-side contracts are
GitPrincipal, GitAuthorizationPolicy, GitServiceResponse,
GitUploadPackService and GitHttpRequest.
Because a test double and the real engine satisfy the same contract, one shared suite can run against both. Facades are not implemented by tests: a test that needs one uses the real repository above.
Seams of package:git_engine/testing.dart
That entry point exposes four seams:
GitRunnergathers a command throughGitRunRequestand returns aGitRunResult; every command of every domain passes through it.GitProcessLauncherstarts a streaming process throughGitProcessLaunchRequestand returns aGitLaunchedProcess.GitFileSystemperforms file operations,GitFileSystemEntrydescribes a listed child andMemoryGitFileSystemkeeps everything in memory.GitPlatformsupplies the operating system and path spelling asGitOperatingSystemandGitPathStyle, plus the environment variables.
ProcessGitEngine accepts a runner, a launcher, a file system and a platform
through its constructor. A runner already carries the executable, environment,
long-path setting and timeout, so supplying a non-default value for one of
those with it raises ArgumentError. The memory file system uses POSIX paths,
so pair it with GitPlatform.linux.
import 'package:git_engine/git_engine.dart';
import 'package:git_engine/process.dart';
import 'package:git_engine/testing.dart';
Future<void> main() async {
final MemoryGitFileSystem fileSystem = MemoryGitFileSystem();
final ProcessGitEngine engine = ProcessGitEngine(
fileSystem: fileSystem,
platform: GitPlatform.linux,
);
fileSystem.seedDirectory('/repo');
fileSystem.seedFile('/repo/notes.txt', <int>[65]);
try {
await engine.init('/repo');
} on GitOccupiedDirectoryException catch (error) {
print(error.path);
}
}
The creation guard of init consults the injected file system, so an occupied
target is refused before git runs and no repository is created.
Classes
- GitFileSystem Testing
- The file operations the process backend performs, injectable so they can run without a disk.
- GitFileSystemEntry Testing
- One entry of a listed directory.
- GitLaunchedProcess Testing
- A launched process, with the streams and controls a streaming exchange needs.
- GitPathStyle Testing
- Path spelling of a platform: Windows or POSIX.
- GitPlatform Testing
- The platform facts the process backend adapts to: the operating system, the path spelling, the environment variables commands receive and the directory relative paths hang from.
- GitProcessLauncher Testing
- Launches the streaming processes of the process backend.
- GitProcessLaunchRequest Testing
- Everything needed to launch one streaming process.
- GitRunner Testing
- Launches git commands.
- GitRunRequest Testing
- Everything needed to launch one git command.
- GitRunResult Testing
- Output of a git command that exited successfully.
- MemoryGitFileSystem Testing
- GitFileSystem kept entirely in memory, for tests without a disk.
Enums
- GitOperatingSystem Testing
- Operating system a GitPlatform describes.