Xfty 1.0.0-beta.12
dotnet add package Xfty --version 1.0.0-beta.12
NuGet\Install-Package Xfty -Version 1.0.0-beta.12
<PackageReference Include="Xfty" Version="1.0.0-beta.12" />
<PackageVersion Include="Xfty" Version="1.0.0-beta.12" />
<PackageReference Include="Xfty" />
paket add Xfty --version 1.0.0-beta.12
#r "nuget: Xfty, 1.0.0-beta.12"
#:package Xfty@1.0.0-beta.12
#addin nuget:?package=Xfty&version=1.0.0-beta.12&prerelease
#tool nuget:?package=Xfty&version=1.0.0-beta.12&prerelease
XFTY — Extreme C# Test Data Factory
XFTY is a declarative test data factory for C#.
Instead of manually constructing complete object graphs for every test, you describe only the values your test actually cares about. XFTY supplies sensible defaults, automatically creates related records, and can either mock persistence entirely or actually insert through a pluggable IPersistenceGateway.
The same Provider definitions can therefore be used in a pure in-memory unit test or a real database integration test.
Installation
dotnet add package Xfty
Xfty is the core package. Everything else in the XFTY ecosystem is optional.
Why XFTY?
As an application grows, so does the amount of code required simply to create valid test data.
A Contact might require an Account. Later, a validation rule might require additional Account fields. Eventually another related type becomes mandatory. Over time, hundreds or thousands of tests can end up duplicating nearly identical setup code.
XFTY centralizes that knowledge.
Providers define how valid records are constructed once. Individual tests then override only the fields that matter to the behavior being tested.
The result is test data that is:
- shorter to write
- easier to read
- easier to maintain
- more resilient to application changes
Quick Example
Generate a Contact using its Provider's defaults:
DefaultProviderLookup lookup = new();
Contact contact = (Contact)await new RecordProvider(typeof(Contact), lookup)
.Supply();
Override only the fields the test cares about:
Contact contact = (Contact)await new RecordProvider(typeof(Contact), lookup)
.Put<Contact>(x => x.FirstName, "Alice")
.SetInsertMode(InsertMode.Mock)
.Supply();
Generate a complete related object graph:
Bundle bundle = await new RecordProvider(typeof(Contact), lookup)
.SetInsertMode(InsertMode.Mock)
.SetInclusivity(InsertInclusivity.All)
.SupplyBundle();
Contact contact = (Contact)bundle.GetList<Contact>(x => x.Id)![0];
Account account = (Account)bundle.GetList<Contact>(x => x.AccountId)![0];
Assert.Equal(account.Id, contact.AccountId);
The important distinction is that the test does not have to know how to construct the complete Contact → Account graph. That knowledge belongs to the Providers.
Core Features
Declarative generation
Providers describe the data a particular record needs. Tests can then override individual fields without rebuilding the entire object.
.Put<Contact>(x => x.FirstName, "Alice")
Field access is expressed with lambdas rather than raw PropertyInfo instances or nameof(...).
Automatic relationships
XFTY can generate related records automatically, including:
- required relationships
- optional relationships
- shared ancestors
- self-referential relationships with cycle protection
Relationship behavior can also be controlled for an individual generation call with IncludeOptional and ExcludeRelationship, without changing the Provider itself.
Context-aware values
Values can depend on other generated records or fields in the graph.
A value can be derived from:
- a sibling
- a generated ancestor
- a generated child
XFTY detects an attempt to read a value before the corresponding part of the graph has been generated and reports the problem rather than silently producing an incorrect null.
Persistence
XFTY separates test-data generation from persistence through IPersistenceGateway.
A Provider can therefore be used with:
InsertMode.Mockfor tests that should not touch a database- a real persistence implementation for integration tests
The core package does not require a database provider.
The official EF Core implementation is available separately as Xfty.EntityFrameworkCore.
Deferred and depth-batched persistence
A graph can be built across multiple calls and then persisted as a bundle.
XFTY handles dependency ordering across mixed record types rather than requiring test code to manually determine which records must be inserted first.
Provider variants
The Provider architecture supports multiple definitions for the same record type.
FlavouredLookupKey and DiscriminatorLookupKey allow a different Provider to be selected according to a runtime predicate or field value.
Async throughout
The public generation and persistence pipeline is asynchronous.
This allows the same model to work with persistence implementations backed by databases, network services, or other inherently asynchronous infrastructure.
Persistence Is Optional
The core Xfty package does not contain a database-specific persistence implementation.
This is intentional.
You can use XFTY purely as an in-memory test-data factory, or add the persistence implementation appropriate for your integration tests.
For example:
Xfty.EntityFrameworkCore
EF Core persistence through IPersistenceGateway.
Additional persistence integrations are being developed separately rather than being bundled into the core package.
The XFTY Ecosystem
Xfty is the core of a collection of small, optional packages. They add capabilities without making the core package depend on unrelated libraries.
Some examples include:
| Package | Purpose |
|---|---|
Xfty.EntityFrameworkCore |
EF Core persistence through IPersistenceGateway |
Xfty.Bogus |
Realistic fake-data value generation using Bogus |
Xfty.VectorDatabases |
Random-vector value generation for embedding fields |
Xfty.AutoFixture |
Integration between XFTY and AutoFixture |
Xfty.AutoBogus |
Integration between XFTY and AutoBogus |
Xfty.Xunit |
xUnit integration, including [IsolatesSharedAncestor] |
Xfty.FSharpAsync |
Async<'T> wrappers for F# async { } workflows |
Xfty.VectorDatabases.Qdrant |
Preview Qdrant persistence integration |
Xfty.VectorDatabases.MicrosoftExtensionsVectorData |
Preview persistence through Microsoft.Extensions.VectorData connectors |
These packages are independent and opt-in. Installing Xfty does not pull the entire ecosystem into your application.
XFTY vs. General-Purpose Fixture Libraries
XFTY is not intended to replace every test-data or fixture library.
Libraries such as AutoFixture and Bogus solve different problems particularly well.
XFTY's focus is the combination of declarative Providers, related object graphs, and persistence.
In particular, XFTY can:
- generate a related graph rather than treating each object independently
- generate required and optional relationships
- deduplicate shared ancestors
- guard against self-referential relationship cycles
- use context-aware values derived from the generated graph
- use the same Provider definitions for mocked and real persistence
- select Provider variants according to runtime keys or predicates
Core Xfty deliberately does not attempt to provide realistic fake-data generation or automatic population of every unspecified property.
Those capabilities are available through optional ecosystem packages such as Xfty.Bogus, Xfty.AutoFixture, and Xfty.AutoBogus.
For a detailed comparison with AutoFixture, Bogus, AutoBogus, and NBuilder, see the project's comparison documentation.
Documentation
The full documentation lives in the repository:
- Getting started
- Using XFTY
- Extending XFTY
- API reference and cheatsheet
- Comparison with other test-data libraries
- Known issues
- Architecture
- Roadmap
Platform Support
The core package targets:
netstandard2.0net8.0net10.0
The netstandard2.0 target allows XFTY to be consumed by older .NET implementations, including .NET Framework 4.6.1+, Mono, Xamarin, and older .NET Core applications, while the net8.0 and net10.0 targets provide native builds for modern .NET applications.
Design Philosophy
XFTY is built around a simple idea:
Tests should describe only what makes them unique.
Everything else should be generated automatically.
Rather than scattering test-data construction throughout a test suite, XFTY moves knowledge about valid records and their relationships into reusable Providers.
The framework then constructs the object graph required by the test, leaving the test itself focused on the behavior it is supposed to verify.
Contributing
Contributions, bug reports, feature requests, and discussions are welcome.
The project repository contains the source code, tests, documentation, roadmap, and contribution information:
ExtremeCSharpTestDataFactory on GitHub
License
XFTY is released under the MIT License.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
| .NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.0 is compatible. netstandard2.1 was computed. |
| .NET Framework | net461 was computed. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 was computed. net481 was computed. |
| MonoAndroid | monoandroid was computed. |
| MonoMac | monomac was computed. |
| MonoTouch | monotouch was computed. |
| Tizen | tizen40 was computed. tizen60 was computed. |
| Xamarin.iOS | xamarinios was computed. |
| Xamarin.Mac | xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.0
- No dependencies.
-
net10.0
- No dependencies.
-
net8.0
- No dependencies.
NuGet packages (10)
Showing the top 5 NuGet packages that depend on Xfty:
| Package | Downloads |
|---|---|
|
Xfty.Xunit
xUnit integration for XFTY: [IsolatesSharedAncestor], an attribute for a test class or method that resets SharedAncestor's registry before and after - so a consumer never has to hand-wire a base test class or fixture to keep shared-ancestor state from leaking between tests. |
|
|
Xfty.VectorDatabases
A bundled IValueExpression for XFTY that fills a vector-database record's embedding field with a fixed-length array of random floats - structurally a vector, not a semantically meaningful embedding. |
|
|
Xfty.Bogus
Bundled IValueExpressions for XFTY that produce realistic-looking fake data - names, emails, addresses, paragraphs - by wrapping Bogus, instead of every Provider writing its own. |
|
|
Xfty.EntityFrameworkCore
An IPersistenceGateway implementation for XFTY that inserts generated records through Entity Framework Core, instead of mocking them. |
|
|
Xfty.AutoBogus
Pairs XFTY with AutoBogus (AutoFixture-style auto-population plus Bogus's realistic generators): point AutoBogus's generation at a registered RecordProvider instead of its own, and/or let AutoBogus fill in whatever fields a Provider's Master Template left unset. |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 1.0.0-beta.12 | 80 | 9/18/2026 |
| 1.0.0-beta.11 | 98 | 9/10/2026 |
| 1.0.0-beta.10 | 82 | 9/10/2026 |
| 1.0.0-beta.9 | 88 | 9/10/2026 |
| 1.0.0-beta.8 | 96 | 9/10/2026 |
| 1.0.0-beta.7 | 95 | 9/7/2026 |
| 1.0.0-beta.6 | 112 | 9/7/2026 |
| 1.0.0-beta.5 | 95 | 9/6/2026 |
| 1.0.0-beta.3 | 97 | 9/6/2026 |
| 1.0.0-beta.2 | 102 | 9/6/2026 |
| 1.0.0-beta.1 | 103 | 9/6/2026 |