<< All versions
Skill v1.0.0
currentTrusted Publisher100/100microsoft/accordant/quickref
──Details
PublishedOctober 1, 2026 at 05:01 AM
Content Hashsha256:44fc6062a1123903...
Git SHA
──Files
Files (1 file, 6.3 KB)
SKILL.md6.3 KBactive
SKILL.md · 276 lines · 6.3 KB
version: "1.0.0" name: accordant-quickref description: Quick reference and cheatsheet for Accordant API - use this skill for quick syntax lookup or code snippets
Accordant Quick Reference
State Definition
csharp
[State]public partial class MyState{public Dictionary<string, decimal> Balances { get; set; } = new();public Dictionary<string, UserState> Users { get; set; } = new();}[State]public partial class UserState{public string Name { get; set; } = string.Empty;public List<string> Tags { get; set; } = new();}
Create a Spec
csharp
var spec = new Spec<MyState>().WithJsonPrinters(); // Optional: nice logging
Define Operations
Inline Syntax
csharp
spec.Operation<TRequest, TResponse>("OperationName", (request, state) =>{// Return ExpectedOutcomes});
Examples
csharp
// Simple request (single value)spec.Operation<string, ApiResult<User>>("GetUser", (userId, state) => { ... });// Tuple request (multiple values)spec.Operation<(string Id, decimal Amount), ApiResult<decimal>>("Deposit", (request, state) =>{var (id, amount) = request; // Destructure// ...});// Class-based requestspec.Operation<CreateUserRequest, ApiResult<User>>("CreateUser", (request, state) => { ... });
Expected Outcomes
Basic Expectation
csharp
Expect.That<TResponse>(response => /* predicate */)
With Explanation (Recommended)
csharp
Expect.That<ApiResult<decimal>>(r => r.IsSuccess && r.Data == expectedValue,$"Expected success with value {expectedValue}")
With ValidationResult
csharp
Expect.That<User>(response =>{if (response.Name != expected)return ValidationResult.Invalid($"Name mismatch: {response.Name}");return ValidationResult.Valid();})
Exception Expectation
csharp
Expect.Throws<NotFoundException>("Resource not found")
Multiple Valid Outcomes
csharp
Expect.OneOf(Expect.That<T>(r => /* outcome 1 */).ThenState(...),Expect.That<T>(r => /* outcome 2 */).SameState(),Expect.That<T>(r => /* outcome 3 */).ThenState(...))
State Transitions
No Change
csharp
.SameState()
State Changes
csharp
.ThenState<MyState>(nextState => nextState.Items[id] = newValue)
Response-Dependent State
csharp
.ThenState<MyState>((TResponse response, MyState nextState) =>nextState.Items[response.Id] = new Item { ... },mock: () => new TResponse { Id = Guid.NewGuid().ToString() })
Async Operations
csharp
.ThenState<MyState>(next => next.Jobs[id] = JobStatus.Pending).Triggers(AsyncOperation.Create<MyState>(isTerminal: s => s.Jobs[id] != JobStatus.Pending,transitions: new Action<MyState>[] {next => next.Jobs[id] = JobStatus.Completed,next => next.Jobs[id] = JobStatus.Failed}))
Bind Execution
csharp
spec.ExecuteWith<ApiClient>().Bind<TRequest, TResponse>("OperationName",(client, request) => client.Method(request).Result).BindAsync<TRequest, TResponse>("AsyncOperation",async (client, request) => await client.MethodAsync(request));
Test Generation
Define Inputs
csharp
var inputs = new InputSet{spec.GetOperation<string, ApiResult<User>>("CreateUser").With("alice", "Create Alice"),spec.GetOperation<(string, decimal), ApiResult<decimal>>("Deposit").With(("alice", 100m), "Deposit 100"),};
Generate Tests
csharp
var testCases = spec.GenerateTests(initialState, inputs, new TestGenerationOptions{MaxDepth = 5,StateConstraint = state => ((MyState)state).Items.Count <= 3});
Run Tests
csharp
var context = spec.CreateTestingContext();context.Register(new ApiClient(httpClient));var results = await spec.RunTests(context, initialState, testCases, new TestExecutionOptions{BeforeEachAsync = async _ => await ResetDatabase()});Assert.That(results.All(r => r.Success));
Concurrent Tests
csharp
var concurrentTestCases = spec.GenerateConcurrentTests(initialState, inputs,new TestGenerationOptions { MaxDepth = 4 });var results = await spec.RunTests(context, initialState, concurrentTestCases,new TestExecutionOptions { ... });
Manual Conformance Testing
csharp
var stateProfile = new StateProfile(initialState);var response = await client.CreateUser("alice");(bool isValid, string message, stateProfile) =spec.Allows(createUserOp, "alice", response, stateProfile);Assert.IsTrue(isValid, message);
Visualization
csharp
var dot = spec.VisualizeStateSpace(initialState, inputs, options);File.WriteAllText("graph.dot", dot);// Convert: dot -Tpng graph.dot -o graph.png
TestGenerationOptions
| Option | Type | Default | Description | |
|---|---|---|---|---|
MaxDepth | int | 5 | Max sequence length | |
StateConstraint | Func<State, bool> | null | Prune states | |
MaxConcurrencyLevel | int | 3 | Concurrent ops | |
SequentialTestCaseAlgorithm | delegate | StateCoverage | Walk algorithm |
Test Case Algorithms
csharp
// State coverage (default)SequentialTestCaseAlgorithms.StateCoverage// Transition coverageSequentialTestCaseAlgorithms.CreateTransitionCoverage(maxSequenceLength: 4)// Random walkSequentialTestCaseAlgorithms.CreateRandomWalk(numberOfWalks: 100, maxWalkLength: 8, seed: 42)
Common Operation Pattern
csharp
spec.Operation<(string Id, decimal Amount), ApiResult<decimal>>("Withdraw", (request, state) =>{var (accountId, amount) = request;// Guard 1: Resource exists?if (!state.Accounts.TryGetValue(accountId, out var balance))return Expect.That<ApiResult<decimal>>(r => r.IsNotFound, "Account not found").SameState();// Guard 2: Business ruleif (balance < amount)return Expect.That<ApiResult<decimal>>(r => r.IsBadRequest, "Insufficient funds").SameState();// Success pathvar newBalance = balance - amount;return Expect.That<ApiResult<decimal>>(r => r.IsSuccess && r.Data == newBalance,$"Expected new balance {newBalance}").ThenState<BankState>(next => next.Accounts[accountId] = newBalance);});
Namespace
csharp
using Microsoft.Accordant;
NuGet Package
bash
dotnet add package Microsoft.Accordant