FEFF.TestFixtures.Xunit
1.0.1
Prefix Reserved
dotnet add package FEFF.TestFixtures.Xunit --version 1.0.1
NuGet\Install-Package FEFF.TestFixtures.Xunit -Version 1.0.1
<PackageReference Include="FEFF.TestFixtures.Xunit" Version="1.0.1" />
<PackageVersion Include="FEFF.TestFixtures.Xunit" Version="1.0.1" />
<PackageReference Include="FEFF.TestFixtures.Xunit" />
paket add FEFF.TestFixtures.Xunit --version 1.0.1
#r "nuget: FEFF.TestFixtures.Xunit, 1.0.1"
#:package FEFF.TestFixtures.Xunit@1.0.1
#addin nuget:?package=FEFF.TestFixtures.Xunit&version=1.0.1
#tool nuget:?package=FEFF.TestFixtures.Xunit&version=1.0.1
FEFF.TestFixtures
Replace setup/teardown methods with reusable Fixtures. Fixtures can depend on other ones. (!!!)
Terminology and Goals
A fixture is a reusable component used for testing purposes. Fixtures can be packaged into libraries and reused by any number of testing projects. The fixture is a class containing three optional parts:
- setup code in constructor;
- state;
- teardown code in Dispose() or DisposeAsync().
A scope of the fixtures defines a lifetime of those fixtures. For a scope, the fixture is created only once lazily on demand and destroyed at the end of the scope. If the fixture has Dispose() or DisposeAsync(), it is called. A list of scopes is defined by the test framework used. For Xunit Integration available scopes are:
| Scope name | Description |
|---|---|
| test-case | Fixtures are created and destroyed for each test case |
| class | Fixtures are created and destroyed once for each test class |
| collection | Fixtures are created and destroyed once for each test collection |
| assembly | Fixtures are created and destroyed once for a test assembly |
Every request of the same fixture from the same scope results in the same fixture instance. Hence class-, collection- and assembly- fixtures can share state between all tests within the same scope.
Getting started (Xunit)
Add library reference to a test project:
dotnet add package FEFF.TestFixtures.Xunit
Add assembly-level attribute to initialize the extension:
[assembly: FEFF.TestFixtures.Xunit.TestFixturesExtension]
Use TestContext.Current.GetFeffFixture<T>() extension method to get the required fixture instance at any moment of a test:
public class SystemUnderTest
{
public static void Write(string filePath) =>
File.WriteAllText(filePath, "some-data", Encoding.UTF8);
}
public class ExampleTests
{
protected TmpDirectoryFixture TmpDir { get; } = TestContext.Current.GetFeffFixture<TmpDirectoryFixture>();
[Fact]
public void File__should_be_created()
{
// Arrange
var filePath = TmpDir.Path + "/file.tmp";
File.Exists(filePath).Should().BeFalse();
// Act
SystemUnderTest.Write(filePath);
// Assert
File.Exists(filePath)
.Should().BeTrue();
File.ReadAllText(filePath, Encoding.UTF8)
.Should().Be("some-data");
}
}
In this example a TmpDir is created once the fixture is requested at the test class constructor. The scope of the fixture in the example is 'test-case'. The TmpDir with its content would be deleted automatically after the test finishes.
Advanced usage
Defining other scopes for a fixture
The scope of a fixture is defined by test creator using overloaded method:
TestContext.Current.GetFeffFixture<T>(FixtureScopeType scopeType)
Also note that multiple instances of the fixture can exist in different scopes if needed.
Creating a fixture
To create a fixture, user has to create a class with FixtureAttribute. Let's look at sources of TmpDirectoryFixture we have used above.
[Fixture]
public sealed class TmpDirectoryFixture : IDisposable
{
public string Path { get; } = Directory.CreateTempSubdirectory().FullName;
public void Dispose()
{
// double dispose guard
try
{
Directory.Delete(Path, true);
}
catch (DirectoryNotFoundException)
{
}
}
}
Where
| Fixture function | Implementation |
|---|---|
| Setup | Constructor |
| State | 'Path' property |
| Teardown | IDisposable |
Fixture dependencies
Fixtures can depend on other fixtures. Dependencies are injected via constructor:
[Fixture]
public class MyCustomFixture1
{
}
[Fixture]
public class MyCustomFixture2
{
}
[Fixture]
public record MyFixtureSet(
MyCustomFixture1 F1,
MyCustomFixture2 F2,
);
public class ExampleTests
{
protected MyFixtureSet Set { get; } = TestContext.Current.GetFeffFixture<MyFixtureSet>();
//...
}
Note:
- All fixture dependencies (
MyCustomFixture1&MyCustomFixture2) exist in the same scope as the dependent fixture (MyFixtureSetin the example above). - Fixtures can't have cyclic dependencies.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | 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. |
-
net10.0
- FEFF.TestFixtures (>= 1.0.1)
- xunit.v3.extensibility.core (>= 3.2.2)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|