DrillSergeant 0.0.6-alpha
See the version list below for details.
dotnet add package DrillSergeant --version 0.0.6-alpha
NuGet\Install-Package DrillSergeant -Version 0.0.6-alpha
<PackageReference Include="DrillSergeant" Version="0.0.6-alpha" />
paket add DrillSergeant --version 0.0.6-alpha
#r "nuget: DrillSergeant, 0.0.6-alpha"
// Install DrillSergeant as a Cake Addin #addin nuget:?package=DrillSergeant&version=0.0.6-alpha&prerelease // Install DrillSergeant as a Cake Tool #tool nuget:?package=DrillSergeant&version=0.0.6-alpha&prerelease
DrillSergeant
.net behavior driven testing written by developers, for developers.
Summary
DrillSergeant
is a behavior testing library that empowers developers to apply BDD practices with minimal amount of friction. Simply import the package and write your behaviors in familiar C# syntax.
Getting Started
For a complete example of a feature, see the following example.
Creating a Behavior
Creating a behavior is very simple:
[Behavior, InputData(1,1)]
public Behavior MyBehaviorTest(int value1, int value2)
{
var input = new Input(value1, value2);
var behavior = new Behavior<Context,Input>(input);
// Configure behavior here...
return behavior;
}
Behaviors are regular test methods that are decorated with the [Behavior]
attribute and return an instance of a Behavior
class. Because [Behavior]
is built on top of [Theory]
one or more inputs must be provided to the test. This can be done through any xunit
data discovery mechanism (e.g. [InlineData]
, [MemberData]
, etc...).
Context and Input
DrillSergeant
is built on top of xunit
and makes use of [Theory]
based tests. As a result behavior tests require both a context to hold state throughout the test and input to drive the test. These are typically defined using the C# record
type:
public class Context {};
public record Input();
Each step within a behavior can update its context, which is then fed into the next step. It's recommended to use the C# record
type for inputs and class
for context.
Configuring Input and Context
The only required parameter to a behavior is the input
parameter, which must be a type of TInput
. Context on the other hand is optional and can be omitted. If it is, then a new instance of TContext
will be instantiated using its parameterless constructor.
var input = new Input();
var behavior1 = new Behavior<Context,Input>(input); // Creates context automatically.
var behavior2 = new Behavior<Context,Input>(input, new Context()); // Manually specify context.
Configuring Steps
Individual steps can be configured depending on the level of granularity required.
Inline Steps
Inline steps are the simplest type of step. An inline step can be added simply by calling Given()
/When()
/Then()
and passing in a lambda:
Given("My step", (c,i) => {
// Perform some action
});
Inline steps are convenient when you need a one-off step that won't be reused in other behaviors.
Lambda Steps
Lambda steps are ideal for situations where a step needs to be reused for multiple behaviors within a single class:
public LambdaStep<Context,Input> MyStep =>
new GivenLambdaStep<Context,Input>()
.Named("My step")
.Handle( (c,i) => {
// Perform some action.
});
As you can see, the syntax is nearly identical to an inline step. In fact, inline steps are actually converted to lambda steps behind the scenes.
Class Steps
Class steps are the most flexible type of step and best used when a particular step needs to be reused between multiple features. To create a class step, override the desired verb and fill in the step method:
public class MyStep<Context,Input> : GivenStep<Context,Input>
{
public override void Given(Context context, Input input)
{
// Perform some action.
}
}
Unlike inline and lambda steps, class steps are convention based. By default, The GivenStep
, WhenStep
, and ThenStep
provide virtual methods for convenience, but it is not required to use them. Internally, DrillSergeant
will pick a matching verb method with the most parameters. For example:
public class MyStep<Context,Input> : GivenStep<Context,Input>
{
// DrillSergeant will *not* excute this.
public override void Given(Context context, Input input)
{
// Perform some action.
}
// DrillSergeant will execute this.
public override void Given(Context context, Input input, MyDependency dependency)
{
// Perform some action.
}
}
Configuring the Resolver
DrillSergeant
supports dependency injection for class steps and inline steps. This is accomplished via the IDependencyResolver
interface. The default behavior when injecting parameters is to invoke their default constructor. However this can be configured. To override this behavior, use the ConfigureResolver()
method and supply your own:
var behavior =
new Behavior<Context,Input>(input)
.ConfigureResolver(() => {
var resolver = A.Fake<IDependencyResolver();
// Configure resolver here...
return resolver;
});
In this example, we're using the mocking library FakeItEasy
to create a resolver that returns instances of the required dependency, but for more advanced scenarios a real DI container can be substituted in its place.
Best Practices
Favor Xunit Class/Collection Fixtures
Xunit already has a mechanism for handling shared data with constructors, IClassFixture<>
, and ICollectionFixture
. These should be preferred by default. More information can be found here.
As a quick recap:
- Use constructors/private fields for dependencies that are isolated at the test level.
- Use
IClassFixture<>
for dependencies that are isolated at the class level. - Use
ICollectionFixture<>
for global dependencies.
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net6.0 is compatible. 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 is compatible. 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 was computed. 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. |
-
net6.0
- System.Text.Json (>= 7.0.2)
- xunit.extensibility.execution (>= 2.4.2)
-
net7.0
- System.Text.Json (>= 7.0.2)
- xunit.extensibility.execution (>= 2.4.2)
NuGet packages (3)
Showing the top 3 NuGet packages that depend on DrillSergeant:
Package | Downloads |
---|---|
DrillSergeant.MSTest
Write behavior tests in pure C#. |
|
DrillSergeant.NUnit3
Write behavior tests in pure C#. |
|
DrillSergeant.Xunit2
Write behavior tests in pure C#. |
GitHub repositories
This package is not used by any popular GitHub repositories.
Version | Downloads | Last updated |
---|---|---|
1.2.2 | 59 | 4/21/2024 |
1.2.1 | 45 | 4/21/2024 |
1.2.0 | 66 | 2/20/2024 |
1.2.0-alpha.40 | 78 | 1/20/2024 |
1.2.0-alpha.39 | 54 | 1/20/2024 |
1.2.0-alpha.38 | 54 | 1/20/2024 |
1.2.0-alpha.37 | 51 | 1/20/2024 |
1.2.0-alpha.35 | 142 | 11/19/2023 |
1.2.0-alpha.34 | 64 | 11/19/2023 |
1.2.0-alpha.33 | 69 | 11/13/2023 |
1.1.8 | 52 | 2/20/2024 |
1.1.2 | 80 | 1/20/2024 |
1.1.1 | 255 | 11/12/2023 |
1.1.0-alpha.42 | 68 | 11/12/2023 |
1.1.0-alpha.41 | 66 | 11/12/2023 |
1.1.0-alpha.39 | 60 | 11/12/2023 |
1.1.0-alpha.38 | 68 | 11/12/2023 |
1.1.0-alpha.37 | 69 | 11/12/2023 |
1.1.0-alpha.35 | 67 | 11/12/2023 |
1.0.3 | 203 | 10/21/2023 |
1.0.1 | 183 | 10/12/2023 |
1.0.0-beta.53 | 78 | 9/30/2023 |
1.0.0-beta.52 | 70 | 9/29/2023 |
0.6.2 | 194 | 8/20/2023 |
0.6.1-beta | 149 | 8/20/2023 |
0.6.0-beta | 152 | 8/20/2023 |
0.5.0 | 208 | 7/20/2023 |
0.4.0 | 204 | 7/16/2023 |
0.3.0-beta | 181 | 7/12/2023 |
0.2.0-beta | 178 | 7/9/2023 |
0.1.0-beta | 99 | 7/4/2023 |
0.0.17-alpha | 119 | 7/3/2023 |
0.0.16-alpha | 118 | 6/30/2023 |
0.0.15-alpha | 128 | 6/29/2023 |
0.0.14-alpha | 116 | 6/23/2023 |
0.0.13-alpha | 114 | 6/23/2023 |
0.0.12-alpha | 112 | 6/16/2023 |
0.0.11-alpha | 118 | 6/14/2023 |
0.0.10-alpha | 115 | 6/10/2023 |
0.0.9-alpha | 108 | 5/28/2023 |
0.0.8-alpha | 106 | 5/25/2023 |
0.0.7-alpha | 105 | 5/23/2023 |
0.0.6-alpha | 114 | 5/20/2023 |
0.0.5-alpha | 118 | 5/20/2023 |
0.0.4-alpha | 111 | 5/17/2023 |
0.0.3-alpha | 104 | 5/14/2023 |
0.0.2-alpha | 112 | 5/12/2023 |