{"id":33900581,"url":"https://github.com/thomhurst/tunit","last_synced_at":"2026-05-29T02:01:21.891Z","repository":{"id":223208851,"uuid":"747691207","full_name":"thomhurst/TUnit","owner":"thomhurst","description":"A modern, fast and flexible .NET testing framework ","archived":false,"fork":false,"pushed_at":"2026-05-23T03:27:08.000Z","size":263744,"stargazers_count":3863,"open_issues_count":20,"forks_count":126,"subscribers_count":19,"default_branch":"main","last_synced_at":"2026-05-23T05:17:29.256Z","etag":null,"topics":["csharp","dotnet","test","testing"],"latest_commit_sha":null,"homepage":"https://tunit.dev/","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/thomhurst.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":".github/CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null},"funding":{"github":["thomhurst"]}},"created_at":"2024-01-24T13:00:36.000Z","updated_at":"2026-05-23T03:25:38.000Z","dependencies_parsed_at":"2024-04-14T19:29:55.558Z","dependency_job_id":"c9178519-3aaf-44c4-9ab9-744b24d9e5f6","html_url":"https://github.com/thomhurst/TUnit","commit_stats":null,"previous_names":["thomhurst/tunit"],"tags_count":1764,"template":false,"template_full_name":null,"purl":"pkg:github/thomhurst/TUnit","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thomhurst%2FTUnit","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thomhurst%2FTUnit/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thomhurst%2FTUnit/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thomhurst%2FTUnit/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/thomhurst","download_url":"https://codeload.github.com/thomhurst/TUnit/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thomhurst%2FTUnit/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33633468,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-05-29T02:00:06.066Z","response_time":107,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["csharp","dotnet","test","testing"],"created_at":"2025-12-11T23:02:47.423Z","updated_at":"2026-05-29T02:01:21.883Z","avatar_url":"https://github.com/thomhurst.png","language":"C#","funding_links":["https://github.com/sponsors/thomhurst"],"categories":[],"sub_categories":[],"readme":"![TUnit](assets/banner.png)\n\n# TUnit\n\nA modern .NET testing framework. Tests are source-generated at compile time, run in parallel by default, and support Native AOT — all built on [Microsoft.Testing.Platform](https://learn.microsoft.com/en-us/dotnet/core/testing/microsoft-testing-platform-intro).\n\n\u003cdiv align=\"center\"\u003e\n\n[![thomhurst%2FTUnit | Trendshift](https://trendshift.io/api/badge/repositories/11781)](https://trendshift.io/repositories/11781)\n\n[![Codacy Badge](https://api.codacy.com/project/badge/Grade/a8231644d844435eb9fd15110ea771d8)](https://app.codacy.com/gh/thomhurst/TUnit?utm_source=github.com\u0026utm_medium=referral\u0026utm_content=thomhurst/TUnit\u0026utm_campaign=Badge_Grade) ![GitHub Repo stars](https://img.shields.io/github/stars/thomhurst/TUnit) ![GitHub Issues or Pull Requests](https://img.shields.io/github/issues-closed-raw/thomhurst/TUnit)\n [![GitHub Sponsors](https://img.shields.io/github/sponsors/thomhurst)](https://github.com/sponsors/thomhurst) [![nuget](https://img.shields.io/nuget/v/TUnit.svg)](https://www.nuget.org/packages/TUnit/) [![NuGet Downloads](https://img.shields.io/nuget/dt/TUnit)](https://www.nuget.org/packages/TUnit/) ![GitHub Workflow Status (with event)](https://img.shields.io/github/actions/workflow/status/thomhurst/TUnit/dotnet.yml) ![GitHub last commit (branch)](https://img.shields.io/github/last-commit/thomhurst/TUnit/main) ![License](https://img.shields.io/github/license/thomhurst/TUnit)\n\n\u003c/div\u003e\n\n## Features\n\n- **Compile-time test discovery** — tests are generated at build time rather than discovered via reflection at runtime, which means faster startup and better IDE integration\n- **Parallel by default** — tests run concurrently; use `[DependsOn]` to express ordering and `[ParallelLimiter]` to cap concurrency\n- **Data-driven testing** — `[Arguments]`, `[Matrix]`, `[ClassData]`, and custom `DataSourceGenerator\u003cT\u003e` sources\n- **Async assertions** with detailed failure messages\n- **Built-in Roslyn analyzers** — catch mistakes at compile time, such as missing `async`, incorrect method signatures, and invalid attribute combinations\n- **Extensible** — write your own skip conditions, retry logic, and attributes\n- **Native AOT \u0026 trimming support**\n- **Lifecycle hooks** — `[Before]` / `[After]` at method, class, assembly, or test session scope\n\n## Getting Started\n\n### Using the Project Template (Recommended)\n```bash\ndotnet new install TUnit.Templates\ndotnet new TUnit -n \"MyTestProject\"\ncd MyTestProject\ndotnet run\n```\n\n### Manual Installation\n```bash\ndotnet add package TUnit\n```\n\n[Getting Started Guide](https://tunit.dev/docs/getting-started/installation) · [Migration Guides](https://tunit.dev/docs/migration/xunit)\n\n## Examples\n\n### Basic test with assertions\n\n```csharp\n[Test]\npublic async Task Parsing_A_Valid_Date_Succeeds()\n{\n    var date = DateTime.Parse(\"2025-01-01\");\n\n    await Assert.That(date.Year).IsEqualTo(2025);\n    await Assert.That(date.Month).IsEqualTo(1);\n}\n```\n\n### Data-driven tests\n\n```csharp\n[Test]\n[Arguments(\"user1@test.com\", \"ValidPassword123\")]\n[Arguments(\"user2@test.com\", \"AnotherPassword456\")]\n[Arguments(\"admin@test.com\", \"AdminPass789\")]\npublic async Task User_Login_Should_Succeed(string email, string password)\n{\n    var result = await authService.LoginAsync(email, password);\n    await Assert.That(result.IsSuccess).IsTrue();\n}\n\n// Matrix — generates a test for every combination (9 total here)\n[Test]\n[MatrixDataSource]\npublic async Task Database_Operations_Work(\n    [Matrix(\"Create\", \"Update\", \"Delete\")] string operation,\n    [Matrix(\"User\", \"Product\", \"Order\")] string entity)\n{\n    await Assert.That(await ExecuteOperation(operation, entity))\n        .IsTrue();\n}\n```\n\n### Hooks, dependencies, and retry\n\n```csharp\n[Before(Class)]\npublic static async Task SetupDatabase(ClassHookContext context)\n{\n    await DatabaseHelper.InitializeAsync();\n}\n\n[Test]\n[MethodDataSource(nameof(GetTestUsers))]\npublic async Task Register_User(string username, string password) { ... }\n\n[Test, DependsOn(nameof(Register_User))]\n[Retry(3)]\npublic async Task Login_With_Registered_User(string username, string password)\n{\n    // Guaranteed to run after Register_User passes\n}\n```\n\n### Custom attributes\n\nExtend built-in base classes to create your own skip conditions, retry logic, and more:\n\n```csharp\npublic class WindowsOnlyAttribute : SkipAttribute\n{\n    public WindowsOnlyAttribute() : base(\"Windows only\") { }\n\n    public override Task\u003cbool\u003e ShouldSkip(TestContext testContext)\n        =\u003e Task.FromResult(!OperatingSystem.IsWindows());\n}\n\n[Test, WindowsOnly]\npublic async Task Windows_Specific_Feature() { ... }\n```\n\nSee the [documentation](https://tunit.dev/docs/getting-started/attributes) for more examples, including custom retry logic and data sources.\n\n## IDE Support\n\n| IDE | Notes |\n|-----|-------|\n| **Visual Studio 2022 (17.13+)** | Works out of the box |\n| **Visual Studio 2022 (earlier)** | Enable \"Use testing platform server mode\" in Tools \u003e Manage Preview Features |\n| **JetBrains Rider** | Enable \"Testing Platform support\" in Settings \u003e Build, Execution, Deployment \u003e Unit Testing \u003e Testing Platform |\n| **VS Code** | Install [C# Dev Kit](https://marketplace.visualstudio.com/items?itemName=ms-dotnettools.csdevkit) and enable \"Use Testing Platform Protocol\" |\n| **CLI** | Works with `dotnet test`, `dotnet run`, and direct execution |\n\n## Packages\n\n| Package | Purpose |\n|---------|---------|\n| `TUnit` | Start here — the full framework (Core + Engine + Assertions) |\n| `TUnit.Core` | Shared test library components without an execution engine |\n| `TUnit.Engine` | Execution engine for test projects |\n| `TUnit.Assertions` | Standalone assertions — works with other test frameworks too |\n| `TUnit.Assertions.Should` | Optional FluentAssertions-style `value.Should().BeEqualTo(...)` syntax over `TUnit.Assertions` (beta) |\n| `TUnit.Mocks` | Source-generated, AOT-compatible mocking framework — works with any test runner |\n| `TUnit.Mocks.Http` | `HttpClient` mocking helpers built on `TUnit.Mocks` |\n| `TUnit.Mocks.Logging` | `ILogger` capture/verification helpers built on `TUnit.Mocks` |\n| `TUnit.AspNetCore` | ASP.NET Core integration — `WebApplicationFactory`-based test fixtures |\n| `TUnit.Aspire` | Aspire integration — distributed app host fixtures with OpenTelemetry capture |\n| `TUnit.Playwright` | Playwright integration with automatic browser lifecycle management |\n\n## Migrating from xUnit, NUnit, or MSTest?\n\nThe syntax will feel familiar. For example, xUnit's `[Fact]` becomes `[Test]`, and `[Theory]` + `[InlineData]` becomes `[Test]` + `[Arguments]`. See the migration guides for full details: [xUnit](https://tunit.dev/docs/migration/xunit) · [NUnit](https://tunit.dev/docs/migration/nunit) · [MSTest](https://tunit.dev/docs/migration/mstest).\n\n## Community\n\n- [Documentation](https://tunit.dev) — guides, tutorials, and API reference\n- [GitHub Discussions](https://github.com/thomhurst/TUnit/discussions) — questions and ideas welcome\n- [Issues](https://github.com/thomhurst/TUnit/issues) — bug reports and feature requests\n- [Changelog](https://github.com/thomhurst/TUnit/releases)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthomhurst%2Ftunit","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fthomhurst%2Ftunit","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthomhurst%2Ftunit/lists"}