Tanaro 0.0.1-alfa.7
dotnet add package Tanaro --version 0.0.1-alfa.7
NuGet\Install-Package Tanaro -Version 0.0.1-alfa.7
<PackageReference Include="Tanaro" Version="0.0.1-alfa.7" />
<PackageVersion Include="Tanaro" Version="0.0.1-alfa.7" />
<PackageReference Include="Tanaro" />
paket add Tanaro --version 0.0.1-alfa.7
#r "nuget: Tanaro, 0.0.1-alfa.7"
#:package Tanaro@0.0.1-alfa.7
#addin nuget:?package=Tanaro&version=0.0.1-alfa.7&prerelease
#tool nuget:?package=Tanaro&version=0.0.1-alfa.7&prerelease
Tanaro
A testing harness for Azure Functions (isolated worker model), inspired by Alba.
Tanaro boots a real IHost from your Function App's own Program.cs (no test seam needed in the app itself),
then lets you invoke individual functions directly and assert on their result, without going through the
Functions runtime or any network hop.
Install
dotnet add package Tanaro
Referencing the package also pulls in a source generator that emits typed scenario methods - no separate analyzer reference required.
Quick start
Program from top-level statements is internal, so your Function App needs to expose it to the test
project via InternalsVisibleTo:
<ItemGroup>
<InternalsVisibleTo Include="YourTestProject" />
</ItemGroup>
Flag your test fixture with [FunctionUnderTest<T>] for every function class you want to exercise, and start
the host from your Function App's Program.
NUnit
Building the FunctionHost is expensive so you only want to do it once per test fixture. The following pattern allows you to reuse your host across tests.
[SetUpFixture]
[FunctionUnderTest<SampleFunctions>]
public class AppUnderTest
{
public static FunctionHost Host { get; private set; } = null!;
[OneTimeSetUp]
public void Setup() => Host = FunctionHost.For<Program>(builder => { }, []);
[OneTimeTearDown]
public void TearDown() => Host.Dispose();
}
The generator emits one scenario method per [Function("Name")] method on SampleFunctions, named after the
function. Call it to invoke the function through DI and assert on its return value:
using Tanaro.DemoFunction;
[Test]
public async Task CountsEvents()
{
var eventData = EventHubsModelFactory.EventData(BinaryData.FromString("x"));
var result = await AppUnderTest.Host.Run<SampleFunctions>()
.SampleTaskOfValue(s => s.Execute([eventData]));
Assert.That(result.Value, Is.EqualTo(1));
}
Execute(...) records the call; WithContext(ctx => ...) lets you inspect or mutate the FunctionContext
(bindings, items, retry context, ...) before the function actually runs.
The function under test is expected to succeed by default - a thrown exception or a middleware short-circuit
fails the scenario immediately via EnsureSuccess(). If you're deliberately testing a failure path, opt out
with s.Execute(...).ExpectFailure() and inspect result.Faulted/result.Exception/result.Invoked yourself.
xUnit
xUnit doesn't have [SetUpFixture]/[OneTimeSetUp], so start the host in an IAsyncDisposable fixture and
share it across tests with an [assembly: AssemblyFixture(...)]:
[assembly: AssemblyFixture(typeof(Tanaro.XUnit.Tests.AppFixture))]
namespace Tanaro.XUnit.Tests;
[FunctionUnderTest<SampleFunctions>]
public class AppFixture : IAsyncDisposable
{
public FunctionHost Host { get; } = FunctionHost.For<Program>(_ => { }, []);
public ValueTask DisposeAsync() => Host.DisposeAsync();
}
Inject the fixture into your test class and call the generated scenario methods the same way:
using Tanaro.DemoFunction;
public class SampleFunctionsScenarioTests(AppFixture fixture)
{
[Fact]
public async Task TaskOfValueShape()
{
var eventData = EventHubsModelFactory.EventData(BinaryData.FromString("x"));
var result = await fixture.Host.Run<SampleFunctions>().SampleTaskOfValue(s => s.Execute([eventData]));
Assert.Equal(1, result.Value);
}
}
AI Stance
Tanaro isn't vibe-coded. We use a mix of regular coding and agent-assisted work, but people make the design decisions. Every change is reviewed, understood, and validated by a person before it lands.
We don't mind contributors using agents either, as long as their contributions follow the contributing guide. The rule is simple: you vibe it, you own it. If you submit a change, you must understand it, stand behind it, and be able to explain, test, and fix it. The contribution is yours, not the tool's, so we don't accept generative AI tools as authors or co-authors.
Please don't submit AI slop. Generic, unreviewed, or needlessly verbose generated issues, pull request descriptions, or review comments will be immediately closed when they create more work than value.
(Generously stolen from Oskar Dudycz)
Name
Tanaro is the river running trough the city of Alba, Italy. Since this project is inspired by the Alba testing framework, that seemed like a good name.
And yes, I know that library is named after Alba, Missouri.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- Microsoft.Azure.Functions.Worker (>= 2.52.0)
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 |
|---|---|---|
| 0.0.1-alfa.7 | 108 | 10/2/2026 |
| 0.0.1-alfa.6 | 107 | 9/23/2026 |
| 0.0.1-alfa.5 | 69 | 9/23/2026 |
| 0.0.1-alfa.4 | 62 | 9/23/2026 |
| 0.0.1-alfa.3 | 127 | 9/22/2026 |
| 0.0.1-alfa.2 | 60 | 9/22/2026 |
| 0.0.1-alfa.1 | 76 | 9/22/2026 |