Testing¶
As your repository is the single source of truth for everything git sees, it is worth testing it with a real git
client. GenHTTP.Testing makes this straightforward: it hosts a handler on a free port for the duration of a test.
[TestMethod]
public async Task TestPushedVersionsCanBeCloned()
{
var repository = new DocumentRepository(...);
await using var host = await TestHost.RunAsync(GitServer.Create().Repository(repository));
// run git clone/commit/push against host.GetUrl("/") and inspect your repository
}
Running git from tests requires a few precautions so the tests neither depend on nor change the configuration of the machine they run on:
- Use a temporary
HOMEwith its own.gitconfig(user name and email,init.defaultBranch), and setGIT_CONFIG_NOSYSTEM=1andGIT_TERMINAL_PROMPT=0. - Enable
transfer.fsckObjectsso the client verifies everything it receives, and rungit fsck --stricton clones. - Run the important scenarios with
protocol.versionset to0and2, as the server implements both.
The test suite of this project
contains a GitClient helper doing exactly this, along with tests for many scenarios you can use as a starting
point.
What to test¶
- Stability: cloning twice (and after restarting your application) yields the same commit ids.
- Round trips: pushed commits are returned with the same ids and files, e.g. by cloning into a second directory.
- Rules: everything your repository rejects is reported to the client with a helpful message.
- Concurrency: changes made outside of git while a client works on a clone result in "fetch first" rejections instead of lost changes.
- History limits: if you delete old data, clones still work and are shallow.
Using the in-memory repository¶
InMemoryGitRepository behaves like a bare repository hosted by git and is useful to test code that consumes
repositories (e.g. a CI integration), or as a reference when implementing your own repository: