Class Spec<TState>
A Spec contains the list of operations that define the behavior of a stateful system. Each operation is registered under a unique name.
public class Spec<TState> : ISpec where TState : class, IState
Type Parameters
TStateThe type of state the spec operates on.
- Inheritance
-
Spec<TState>
- Implements
- Inherited Members
Properties
this[string]
The indexer property can be used to register operations under a given name and retrieve them given the registered name.
public IOperation this[string name] { get; set; }
Parameters
namestring
Property Value
Operations
The operations registered in this spec.
public IEnumerable<IOperation> Operations { get; }
Property Value
Methods
Add(IOperation)
Registers an IOperation with this spec.
public void Add(IOperation operation)
Parameters
operationIOperationThe operation to register.
Allows(IOperation, object, object, StateProfile)
Validates whether the spec allows the observed response for the given operation, request, and state profile. This non-generic overload accepts object types for request and response, useful when the caller doesn't know the exact types at compile time.
public (bool IsValid, string Message, StateProfile UpdatedStateProfile) Allows(IOperation operation, object request, object response, StateProfile stateProfile)
Parameters
operationIOperationThe operation that was invoked.
requestobjectThe request that was sent.
responseobjectThe observed response from the system.
stateProfileStateProfileThe state profile representing possible states before the operation.
Returns
- (bool IsValid, string Message, StateProfile UpdatedStateProfile)
A tuple of (isValid, explanationMessage, updatedStateProfile).
Allows(IOperation, object, object, TState)
Validates whether the spec allows the observed response for the given operation, request, and state. This non-generic overload accepts object types for request and response, useful when the caller doesn't know the exact types at compile time.
public (bool IsValid, string Message, StateProfile UpdatedStateProfile) Allows(IOperation operation, object request, object response, TState state)
Parameters
operationIOperationThe operation that was invoked.
requestobjectThe request that was sent.
responseobjectThe observed response from the system.
stateTStateThe state the system was in before the operation.
Returns
- (bool IsValid, string Message, StateProfile UpdatedStateProfile)
A tuple of (isValid, explanationMessage, updatedStateProfile).
AllowsConcurrent(StateProfile, IList<(IOperation operation, object request, object response)>)
Validates whether the spec allows the observed responses for a set of operations that were invoked concurrently. If the responses can be explained by some logical ordering of the operations, returns the updated state profile. If not, returns an explanation message.
public (bool IsValid, string Message, StateProfile UpdatedStateProfile) AllowsConcurrent(StateProfile stateProfile, IList<(IOperation operation, object request, object response)> concurrentCalls)
Parameters
stateProfileStateProfileThe state profile representing possible states before the concurrent operations.
concurrentCallsIList<(IOperation operation, object request, object response)>The list of concurrent operation calls with their requests and responses.
Returns
- (bool IsValid, string Message, StateProfile UpdatedStateProfile)
A tuple of (isValid, explanationMessage, updatedStateProfile).
Allows<TRequest, TResponse>(Operation<TRequest, TResponse, TState>, TRequest, object, StateProfile)
Validates whether the spec allows the observed response for the given operation, request, and state profile. If valid, returns the updated state profile reflecting any state transitions. If not valid, returns an explanation message.
public (bool IsValid, string Message, StateProfile UpdatedStateProfile) Allows<TRequest, TResponse>(Operation<TRequest, TResponse, TState> operation, TRequest request, object response, StateProfile stateProfile)
Parameters
operationOperation<TRequest, TResponse, TState>The operation that was invoked.
requestTRequestThe request that was sent.
responseobjectThe observed response from the system.
stateProfileStateProfileThe state profile representing possible states before the operation.
Returns
- (bool IsValid, string Message, StateProfile UpdatedStateProfile)
A tuple of (isValid, explanationMessage, updatedStateProfile).
Type Parameters
TRequestThe type of request.
TResponseThe type of response.
Allows<TRequest, TResponse>(Operation<TRequest, TResponse, TState>, TRequest, object, TState)
Validates whether the spec allows the observed response for the given operation, request, and state. If valid, returns the updated state profile reflecting any state transitions. If not valid, returns an explanation message.
public (bool IsValid, string Message, StateProfile UpdatedStateProfile) Allows<TRequest, TResponse>(Operation<TRequest, TResponse, TState> operation, TRequest request, object response, TState state)
Parameters
operationOperation<TRequest, TResponse, TState>The operation that was invoked.
requestTRequestThe request that was sent.
responseobjectThe observed response from the system.
stateTStateThe state the system was in before the operation.
Returns
- (bool IsValid, string Message, StateProfile UpdatedStateProfile)
A tuple of (isValid, explanationMessage, updatedStateProfile).
Type Parameters
TRequestThe type of request.
TResponseThe type of response.
ConfigureDerivations(string, params RequestDerivation[])
Configures request derivations for an inline operation. This allows inline operations to have derivations without needing a class-based definition.
public Spec<TState> ConfigureDerivations(string operationName, params RequestDerivation[] derivations)
Parameters
operationNamestringThe name of the operation to configure derivations for.
derivationsRequestDerivation[]The derivations to set for this operation.
Returns
- Spec<TState>
This spec for fluent chaining.
Examples
spec.Operation<(string, string), ApiResult<Todo>>("GetTodo", (req, state) => { ... });
spec.ConfigureDerivations("GetTodo",
Derive.From<Todo, ApiResult<Todo>, (string, string)>("CreateTodo")
.When((req, resp) => resp.IsSuccess)
.As((req, resp) => (resp.Data.UserId, resp.Data.TodoId)));
Exceptions
- InvalidOperationException
Thrown if the operation is not an inline operation (class-based operations should override DerivedFrom instead).
ConfigurePolling(string, PollingSetup)
Configures polling for an inline operation. This allows inline operations to have polling without needing a class-based definition.
public Spec<TState> ConfigurePolling(string operationName, PollingSetup polling)
Parameters
operationNamestringThe name of the operation to configure polling for.
pollingPollingSetupThe polling setup for this operation.
Returns
- Spec<TState>
This spec for fluent chaining.
Examples
spec.Operation<string, ApiResult<Job>>("CreateJob", (req, state) => { ... });
spec.ConfigurePolling("CreateJob", new PollingSetup
{
Operation = "GetJob",
WaitTimeInMs = 100,
MaxRetryCount = 100
});
Exceptions
- InvalidOperationException
Thrown if the operation is not an inline operation (class-based operations should override Polling instead).
CreateTestingContext(string)
Creates a new TestingContext for this spec.
public TestingContext CreateTestingContext(string testDirectoryPath = null)
Parameters
testDirectoryPathstringOptional path for test output.
Returns
- TestingContext
A new testing context.
ExecuteWith<TTarget>()
Creates an ExecuteBuilder<TTarget, TState> for binding execution logic to operations in this spec.
public ExecuteBuilder<TTarget, TState> ExecuteWith<TTarget>()
Returns
- ExecuteBuilder<TTarget, TState>
An ExecuteBuilder<TTarget, TState> for fluent binding.
Type Parameters
TTargetThe type of the system under test.
GenerateConcurrentTests(TState, InputSet, TestGenerationOptions)
Generates concurrent test cases from the given inputs.
public IList<ConcurrentTestCase> GenerateConcurrentTests(TState initialState, InputSet inputs, TestGenerationOptions options = null)
Parameters
initialStateTStateThe initial state for test generation.
inputsInputSetThe input set containing operation inputs to use.
optionsTestGenerationOptionsAdditional test generation options.
Returns
- IList<ConcurrentTestCase>
A list of concurrent test cases.
GenerateTests(TState, InputSet, TestGenerationOptions)
Generates sequential test cases from the given inputs.
public IList<SequentialTestCase> GenerateTests(TState initialState, InputSet inputs, TestGenerationOptions options = null)
Parameters
initialStateTStateThe initial state for test generation.
inputsInputSetThe input set containing operation inputs to use.
optionsTestGenerationOptionsAdditional test generation options.
Returns
- IList<SequentialTestCase>
A list of sequential test cases.
GetOperation(string)
This method returns the operation registered under the given name.
public IOperation GetOperation(string name)
Parameters
namestring
Returns
GetOperationName(IOperation)
This method returns the name the given operation was registered under.
public string GetOperationName(IOperation operation)
Parameters
operationIOperation
Returns
GetOperation<TRequest, TResponse>(string)
Gets a typed operation by name.
public Operation<TRequest, TResponse, TState> GetOperation<TRequest, TResponse>(string name)
Parameters
namestringThe name of the operation.
Returns
- Operation<TRequest, TResponse, TState>
The typed operation.
Type Parameters
TRequestThe request type.
TResponseThe response type.
Operation<TRequest, TResponse>(string, Func<TRequest, TState, ExpectedOutcomes>)
Creates and registers an inline operation using a lambda expression. Returns the spec for fluent chaining.
public Spec<TState> Operation<TRequest, TResponse>(string name, Func<TRequest, TState, ExpectedOutcomes> apply)
Parameters
namestringThe name of the operation.
applyFunc<TRequest, TState, ExpectedOutcomes>The function that defines the operation's behavior.
Returns
- Spec<TState>
This spec for fluent chaining.
Type Parameters
TRequestThe type of request.
TResponseThe type of response.
RegisterOperation(string, IOperation)
This method registers the given operation under the given name.
public void RegisterOperation(string name, IOperation operation)
Parameters
namestringoperationIOperation
RegisterOperationProperties()
Automatically registers all public properties that implement IOperation. Call this in the derived Spec constructor after initializing operation properties.
protected void RegisterOperationProperties()
RunTests(TestingContext, TState, IList<ConcurrentTestCase>, TestExecutionOptions)
Runs the given concurrent test cases.
public Task<IList<TestCaseExecutionResult>> RunTests(TestingContext context, TState initialState, IList<ConcurrentTestCase> testCases, TestExecutionOptions options = null)
Parameters
contextTestingContextThe testing context with registered services.
initialStateTStateThe initial state for each test.
testCasesIList<ConcurrentTestCase>The test cases to run.
optionsTestExecutionOptionsExecution options.
Returns
- Task<IList<TestCaseExecutionResult>>
The execution results.
RunTests(TestingContext, TState, IList<SequentialTestCase>, TestExecutionOptions)
Runs the given sequential test cases.
public Task<IList<TestCaseExecutionResult>> RunTests(TestingContext context, TState initialState, IList<SequentialTestCase> testCases, TestExecutionOptions options = null)
Parameters
contextTestingContextThe testing context with registered services.
initialStateTStateThe initial state for each test.
testCasesIList<SequentialTestCase>The test cases to run.
optionsTestExecutionOptionsExecution options.
Returns
- Task<IList<TestCaseExecutionResult>>
The execution results.
VisualizeStateSpace(TState, InputSet, TestGenerationOptions, VisualizationOptions)
Generates a GraphViz DOT visualization of the state space explored during test generation. This is useful for understanding how test cases are generated and debugging state transitions.
public string VisualizeStateSpace(TState initialState, InputSet inputs, TestGenerationOptions generationOptions = null, VisualizationOptions visualizationOptions = null)
Parameters
initialStateTStateThe initial state for visualization.
inputsInputSetThe input set containing operation inputs to use.
generationOptionsTestGenerationOptionsTest generation options that control state space exploration.
visualizationOptionsVisualizationOptionsOptions for customizing the visualization output.
Returns
- string
A string containing the GraphViz DOT file content.
WithJsonPrinters()
Configures JSON serialization for both request and response logging. Uses System.Text.Json with default options.
public Spec<TState> WithJsonPrinters()
Returns
- Spec<TState>
This spec for fluent chaining.
WithRequestPrinter(Func<object, string>)
Configures a custom request printer for logging during test execution.
public Spec<TState> WithRequestPrinter(Func<object, string> printer)
Parameters
Returns
- Spec<TState>
This spec for fluent chaining.
WithResponsePrinter(Func<object, string>)
Configures a custom response printer for logging during test execution.
public Spec<TState> WithResponsePrinter(Func<object, string> printer)
Parameters
Returns
- Spec<TState>
This spec for fluent chaining.