Skip to content

Commit

Permalink
[Docs] Testing (#1608)
Browse files Browse the repository at this point in the history
  • Loading branch information
martintmk authored Sep 22, 2023
1 parent 3ab6f6b commit 29ef55b
Show file tree
Hide file tree
Showing 9 changed files with 156 additions and 133 deletions.
63 changes: 63 additions & 0 deletions docs/advanced/testing.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# Testing

This document explains how to test Polly’s resilience pipelines. You should not test how the resilience pipelines operate internally, but rather test your own settings or custom delegates.

To make the testing process simpler, Polly offers the [`Polly.Testing`](https://www.nuget.org/packages/Polly.Testing/) package. This package has a range of APIs designed to help you test the setup and combination of resilience pipelines in your user code.

## Usage

Begin by adding the `Polly.Testing` package to your test project:

```sh
dotnet add package Polly.Testing
```

Use the `GetPipelineDescriptor` extension method to get the [`ResiliencePipelineDescriptor`](xref:Polly.Testing.ResiliencePipelineDescriptor) which provides details on the pipeline's composition:

<!-- snippet: get-pipeline-descriptor -->
```cs
// Build your resilience pipeline.
ResiliencePipeline pipeline = new ResiliencePipelineBuilder()
.AddRetry(new RetryStrategyOptions
{
MaxRetryAttempts = 4
})
.AddTimeout(TimeSpan.FromSeconds(1))
.Build();

// Retrieve the descriptor.
ResiliencePipelineDescriptor descriptor = pipeline.GetPipelineDescriptor();

// Check the pipeline's composition with the descriptor.
Assert.Equal(2, descriptor.Strategies.Count);

// Verify the retry settings.
var retryOptions = Assert.IsType<RetryStrategyOptions>(descriptor.Strategies[0].Options);
Assert.Equal(4, retryOptions.MaxRetryAttempts);

// Confirm the timeout settings.
var timeoutOptions = Assert.IsType<TimeoutStrategyOptions>(descriptor.Strategies[1].Options);
Assert.Equal(TimeSpan.FromSeconds(1), timeoutOptions.Timeout);
```
<!-- endSnippet -->

The `GetPipelineDescriptor` extension method is also available for the generic `ResiliencePipeline<T>`:

<!-- snippet: get-pipeline-descriptor-generic -->
```cs
// Construct your resilience pipeline.
ResiliencePipeline<string> pipeline = new ResiliencePipelineBuilder<string>()
.AddRetry(new RetryStrategyOptions<string>
{
MaxRetryAttempts = 4
})
.AddTimeout(TimeSpan.FromSeconds(1))
.Build();

// Obtain the descriptor.
ResiliencePipelineDescriptor descriptor = pipeline.GetPipelineDescriptor();

// Check the pipeline's composition with the descriptor.
// ...
```
<!-- endSnippet -->
1 change: 1 addition & 0 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ Polly has a rich documentation that covers various topics, such as:
- [Telemetry and monitoring](advanced/telemetry.md): How to access and analyze the data generated by Polly strategies and pipelines.
- [Dependency injection](advanced/dependency-injection.md): How to integrate Polly with dependency injection frameworks and containers.
- [Performance](advanced/performance.md): Tips on optimizing and getting the best performance from Polly.
- [Testing](advanced/testing.md): How to test the composition and configuration of resilience pipelines.
- [Chaos engineering](advanced/simmy.md): How to use Polly to inject faults and test the resilience of your system.
- [Extensibility](extensibility/index.md): How to create and use custom strategies and extensions for Polly.

Expand Down
2 changes: 2 additions & 0 deletions docs/toc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@
href: advanced/resilience-context.md
- name: Performance
href: advanced/performance.md
- name: Testing
href: advanced/testing.md
- name: Chaos engineering
href: advanced/simmy.md

Expand Down
56 changes: 19 additions & 37 deletions src/Polly.RateLimiting/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,46 +6,28 @@ The `Polly.RateLimiting` package adopts the [.NET Rate Limiting](https://devblog
- It exposes the `AddConcurrencyLimiter` convenience extension methods for `ResiliencePipelineBuilder`.
- It exposes the `RateLimiterRejectedException` class to notify the caller that the operation was rate limited.

Example:
See <https://www.pollydocs.org/strategies/rate-limiter> for more details.

<!-- snippet: rate-limiter-usage -->
```cs
ResiliencePipelineBuilder builder = new ResiliencePipelineBuilder();

// Convenience extension method for ConcurrencyLimiter
builder.AddConcurrencyLimiter(permitLimit: 10, queueLimit: 10);

// Convenience extension method for ConcurrencyLimiter with callback
builder.AddConcurrencyLimiter(
new ConcurrencyLimiterOptions
{
PermitLimit = 10,
QueueLimit = 10
});
## Usage

// Convenience extension method with custom limiter creation
builder.AddRateLimiter(
new ConcurrencyLimiter(new ConcurrencyLimiterOptions
<!-- snippet: rate-limiter -->
```cs
// Add rate limiter with default options.
// See https://www.pollydocs.org/strategies/rate-limiter#defaults for defaults.
new ResiliencePipelineBuilder()
.AddRateLimiter(new RateLimiterStrategyOptions());

// Create a rate limiter to allow a maximum of 100 concurrent executions and a queue of 50.
new ResiliencePipelineBuilder()
.AddConcurrencyLimiter(100, 50);

// Create a rate limiter that allows 100 executions per minute.
new ResiliencePipelineBuilder()
.AddRateLimiter(new SlidingWindowRateLimiter(new SlidingWindowRateLimiterOptions
{
PermitLimit = 10,
QueueLimit = 10
PermitLimit = 100,
Window = TimeSpan.FromMinutes(1)
}));

// Add rate limiter using the RateLimiterStrategyOptions
var limiter = new ConcurrencyLimiter(new ConcurrencyLimiterOptions
{
PermitLimit = 10,
QueueLimit = 10
});

builder.AddRateLimiter(new RateLimiterStrategyOptions
{
RateLimiter = args => limiter.AcquireAsync(1, args.Context.CancellationToken),
OnRejected = _ =>
{
Console.WriteLine("Rate limiter rejected!");
return default;
}
});
```
<!-- endSnippet -->

13 changes: 9 additions & 4 deletions src/Polly.Testing/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

This package exposes APIs and utilities that can be used to assert on the composition of resilience pipelines.

See <https://www.pollydocs.org/advanced/testing> for more details.

## Usage

<!-- snippet: get-pipeline-descriptor -->
```cs
// Build your resilience pipeline.
Expand All @@ -11,19 +15,20 @@ ResiliencePipeline pipeline = new ResiliencePipelineBuilder()
MaxRetryAttempts = 4
})
.AddTimeout(TimeSpan.FromSeconds(1))
.ConfigureTelemetry(NullLoggerFactory.Instance)
.Build();

// Retrieve inner strategies.
// Retrieve the descriptor.
ResiliencePipelineDescriptor descriptor = pipeline.GetPipelineDescriptor();

// Assert the composition.
// Check the pipeline's composition with the descriptor.
Assert.Equal(2, descriptor.Strategies.Count);

// Verify the retry settings.
var retryOptions = Assert.IsType<RetryStrategyOptions>(descriptor.Strategies[0].Options);
Assert.Equal(4, retryOptions.MaxRetryAttempts);

var timeoutOptions = Assert.IsType<TimeoutStrategyOptions>(descriptor.Strategies[0].Options);
// Confirm the timeout settings.
var timeoutOptions = Assert.IsType<TimeoutStrategyOptions>(descriptor.Strategies[1].Options);
Assert.Equal(TimeSpan.FromSeconds(1), timeoutOptions.Timeout);
```
<!-- endSnippet -->
61 changes: 61 additions & 0 deletions src/Snippets/Docs/Testing.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
using Polly.Retry;
using Polly.Testing;
using Polly.Timeout;
using Xunit;

namespace Snippets.Docs;

internal static class Testing
{
public static void GetPipelineDescriptor()
{
#region get-pipeline-descriptor

// Build your resilience pipeline.
ResiliencePipeline pipeline = new ResiliencePipelineBuilder()
.AddRetry(new RetryStrategyOptions
{
MaxRetryAttempts = 4
})
.AddTimeout(TimeSpan.FromSeconds(1))
.Build();

// Retrieve the descriptor.
ResiliencePipelineDescriptor descriptor = pipeline.GetPipelineDescriptor();

// Check the pipeline's composition with the descriptor.
Assert.Equal(2, descriptor.Strategies.Count);

// Verify the retry settings.
var retryOptions = Assert.IsType<RetryStrategyOptions>(descriptor.Strategies[0].Options);
Assert.Equal(4, retryOptions.MaxRetryAttempts);

// Confirm the timeout settings.
var timeoutOptions = Assert.IsType<TimeoutStrategyOptions>(descriptor.Strategies[1].Options);
Assert.Equal(TimeSpan.FromSeconds(1), timeoutOptions.Timeout);

#endregion
}

public static void GetPipelineDescriptorGeneric()
{
#region get-pipeline-descriptor-generic

// Construct your resilience pipeline.
ResiliencePipeline<string> pipeline = new ResiliencePipelineBuilder<string>()
.AddRetry(new RetryStrategyOptions<string>
{
MaxRetryAttempts = 4
})
.AddTimeout(TimeSpan.FromSeconds(1))
.Build();

// Obtain the descriptor.
ResiliencePipelineDescriptor descriptor = pipeline.GetPipelineDescriptor();

// Check the pipeline's composition with the descriptor.
// ...

#endregion
}
}
52 changes: 0 additions & 52 deletions src/Snippets/RateLimiting/Snippets.cs

This file was deleted.

2 changes: 1 addition & 1 deletion src/Snippets/Snippets.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
<ProjectReference Include="..\Polly.Testing\Polly.Testing.csproj" />
<ProjectReference Include="..\Polly\Polly.csproj" />

<Using Include="Polly"/>
<Using Include="Polly" />
</ItemGroup>

</Project>
Expand Down
39 changes: 0 additions & 39 deletions src/Snippets/Testing/Snippets.cs

This file was deleted.

0 comments on commit 29ef55b

Please sign in to comment.