BDTest is a testing framework. It can be used with other frameworks (such as MSTest, xUnit or NUnit) or standalone.
The examples below will use attributes (such as [Test]
) from NUnit.
Install via Nuget > Install-Package BDTest
Tests can be constructed either by extending from a base class, or by using the a test builder object.
Extending from BDTestBase
public class MyTests : BDTestBase
{
[Test]
public void Test1() {
Given(() => Action1())
.When(() => Action2())
.Then(() => Action3())
.BDTest();
}
}
Or by using the BDTestBuilder
object
public class MyTests
{
[Test]
public void Test1() {
new BDTestBuilder().Given(() => Action1())
.When(() => Action2())
.Then(() => Action3())
.BDTest();
}
}
Construction of your TestContext using lambda syntax
public class MyTests : BDTestBase
{
[Test]
public void Test1() {
WithContext<TestContext>(context =>
Given(() => Action1(context))
.When(() => Action2(context))
.Then(() => Action3(context))
.BDTest()
);
}
}
- Your TestContext will be automatically constructed and injected in via the lambda
Instead of extending from BDTestBase
extend from NUnitBDTestBase
and pass the type of your Context.
Your context will be constructed for each test independently.
Access this using the Context
property. See below for example.
public class TestsUsingNUnitBaseWithContext : NUnitBDTestBase<TestContext>
{
[Test]
public void Test1()
{
Given(() => Action1(Context))
.When(() => Action2(Context))
.Then(() => Action3(Context))
.BDTest();
}
}
For either of these methods, your TestContext should have a public constructor with 0 parameters. Otherwise, check out the source code for NUnitBDTestBase to set up your own version with extra construction logic.
In order to keep all tests thread safe and have the ability to run all in parallel:
- Use the
NUnitBDTestBase<>
base class ORWithContext<TestContext>(...)
syntax as above - Do not use static variables/fields/properties in your tests
- Do not share fields/properties in your test class - All variables should be populated as new for each test - Which the Context construction can take care of
BDTest enforces best practice:
- Tests MUST contain a
Given
+When
+Then
and executed with aBDTest
- Tests MUST start with a
Given
- Off of a
Given
you can haveAnd
orWhen
- Off of an
And
you can haveAnd
orWhen
- Off of an
- Off of a
When
you can have aThen
- (No
And
- We should be testing one action!)
- (No
- Off of a
Then
you can haveAnd
orBDTest
- Off of an
And
you can haveAnd
orBDTest
- Off of an
- Off of a
Annotate your test classes with a [StoryText]
attribute
[Story(AsA = "Test User",
IWant = "To Test",
SoThat = "Things Work")]
public class MyTests : BDTestBase
{
...
}
Annotate your tests with a [ScenarioText]
attribute
[Test]
[ScenarioText("Custom Scenario")]
public void Test1()
{
Given(() => Action1())
.When(() => Action2())
.Then(() => Action3())
.And(() => Action4())
.BDTest();
}
Annotate your steps/methods with a [StepText]
attribute
[StepText("I perform my second action")]
public void Action2()
{
...
}
Use parameter indexes to substitute in your arguments to the steptext
[StepText("my name is {0} {1}")]
public void SetName(string firstName, string lastName)
{
...
}
public void TestSetName()
{
Given(() => SetName("Tom", "Longhurst");) // StepText should equal "Given my name is Tom Longhurst"
.When(() => SetName("Tom", "Longhurst");) // StepText should equal "When my name is Tom Longhurst"
.Then(() => SetName("Tom", "Longhurst");) // StepText should equal "Then my name is Tom Longhurst"
.And(() => SetName("Tom", "Longhurst");) // StepText should equal "And my name is Tom Longhurst"
}
Install via Nuget > Install-Package BDTest.ReportGenerator
You don't have to do anything for the standard reports!
Once the package has been installed and your tests have run, these reports should appear in your output directory automatically.
See below for extra options.
BDTest allows you to pass it a directory path, to persistantly store test data. Why is this useful? It allows us to keep a record of all our test runs, and this allows us to compare test runs.
Set the directory by setting BDTestSettings.PersistantResultsDirectory
[OneTimeSetUp]
public void SetPersistantStorage()
{
BDTestSettings.PersistantResultsDirectory = "C:\\AcceptanceTests";
}
[Test]
public void Test()
{
...
}
If you set these, you will be produced a Test Time Comparison Report and a Test Flakiness Report.
In your output directory after your tests have finished:
BDTest - Report - Test Times Comparison - {timestamp}.html
In your output directory after your tests have finished:
BDTest - Report - Test Times Comparison - {timestamp}.html
In your output directory after your tests have finished:
BDTest - Test Data - {timestamp}.json
Example:
{
"TestTimer": {
"TestsStartedAt": "2019-01-11T10:23:50.0230533+00:00",
"TestsFinishedAt": "2019-01-11T10:23:50.6290701+00:00",
"ElapsedTime": "00:00:00.6060168"
},
"Scenarios": [
{
"StartTime": "2019-01-11T10:23:50.551935+00:00",
"EndTime": "2019-01-11T10:23:50.553344+00:00",
"TimeTaken": "0.00:00:00:0014090",
"StoryText": {
"Story": "As a Test User\r\nI want To Test\r\nSo that Things Work\r\n"
},
"ScenarioText": {
"Scenario": "Custom Scenario"
},
"Steps": [
{
"StartTime": "2019-01-11T10:23:50.5519411+00:00",
"EndTime": "2019-01-11T10:23:50.5522994+00:00",
"_stepType": "Given",
"TimeTaken": "0.00:00:00:0003583",
"Exception": null,
"Status": "Passed",
"StepText": "Given Action 1"
},
{
"StartTime": "2019-01-11T10:23:50.5523005+00:00",
"EndTime": "2019-01-11T10:23:50.5528788+00:00",
"_stepType": "When",
"TimeTaken": "0.00:00:00:0005783",
"Exception": null,
"Status": "Passed",
"StepText": "When Action 2 is custom text"
},
{
"StartTime": "2019-01-11T10:23:50.5528798+00:00",
"EndTime": "2019-01-11T10:23:50.5531625+00:00",
"_stepType": "Then",
"TimeTaken": "0.00:00:00:0002827",
"Exception": null,
"Status": "Passed",
"StepText": "Then Action 3"
},
{
"StartTime": "2019-01-11T10:23:50.5531635+00:00",
"EndTime": "2019-01-11T10:23:50.5533388+00:00",
"_stepType": "AndThen",
"TimeTaken": "0.00:00:00:0001753",
"Exception": null,
"Status": "Passed",
"StepText": "And Action 3"
}
],
"Status": "Passed"
}
]
}
In your output directory after your tests have finished:
BDTest - Test Data - {timestamp}.xml
Example:
<?xml version="1.0" encoding="utf-16"?>
<TestData>
<TestTimer>
<TestsStartedAt>2019-01-11T10:23:50.0230533+00:00</TestsStartedAt>
<TestsFinishedAt>2019-01-11T10:23:50.6290701+00:00</TestsFinishedAt>
<ElapsedTime>00:00:00.6060168</ElapsedTime>
</TestTimer>
<Scenarios>
<StartTime>2019-01-11T10:23:50.551935+00:00</StartTime>
<EndTime>2019-01-11T10:23:50.553344+00:00</EndTime>
<TimeTaken>0.00:00:00:0014090</TimeTaken>
<StoryText>
<Story>As a Test User
I want To Test
So that Things Work
</Story>
</StoryText>
<ScenarioText>
<Scenario>Custom Scenario</Scenario>
</ScenarioText>
<Steps>
<StartTime>2019-01-11T10:23:50.5519411+00:00</StartTime>
<EndTime>2019-01-11T10:23:50.5522994+00:00</EndTime>
<_stepType>Given</_stepType>
<TimeTaken>0.00:00:00:0003583</TimeTaken>
<Exception />
<Status>Passed</Status>
<StepText>Given Action 1</StepText>
</Steps>
<Steps>
<StartTime>2019-01-11T10:23:50.5523005+00:00</StartTime>
<EndTime>2019-01-11T10:23:50.5528788+00:00</EndTime>
<_stepType>When</_stepType>
<TimeTaken>0.00:00:00:0005783</TimeTaken>
<Exception />
<Status>Passed</Status>
<StepText>When Action 2</StepText>
</Steps>
<Steps>
<StartTime>2019-01-11T10:23:50.5528798+00:00</StartTime>
<EndTime>2019-01-11T10:23:50.5531625+00:00</EndTime>
<_stepType>Then</_stepType>
<TimeTaken>0.00:00:00:0002827</TimeTaken>
<Exception />
<Status>Passed</Status>
<StepText>Then Action 3</StepText>
</Steps>
<Steps>
<StartTime>2019-01-11T10:23:50.5531635+00:00</StartTime>
<EndTime>2019-01-11T10:23:50.5533388+00:00</EndTime>
<_stepType>AndThen</_stepType>
<TimeTaken>0.00:00:00:0001753</TimeTaken>
<Exception />
<Status>Passed</Status>
<StepText>And Action 4</StepText>
</Steps>
<Status>Passed</Status>
</Scenarios>
</TestData>
In your output directory after your tests have finished:
BDTest - Report - By Story - {timestamp}.html
In your output directory after your tests have finished:
BDTest - Report - All Scenarios - {timestamp}.html