Skip to main content

Configuration

You can customize certain behavior or specify default values to use globally.

All customizations are located in the static Customize.aweXpect class. Groups such as Formatting() bundle related customization values, and each value is stored on its own with a dedicated Get and Set method. The Set method always returns a lifetime scope, an IDisposable that removes the value it set upon disposal.

The customization options are applied in an async context, so they don't directly influence other parallel tests:

using aweXpect.Customization;

using (Customize.aweXpect.Formatting().MaximumStringLength.Set(500))
{
// strings of up to 500 characters are shown in full here
}

Lifetimes and async flows​

A value you set is visible in the current async flow and in every flow that starts from it afterwards, such as a Task.Run. It never reaches a parallel flow or the flow that started the current one.

Lifetimes in async methods and out-of-order disposal
  • A value set in a synchronous method is visible to its caller. A value set in an awaited async method is not: once that method returns, the caller continues with its own values. Set the value in the calling method, or return the lifetime from a synchronous helper method.
  • Disposing a lifetime removes only the value it set, also when the lifetimes are disposed in a different order than they were created: another value, or a later value of the same setting, stays in effect until its own lifetime is disposed. Disposing a lifetime a second time has no effect.
  • Dispose a lifetime in the flow that created it: disposing a lifetime restores the value in the flow that disposes it.

Global defaults​

Most test frameworks don't run the tests in the async context of an assembly-level setup, so a value set there with Set usually does not reach the tests. Set such defaults on Customize.aweXpect.Global instead, which applies them to all async flows, in any assembly-level setup or in a module initializer:

using System.Runtime.CompilerServices;
using aweXpect.Customization;

internal static class AwexpectDefaults
{
[ModuleInitializer]
internal static void Initialize()
=> Customize.aweXpect.Global.Formatting().MaximumStringLength.Set(500);
}
  • A value set in the current async flow takes precedence over its global value, so a test can still use using (Customize.aweXpect.Formatting().MaximumStringLength.Set(20)) without influencing tests that run in parallel. All other values keep following the global values, and once the lifetimes of the value in the current flow are disposed, it follows the global value again.
  • Set global values once, before the tests run. They can be changed at any time and the change is visible to all running tests immediately.
  • Customize.aweXpect.Global.EnableTracing(traceWriter) enables a trace writer for all async flows. A trace writer enabled in the current flow takes precedence.
  • Groups of extension packages, such as Customize.aweXpect.Global.Json(), work the same way.

Equivalency​

Under Customize.aweXpect.Equivalency():

OptionTypeDefaultDescription
DefaultEquivalencyOptionsEquivalencyOptionsnew EquivalencyOptions()The equivalency options that every expectation starts from.

Formatting​

Under Customize.aweXpect.Formatting():

OptionTypeDefaultDescription
MaximumNumberOfCollectionItemsint10The maximum number of items shown for a collection.
MaximumStringLengthint100The maximum length of a shown string before it is truncated.
MinimumNumberOfCharactersAfterStringDifferenceint45The minimum number of characters shown after the first mismatch of a string.

MaximumStringLength applies to formatted values in general, e.g. a string item of a collection or the message of an exception. String expectations always shorten the expected and actual values in the first lines of their failure message to 30 characters, so that these lines stay readable. The difference below them shows the details, e.g. at least MinimumNumberOfCharactersAfterStringDifference characters after the first mismatch.

The items of a collection beyond the maximum are summarized at the end of the list: (… and 7 more) when the total number of items is known, and (… and maybe more) when it is not, e.g. for a lazy sequence or when the expectation stopped enumerating early.

To format your own types, register an IValueFormatter with ValueFormatter.Register(…), which returns an IDisposable that removes it again, see value formatters.

Multi-dimensional arrays

For a multi-dimensional array the maximum number of collection items applies to the items of all dimensions together.

Settings​

Under Customize.aweXpect.Settings():

OptionTypeDefaultDescription
TestCancellationTestCancellationnoneA timeout or CancellationToken that is applied to all expectations.
DefaultCheckIntervalTimeSpan100 msThe interval for re-checking a condition, e.g. for Eventually().
DefaultEventuallyTimeoutTimeSpan30 sHow long Eventually() retries until the expectations must be met.
DefaultRegexTimeoutTimeSpan1 sHow long a wildcard or regex pattern may take to match.
DefaultSignalerTimeoutTimeSpan30 sHow long a Signaler expectation waits without Within(…).
DefaultTimeComparisonToleranceTimeSpan0The tolerance for date and time values without Within(…).
ExcludedAssemblyPrefixesIReadOnlyList<string>see belowThe assemblies that are not scanned for a test framework adapter, matched by name prefix.

See time and cancellation for how to create a TestCancellation.

Timeout.InfiniteTimeSpan retries or waits without a limit. See waiting for which expectations use the timeouts.

The DefaultRegexTimeout protects against catastrophic backtracking. Regex.InfiniteMatchTimeout switches it off. A scope can allow more time for a large subject on a slow build server:

using aweXpect.Customization;

using (Customize.aweXpect.Settings().DefaultRegexTimeout.Set(TimeSpan.FromSeconds(5)))
{
// a wildcard or regex pattern may take up to five seconds to match here
}
tip

On Windows the DateTime resolution is about 10 to 15 milliseconds, so a DefaultTimeComparisonTolerance of about 15 ms avoids brittle comparisons of timestamps.

ExcludedAssemblyPrefixes defaults to mscorlib, System, Microsoft, netstandard, WindowsBase, JetBrains, xunit, TUnit, Castle and DynamicProxyGenAssembly2. Extensions such as aweXpect.Reflection use the same prefixes.

How the prefixes are matched and when they are used

A prefix matches at a segment boundary of the assembly name, so System excludes System.Net.Http, but not an assembly named Systemics. A prefix that ends with a ., e.g. MyCompany., excludes all assemblies whose name starts with it, and an empty prefix excludes nothing. Extensions use the same matching, which AssemblyPrefixes.IsExcluded offers to your own extension.

The test framework detection only uses ExcludedAssemblyPrefixes below .NET 8, see test frameworks.

Tracing​

Customize.aweXpect.EnableTracing(traceWriter) writes which subjects are checked, which expectations were met and which exceptions were thrown to an ITraceWriter. Like any other value, it returns a lifetime that disables the trace writer again, and on Customize.aweXpect.Global it applies to all async flows:

using aweXpect.Customization;

using (Customize.aweXpect.EnableTracing(new ConsoleTraceWriter()))
{
await That(42).IsGreaterThan(40);
}

Customize.aweXpect.Global.EnableTracing(new ConsoleTraceWriter());

class ConsoleTraceWriter : ITraceWriter
{
public void WriteMessage(string message) => Console.WriteLine(message);
public void WriteException(Exception exception) => Console.WriteLine(exception);
}

Extensions​

Extensions can add their own groups. For example, the aweXpect.Json package adds Customize.aweXpect.Json() with the default JsonDocumentOptions and JsonSerializerOptions. See customization values to add a group yourself.