Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Before writing any tests, you will need to add a reference to Bard.dll in your project.
The simplest way to do this is to use either the NuGet package manager, or the dotnet CLI.
Using the NuGet package manager console within Visual Studio run the following command:
Or using the .net core CLI from a terminal window:
A .NET library for functional API testing.
Bard is a test library written by Developers for Developers. It is as much a development tool as it is a test library. Although Bard is a .NET library it can be used to test any API if you want.
Bard provides you with the building blocks to allow you to build your own Domain Specific Language (DSL) for test arrangement. This allows the developer to build up a library of stories that can be composed via a fluent interface.
The fluent interface guides the developer how to construct the scenario in a logical sequence making it easier for new tests to be written. This arguably involves a little more effort up front but can pay dividends in the long run when working against a complex domain that involves intricate test arrangement.
Bard uses a functional approach to test arrangement and employs the Collection Pipeline Pattern
Collection pipelines are a programming pattern where you organize some computation as a sequence of operations which compose by taking a collection as output of one operation and feeding it into the next. - Martin Fowler
This means that when there are a number of sequential steps performed during the arrangement of the test data can flow from one step to the next step.
Bard generates exceptional automatically generated log from your tests. This means you can write your tests first and then build your APIs. This gives the developer the opportunity to 'Dog Food' their API whilst writing their tests. No more eyeballing API responses in tools such as Postman.
A fluent API response helper is built directly into Bard. This hides away the boiler plate code needed to work with the HTTP Response and makes the intent of the test easier to comprehend.
Basic configuration of Bard means the Arrangement part of the test cannot be utilized.
To configure our Scenario a few thing need to be set.
Client: our HTTP Client to call our API with (Required)
LogMessage: An action to instruct Bard where to log test output to. This is optional but important because Bard provides detailed logs to the test output windows to help with writing and debugging test failures. If not supplied Bard will output all log messages to the Console window which may not appear in your test output. (Optional)
Services: An instance of a .NET service provider to allow Bard access to use Dependency Injection. (Optional)
BadRequestProvider: Override the default bad request provider with your own implementation. (Optional)
Advanced configuration of Bard means that a StoryBook is specified which allows all the features of Bard to be used within the scenario.
The configuration of our Scenario is almost the same as the basic configuration apart from that we specify that we are going to use a StoryBook
.
Our StoryBook
might look something like this.
And our StoryData
is just a plain old c# object (POCO) of your choice.
A Chapter
is used to navigate through our Scenario
. It contains Stories. It allows us to guide the test author what they can do next.
The important thing to remember is that the Chapter
can receive the output of the previous Story
as an input via the StoryData
. We do that by inheriting from the base Class Chapter
and specify our StoryData class as the Generic Type. Our class should look like this.
Now we have our Chapter we can add our Stories.
As described in the introduction a StoryBook
is the starting Chapter
of our Scenario
.
Lets illustrate what that really means, with an example. I will use my fictitious Banking API to demonstrate.
We want to test the scenario in our Banking API that the balance of our account is correct after we make a cash deposit.
Before we can do that there are a couple of steps we need to do to test that scenario.
Create the bank account
Deposit the money into the correct account.
In Bard after we have created the bank account we can pass the results from the 'Create Bank Account' story into the 'Deposit Money' story this is useful because we probably need to know the Id of the newly created bank account.
Lets demonstrate what that would look like with a code example.
Lets talk about what's going on in that example. The first thing to note is we are calling the base method When
and this is where we do the 'work' of the story is done by calling our create bank account endpoint. Notice that we are making our API call using our TestContext
on line 10.
Now on line 12 we are returning we are updating our StoryData with the response from the API call, making that data available to the next story.
Finally on line 14 we call the generic ProceedToChapter
base method. This instructs our fluent API what the next Chapter
is that will help us build out our Fluent Test interface.
Bard allows you to assert that the correct headers are present in your API Response.
The response can be checked to ensure the correct error message or error code is returned by the API.
When your API returns an HTTP 400 Bard give you the ability to interrogate the API response in more detail.
Execute your tests against your API by calling When on your scenario.
This is essentially a wrapper over the standard .NET HttpClient but that adds additional logging.
StoryData is a plain old C# object (POCO) of your choice. An instance of this class will be instantiated at the beginning of your test arrangement and is accessible in every story. This means you can enrich your StoryData as your stories progress.
You can only have one instance of StoryData per configured scenario.
The story data can be accessed from within a story from the scenario context.
The example below demonstrates accessing the story data to get the correct id to use in the URL and updating the story data with the result of the API call.
This section how to perform test arrangement with Bard. This is the part of the test that tells the 'story' of the state of the system for the test to run.
In my opinion this is the most important part of an integration test and probably the part that is most overlooked when writing tests.
When testing a complex domain test arrangement can become convoluted. A framework like Bard encourages the developers to invest more time upfront to building a library of stories. However these stories be reused and composed into different scenarios. Overtime this will make your tests easier to write, easier to understand and easier to maintain.
In summary the goal of Bard is to make your tests:
Easy to read and understand.
Easy to reuse.
More maintainable
Easy to compose new tests.
Bard has the concept of a StoryBook
. The Story Book describes the way you can interact with you API/Domain in order to put it in the required state. Think of a StoryBook
as the opening chapter of your scenario.
A StoryBook
is the entry point into a Scenario
.
A StoryBook
is made up of Chapters
& Stories
.
The StoryBook
is the starting Chapter
of our Scenario
and from there we can select a Story
that take us to the next Chapter
that contains other stories.
Chapters are our decision points. What can we do given what has happened already.
Stories are the building blocks. This is where the work is done and we make changes to our domain, usually through making an API call.
What makes Bard different from other BDD style testing frameworks is that the output from one Story is the input to the next chapter and the containing stories.
Bard uses a functional approach to test arrangement and employs the Collection Pipeline Pattern
Collection pipelines are a programming pattern where you organize some computation as a sequence of operations which compose by taking a collection as output of one operation and feeding it into the next. - Martin Fowler
This is a powerful feature which means the output of one Story can be the input to the next Story. This can make your tests easier to write and easier to understand.
This page links to some .NET Fiddles to demonstrate. More to be added.
Replace all references of IScenarioContext with ScenarioContext
Example this code:
Should change to:
refactored to:
To test a gRPC API with Bard you will need to install the Bard.gRPC extension .
The simplest way to do this is to use either the NuGet package manager, or the dotnet CLI.
Using the NuGet package manager console within Visual Studio run the following command:
Or using the .net core CLI from a terminal window:
Bard provides the ability to assert that the API responses are returned within a specified timeframe. This can be asserted at a test level or globally for an entire Scenario.
The test below show an individual assertion for a specific end point.
The scenario configuration below demonstrates how to set a global benchmark for all API calls so that they do not exceed 2000 milliseconds.
As described in the the story is where the work is actually done where we can perform our test arrangement.
We can have a few different flavors of stories depending upon where we are in the scenario and how we want to use the story.
A starting story is a story that is written in the opening chapter of a StoryBook
. It is different from other stories in the fact that it does not have any input from other stories.
A simple story has come from another chapter and therefore has input from the previous story.
Notice we have access to the context and the bankAccount on line 3.
Sometimes in the course of a scenario that it makes sense that we want to reuse our story in another chapter. For example with our Banking example after we create a bank account we can either make a withdrawal or a deposit. If we make a withdrawal we should be able to make a further withdrawal or a further deposit. In essence we want to be able to recursively make withdrawals and deposits using our fluent interface.
We could just copy and paste the code into each chapter but that could present a maintenance problem in the future.
However because Bard takes a functional approach to describing it's stories we can define a common library of Story functions and compose our Chapter with those functions.
Lets demonstrate with an example:
What does this mean?
ScenarioContext this is our test context.
DepositRequest this is the API parameter that is passed into the function which means we can pass it from our story rather than hard code it in this function.
Now in our Chapter we write our Story by referencing our Function
Notice that on line 4 we are calling the base Method Given
and passing in a function that describes how to create our API request object.
So before we can start we need to configure our Scenario. To do this we are going to need provide a number of things.
Line 2 we specify our grpc generated client.
Line 3 we specify our StoryBook
& Story Data
Line 6 we provide an instance of our Service Provider so we can use dependency injection within our Stories (Optional)
Line 7 we specify how to log our output (Recommended)
Line 8 provides a delegate function to instantiate an instance of our gRPC client (Required)
Line 9 provides an instance of our HTTP Client.
IScenarioContext now removed. Should be replaced with ScenarioContext instead.
Changed method signatures on Chapters to make them simpler. The Funcs used to require the Chapter Input in the method signature. Now the Chapter input is accessible on the ScenarioContext
Changed UseResult method to access tests output. Used to be called UseResult but is now called GetResult.
Now uses:
Note: UseResult used to terminate the test arrangement. Now GetResult allows you to continue with the test arrangement.
Removed CommonExtensions so now cannot use .And .A etc between test arrangements.
Added better logging when building a chapter and not calling the Context's API. Previously nothing was logged to the console. Now Bard tracks if the API has been called or not and if it hasn't it defaults to outputing the response from the story.
Bug when asserting HTTP code returned from API due to Shouldly not working in Release build.
Bug when asserting HTTP code returned from API due to Shouldly not working in Release build.
Initial Release
Removed dependency on library.
Removed dependency on library.
This section will describe how to configure Bard in order to write your first API test. This example demonstrates the simplest way to use Bard and does not use the more advanced StoryBook feature which we will cover in more detail in this section of the documentation.
So before we can start we need to configure our Scenario. To do this we are going to need provide two things.
A System.Net.Http.HttpClient
in order to call our API
A function to tell our Scenario how to log. This is optional but important because Bard provides detailed logs to the test output windows to help with writing and debugging test failures. If not supplied Bard will ouput all log messages to the Console window which may not appear in your test output.
The GitHub repository has some example tests you can see a working example here.
We've configured our Scenario now. Assuming our API is running now we can start by calling it.
So lets give it a spin by writing a test that calls our fictitious Banking API and creating a new bank account. We expect our API to return a 201 Created response.
And we're done. If we look at the output from our Test we should see some nice logging that includes the request and the response.
In most of the examples in our Stories we have called our API directly to perform the test arrangement. Sometimes this isn't good enough, we may need to simulate an incoming message on a Message Queue or want to insert some data directly into our API Database.
If this is the case we can tell Bard how to resolve services when we configure the Scenario and access them within the Story through the ScenarioContext. This is particularly easy if you are testing a .NET API.