Accelergreat.Xunit
3.0.0
Prefix Reserved
dotnet add package Accelergreat.Xunit --version 3.0.0
NuGet\Install-Package Accelergreat.Xunit -Version 3.0.0
<PackageReference Include="Accelergreat.Xunit" Version="3.0.0" />
paket add Accelergreat.Xunit --version 3.0.0
#r "nuget: Accelergreat.Xunit, 3.0.0"
// Install Accelergreat.Xunit as a Cake Addin #addin nuget:?package=Accelergreat.Xunit&version=3.0.0 // Install Accelergreat.Xunit as a Cake Tool #tool nuget:?package=Accelergreat.Xunit&version=3.0.0
uid: DeveloperDocumentation.Index
Ultra Fast Integration Tests
Accelergreat your tests.
Write and execute efficient and high-performance integration tests with ease. Accelergreat is a powerful .NET integration testing solution that automatically provisions and manages external dependencies for your tests, such as databases and APIs. Simplify your integration testing development process today.
Overview
Accelergreat is a new and innovative testing platform designed to make integration testing easier.
Integration tests are essential to ensuring your code works and stays working. However, they have been challenging to write and run quickly in the past, earning a reputation as a problem area in the development world.
With Accelergreat we intend to make this a problem of the past by doing all the hard work for you.
Accelergreat currently supports xUnit and plans to support other test runners in the future.
NuGet Packages
Accelergreat has a range of nuget packages for different feature sets:
Core packages
Package | |
---|---|
Accelergreat |
Referenced by all other Accelergreat packages. You can also reference this package to make your own custom Accelergreat components. |
Accelergreat.EntityFramework |
Core Entity Framework package referenced by Accelergreat's Entity Framework packages. |
Test framework packages
The test framework packages contain Accelergreat's test framework specific code. All other packages can be used interchangeably with each test framework package.
Framework | Package |
---|---|
xUnit | Accelergreat.Xunit |
Application packages
Accelergreat can run instances of your application.
Application type | Package |
---|---|
Web API | Accelergreat.Web |
Entity Framework packages
Accelergreat supports different database providers with the following entity framework packages. Accelergreat fully manages databse creation, reset between tests and cleanup at the end of the test run.
Provider | Package |
---|---|
Sql Server | Accelergreat.EntityFramework.SqlServer |
Postgre SQL | Accelergreat.EntityFramework.PostgreSql |
Sqlite | Accelergreat.EntityFramework.Sqlite |
In Memory | Accelergreat.EntityFramework.InMemory |
Future packages
Accelergreat is growing and open to requests. See Community & Support for how to get in touch.
Version Compatibility
Accelergreat follows Semantic Versioning 2.0.0 for releases.
Accelergreat keeps up-to date with dotnet releases and each major version will support all currently in-support versions of dotnet at the time of release.
Accelergreat will not introduce amy breaking public API changes for minor and patch versions.
Getting started (xUnit)
Getting startes is easy, whether you are starting a new test project, or want to migrate an existing one.
High level steps
Install
Accelergreat.Xunit
in your test project.dotnet add package Accelergreat.Xunit
Define components needed.
One of the core features of Accelergreat is the concept of components. A component represents a dependency for your tests. For example a database or a web API.
Accelergreat offers a range of pre-built components that can be extended for your specific needs. Or, you can build your own components by implementing the
IAccelergreatComponent
interface.To further understand components beyond what the getting started guide explains, the different components Accelergreat offers and to understand how to build your own components. See the dedicated guide on components.
Configure the environment
Configure the environment by registering components in a startup class that implements the
IAccelergreatStartup
interface. Just like how you setup dependency injection for your application, Accelergreat uses dependency injection for environment and component resolution for your tests.Write your tests! 🚀
Detailed steps (example use case)
Accelergreat has been designed with modularity and flexibility in mind. Whilst the example we have provided below may not match your specific use case, this example was chosen to best show the capabilities of Accelergreat. It should be an effective reference point for your own implementations.
Use case example: Database (Entity Framework SQL Server) + Web API integration test
To see other examples, you can look on our GitHub examples repo.
1. Install the required packages
Accelergreat.EntityFramework.SqlServer
dotnet add package Accelergreat.EntityFramework.SqlServer
Accelergreat.Web
dotnet add package Accelergreat.Web
2. Create the Accelergreat Components
In our example we only need two components. One for our SQL Server database, and one for our Web API.
Database component
Create a class that inherits from SqlServerEntityFrameworkDatabaseComponent
.
If you need to override any of the configuration values, see SqlServerEntityFrameworkConfiguration
for the defaults.
using Accelergreat.EntityFramework.SqlServer;
using Microsoft.Extensions.Configuration;
namespace ExampleTestProject.Components;
public class ExampleDatabaseComponent : SqlServerEntityFrameworkDatabaseComponent<ExampleDbContext>
{
public ExampleDatabaseComponent(IConfiguration configuration) : base(configuration)
{
}
}
Web API component
To interact with a .NET Web API in our integration tests, we need to create a Web App Component.
Web app components run an instance of the API defined by the Web API startup class passed into the generic type parameter. The following steps will set up a component for you:
- Create a class derived from
WebAppComponent
. - Inject the database connection string(s).
- [Optional] overriding appsettings.
Create the class derived from WebAppComponent
To create a Web App Component, create a class that inherits from WebAppComponent
and pass in your Web API startup class as the generic type parameter.
Using an API startup class
using System.Collections.Generic;
using Accelergreat.Web;
using Accelergreat.Web.Extensions;
using Microsoft.Extensions.Configuration;
namespace ExampleTestProject.Components;
public class ExampleApiComponent : WebAppComponent<ExampleApi.Startup>
{
protected override void BuildConfiguration(
IConfigurationBuilder configurationBuilder,
IReadOnlyAccelergreatEnvironmentPipelineData accelergreatEnvironmentPipelineData)
{
configurationBuilder.AddEntityFrameworkDatabaseConnectionString<ExampleDbContext>(
"ExampleConnectionStringName", accelergreatEnvironmentPipelineData);
}
}
Using an API program class
With the recent introduction of using the program.cs file to replace the startup class, you can now configure your application entirely in Program.cs . The Progam class is now in the global
App Domain as an internal class of the Api assembly. If you are using miniminal apis then you will have to expose InternalsVisibleTo
to the Test Assembly by editing the csproj file of the Api project:
<Project Sdk="Microsoft.NET.Sdk.Web">
...
<ItemGroup>
<InternalsVisibleTo Include="ExampleTestProject" />
</ItemGroup>
...
using System;
using System.Collections.Generic;
using Accelergreat.EntityFramework.Extensions;
using Accelergreat.Environments;
using Accelergreat.Web;
using GuestAndActivities.Data.Contexts;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
namespace ExampleTestProject.Components;
internal class ExampleApiComponent : WebAppComponent<Program>
{
protected override void BuildConfiguration(
IConfigurationBuilder configurationBuilder,
IReadOnlyAccelergreatEnvironmentPipelineData accelergreatEnvironmentPipelineData)
{
configurationBuilder.AddEntityFrameworkDatabaseConnectionString<ExampleDbContext>(
"ExampleConnectionStringName", accelergreatEnvironmentPipelineData);
}
}
Inject the database connection string(s)
In the examples above, we need to provide the database connection string to the Web API configuration a database connection string. We do this by overriding > BuildConfiguration
and calling configurationBuilder.AddEntityFrameworkDatabaseConnectionString
.
3. Create a Startup
class
Create a Startup
class in your test project that implements IAccelergreatStartup
.
we need to register our components. In the Configure
implementation, call builder.AddAccelergreatComponent
for each component as the type parameter.
Important The order in which components are initialized is defined by the order they are registered.
In our example, we need to initialize the database before the web API so that it can access the database connection string.
using Accelergreat.Xunit;
using ExampleTestProject.Components;
namespace ExampleTestProject;
public class Startup : IAccelergreatStartup
{
public void Configure(IAccelergreatBuilder builder)
{
builder.AddAccelergreatComponent<ExampleDatabaseComponent>();
builder.AddAccelergreatComponent<ExampleApiComponent>();
}
}
4. Write your first Accelegreat Integration Test
Now that we've got everything set up, we're going to write our first test.
For this example, we'll also be using FluentAssertions to keep our assertion code clean and easy to read. We'll also follow the Arrange Act Assert (AAA) pattern:
Arrange Set up and insert our test data
Act Call the API endpoint
Assert Validate that the response data is correct
Create a test that that inherits from AccelergreatXunitTest
.
using System.Threading.Tasks;
using Accelergreat.Environments.Pooling;
using Accelergreat.Xunit;
using ExampleTestProject.Components;
using FluentAssertions;
using Newtonsoft.Json;
using Xunit;
namespace ExampleTestProject.Tests;
public class ExampleTests : AccelergreatXunitTest
{
public ExampleTests(IAccelergreatEnvironmentPool environmentPool) : base(environmentPool)
{
}
[Fact]
public async Task Examples_GetById_ReturnsCorrectExample()
{
// Arrange
var exampleEntity = new ExampleEntity();
var dbContextFactory = GetComponent<ExampleDatabaseComponent>().DbContextFactory;
await using (var context = dbContextFactory.NewDbContext())
{
context.Set<ExampleEntity>().Add(exampleEntity);
await context.SaveChangesAsync();
}
var httpClient = GetComponent<ExampleApiComponent>().CreateClient();
// Act
var httpResponseMessage = await httpClient.GetAsync($"examples/{exampleEntity.Id}");
// Assert
httpResponseMessage.IsSuccessStatusCode.Should().BeTrue();
var body = await httpResponseMessage.Content.ReadAsStringAsync();
var result = JsonConvert.DeserializeObject<ExampleEntity>(body)!;
result.Id.Should().Be(exampleEntity.Id);
}
}
Extensibility
To further understand components beyond what the below getting started guide shows, read about all the different components Accelergreat offers and to understand how to build your own components. Please follow this guide.
Configuration
Accelergreat supports the overriding of configuration for managed external dependencies such as databases.
Accelergreat will read the following files in the root level of your test projects that have the CopyToOutputDirectory
setting set to Always
or PreserveNewest
:
accelergreat.json
accelergreat.{environment}.json
accelergreat.{environment}.json
is supported to allow you to have different configurations for your local machine and CI pipeline.
{environment}
is defined by setting an environment variable called ACCELERGREAT_ENVIRONMENT
.
A schema has been provided for the configuration files:
{
"$schema": "https://cdn.accelergreat.net/configuration/3.0.0/schema.json#"
}
Example
The following configuration example shows how a premium developer has set their client ID and client secret, the developer is using the SQL Server Entity Framework component, the developer needs this to work slightly differently in their development and CI environments.
accelergreat.json
{ "$schema": "https://cdn.accelergreat.net/configuration/3.0.0/schema.json", "License": { "ClientId": "YourClientId", "ClientSecret": "YourClientSecret } }
In the development environment, the developer wants to run their application in memory to be able to make use of Visual Studio debugging tools, and also make use of faster database reset speed by using the Transactions reset strategy.
accelergreat.development.json
{ "$schema": "https://cdn.accelergreat.net/configuration/3.0.0/schema.json#", "Infrastructure": { // Custom config "Setup": "InMemory" }, "SqlServerEntityFramework": { "ResetStrategy": "Transactions" } }
In the CI environment, the developer wants to run their tests against the docker container that will be deployed to the hosted environments. In this case, the developer is using IL-trimming in the dotnet publish step of their Dockerfile.
accelergreat.CI.json
{ "$schema": "https://cdn.accelergreat.net/configuration/3.0.0/schema.json#", "Infrastructure": { // Custom config "Setup": "Containers" }, "SqlServerEntityFramework": { "ResetStrategy": "SnapshotRollback" } }
On their local machine, the developer would set the ACCELERGREAT_ENVIRONMENT
environment variable with value development
, in the CI environment, the value would be CI
.
To see other examples, you can look on our GitHub examples repo.
Premium features
Parallel execution
One of the best features of Accelergreat is the ability to have your integration tests run in parallel, gaining massive performance improvements on multi-threaded machines.
It's as easy as config change. In your accelergreat configuration, make sure to add your client id and client secret:
{
"$schema": "https://cdn.accelergreat.net/configuration/3.0.0/schema.json#",
"License": {
"ClientId": "YourClientId",
"ClientSecret": "YourClientSecret"
}
}
Given credentials are provided and authentication is successful, Accelergreat will automatically execute in parallel when the following criteria is met:
- More than 1 test collection is queued for execution.
parallelizeTestCollections
has not been set to false in yourxunit.runner.json
.maxParallelThreads
has not been set to 1 in yourxunit.runner.json
.
By default, Accelergreat uses the max threads allowed from the number of logical processors on the machine. You can override this by setting the maxParallelThreads
property in your xunit.runner.json
configuration file.
Database transactions
Resetting a databse between tests takes time. By default, Accelergreat uses the SnapshotRollback
reset strategy that creates a snapshot of the database before the tests run, and performs a rollback on the database between each test.
The time it takes to reset a database will greatly impact how long it takes the entire test suite to run.
With the premium Transactions
reset strategy, Accelergreat performs magic transaction management and all of your test database changes are made within a single transaction.
If your application uses transactions that is covered by your tests, you can enable TransactionOveriding
and Accelergreat will do even more magic behind the scenes to nest your transactions within Accelergreats transaction.
This paired with the Parallel execution feature will let your tests 'make the jump to light speed' - Han Solo.
Licensing / Pricing
Accelergreat is free to use.
A paid subscription is available for those that want to use premium features.
You can see the plans and pricing here.
Debugging Best Practices
Important When debugging tests in Visual Studio, do not click the stop button. Even if an exception occurs, click continue and let the test run through. If you click the stop button xunit will not run cleanup operations and dependencies will not be disposed of. This is especially important when debugging tests that use database dependencies.
Community & support
Email mail@accelergreat.net for direct communication and support requests.
Join our Discord channel.
See our GitHub.
See our FAQs.
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 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. |
-
net6.0
- Accelergreat (>= 3.0.0)
- Microsoft.Extensions.DependencyInjection (>= 6.0.0)
- Microsoft.Extensions.Logging (>= 6.0.0)
- Microsoft.Extensions.Options.ConfigurationExtensions (>= 6.0.0)
- xunit.extensibility.core (>= 2.6.6)
- xunit.extensibility.execution (>= 2.6.6)
-
net7.0
- Accelergreat (>= 3.0.0)
- Microsoft.Extensions.DependencyInjection (>= 7.0.0)
- Microsoft.Extensions.Logging (>= 7.0.0)
- Microsoft.Extensions.Options.ConfigurationExtensions (>= 7.0.0)
- xunit.extensibility.core (>= 2.6.6)
- xunit.extensibility.execution (>= 2.6.6)
-
net8.0
- Accelergreat (>= 3.0.0)
- Microsoft.Extensions.DependencyInjection (>= 8.0.0)
- Microsoft.Extensions.Logging (>= 8.0.0)
- Microsoft.Extensions.Options.ConfigurationExtensions (>= 8.0.0)
- xunit.extensibility.core (>= 2.6.6)
- xunit.extensibility.execution (>= 2.6.6)
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 |
---|---|---|
3.0.0 | 79 | 7/13/2024 |
3.0.0-beta.2 | 595 | 2/12/2024 |
3.0.0-beta.1 | 54 | 2/9/2024 |
2.3.0-beta | 276 | 1/23/2024 |
2.2.7 | 477 | 9/1/2023 |
2.2.6-beta | 104 | 9/1/2023 |
2.2.5-beta | 84 | 9/1/2023 |
2.2.4 | 136 | 9/1/2023 |
2.2.3-beta | 399 | 3/26/2023 |
2.2.2-beta | 104 | 3/26/2023 |
2.2.1-beta | 125 | 3/25/2023 |
2.2.0-beta | 129 | 3/25/2023 |
2.1.0-beta | 133 | 3/24/2023 |
2.0.0 | 838 | 3/8/2023 |
2.0.0-beta02 | 134 | 3/1/2023 |
2.0.0-beta01 | 133 | 2/1/2023 |
1.7.2-beta | 144 | 10/21/2022 |
1.7.1 | 1,160 | 10/18/2022 |
1.7.0 | 417 | 10/18/2022 |
1.7.0-beta | 133 | 8/28/2022 |
1.6.4 | 634 | 8/27/2022 |
1.6.3-beta | 961 | 8/14/2022 |
1.6.1-beta | 245 | 8/12/2022 |
1.6.0-beta | 175 | 7/18/2022 |
1.5.6-beta | 286 | 7/4/2022 |
1.5.4-beta | 262 | 6/25/2022 |
1.5.3-beta | 141 | 6/24/2022 |
1.5.2-beta | 136 | 6/23/2022 |
1.5.1-beta | 154 | 6/20/2022 |
1.5.0-beta | 129 | 6/20/2022 |
1.4.6 | 503 | 6/8/2022 |
1.4.5-beta | 147 | 5/30/2022 |
1.4.4-beta | 159 | 4/24/2022 |
1.4.3-beta | 152 | 4/23/2022 |
1.4.2 | 463 | 3/15/2022 |
1.4.1-beta | 234 | 3/2/2022 |
1.4.0-beta | 162 | 2/17/2022 |
1.3.6 | 540 | 1/30/2022 |
1.3.5 | 450 | 1/30/2022 |
1.3.2-beta | 163 | 1/27/2022 |
1.3.1-alpha | 156 | 1/25/2022 |
1.3.0-alpha | 143 | 1/25/2022 |
1.2.0 | 455 | 1/23/2022 |