ExtrabbitCode.Inventor.Testbench.UI
0.2.3
dotnet add package ExtrabbitCode.Inventor.Testbench.UI --version 0.2.3
NuGet\Install-Package ExtrabbitCode.Inventor.Testbench.UI -Version 0.2.3
<PackageReference Include="ExtrabbitCode.Inventor.Testbench.UI" Version="0.2.3" />
<PackageVersion Include="ExtrabbitCode.Inventor.Testbench.UI" Version="0.2.3" />
<PackageReference Include="ExtrabbitCode.Inventor.Testbench.UI" />
paket add ExtrabbitCode.Inventor.Testbench.UI --version 0.2.3
#r "nuget: ExtrabbitCode.Inventor.Testbench.UI, 0.2.3"
#:package ExtrabbitCode.Inventor.Testbench.UI@0.2.3
#addin nuget:?package=ExtrabbitCode.Inventor.Testbench.UI&version=0.2.3
#tool nuget:?package=ExtrabbitCode.Inventor.Testbench.UI&version=0.2.3
Inventor Testbench: writing real tests
Inventor Testbench lets an addin repository own one ordinary .NET test project. The compiled DLL is loaded by the Testbench desktop app and can contain fast logic tests, tests running inside Inventor through COM, Windows UI Automation tests, and later AI-assisted reviews.
1. Choose the packages
The packages are on nuget.org; no extra feed is needed. Every project references the core package:
<PackageReference Include="ExtrabbitCode.Inventor.Testbench" Version="0.2.1" />
Add the UI package only when the assembly contains UI tests:
<PackageReference Include="ExtrabbitCode.Inventor.Testbench.UI" Version="0.2.1" />
<PackageReference Include="Autodesk.Inventor.Sdk" Version="2.0.1" />
Add Autodesk.Inventor.Sdk directly when test source uses Inventor COM types; its build targets select the interop reference. Consumers do not reference the Testbench runner or desktop app.
Or from the command line:
dotnet add package ExtrabbitCode.Inventor.Testbench --version 0.2.1
dotnet add package ExtrabbitCode.Inventor.Testbench.UI --version 0.2.1
dotnet add package Autodesk.Inventor.Sdk --version 2.0.1
Testing against unreleased changes
Only needed when working on Testbench itself. Pack from the Testbench repository and register the output as a local feed:
dotnet pack .\ExtrabbitCode.Inventor.Testbench.Packages.slnx -c Debug
dotnet nuget add source C:\path\to\Inventor.Testbench\artifacts\packages `
--name local-inventor-testbench
Local builds carry the version from VersionPrefix in Directory.Build.props,
so reference that version to pick them up ahead of the published ones.
2. Create a test project
For a project containing UI tests, use this complete .csproj:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0-windows10.0.19041.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="ExtrabbitCode.Inventor.Testbench" Version="0.2.1" />
<PackageReference Include="ExtrabbitCode.Inventor.Testbench.UI" Version="0.2.1" />
<PackageReference Include="Autodesk.Inventor.Sdk" Version="2.0.1" />
<ProjectReference Include="..\..\src\MyInventorAddin\MyInventorAddin.csproj" />
</ItemGroup>
<ItemGroup>
<Content Include="fixtures\**\*" CopyToOutputDirectory="PreserveNewest" />
</ItemGroup>
</Project>
CopyLocalLockFileAssemblies is important for plugin loading: it puts UI and other NuGet dependencies beside the test DLL so Inventor can resolve them.
Suggested layout:
MyAddin/
src/MyInventorAddin/
tests/MyInventorAddin.Testbench/
LogicTests.cs
InventorApiTests.cs
AddinUiTests.cs
fixtures/
parts/Bracket.ipt
assemblies/Gearbox/Gearbox.iam
assemblies/Gearbox/Gear.ipt
3. Understand the four test kinds
| Marker | Runs where | Use it for |
|---|---|---|
[InventorFact] |
Local Testbench process | filename rules, configuration, validation, planning and other pure .NET logic |
[InventorApiFact] |
Inside the selected Inventor version | documents, iProperties, parameters, BOM, geometry, translators and addin services using COM |
[InventorUiFact] |
Inside Inventor with interactive desktop access | ribbon buttons, dialogs, dock panes, keyboard/focus and combined UI + COM assertions |
[InventorAiFact] |
Reserved AI category | visual or exploratory review; provider execution is not wired yet, so mark these skipped today |
UI tests are normally combined tests: they drive the visible addin UI and then verify the result through context.InventorApplication, documents, or generated files.
4. Fast logic test
using ExtrabbitCode.Inventor.Testbench.Abstractions;
public sealed class ExportNameTests
{
[InventorFact("Export names contain no Windows-invalid characters",
Tags = ["export", "naming", "fast"])]
public void Export_name_is_safe()
{
string result = MyExportNames.Create("1001", "Bracket");
TestbenchAssert.Equal("1001-Bracket.step", result);
TestbenchAssert.False(result.IndexOfAny(Path.GetInvalidFileNameChars()) >= 0);
}
}
Logic tests do not need Inventor and should contain most validation, parsing, configuration, and planning behavior.
5. Inventor COM test
using ExtrabbitCode.Inventor.Testbench.Abstractions;
public sealed class PropertyTests
{
[InventorApiFact("Tracking ID round-trips through a part",
Tags = ["iproperty", "smoke"],
Versions = ["2025", "2026", "2027"])]
public void Tracking_id_round_trips(InventorTestContext context)
{
context.RequireInventor();
Inventor.PartDocument part = context.CreateTempPartDocument();
part.SetCustomProperty("TrackingId", "TB-1001");
context.WaitForIdle();
TestbenchAssert.Equal("TB-1001", part.GetCustomPropertyText("TrackingId"));
context.Output.WriteLine($"Document: {part.DisplayName}");
}
}
Versions is optional. With no value the test is eligible for 2025, 2026, and 2027. When values are declared, Testbench runs it only for those selected versions.
6. Test an existing Inventor fixture safely
Fixtures are never opened in place. OpenPartFixture, OpenAssemblyFixture, and the other typed helpers first copy the file into the test working directory.
[InventorApiFact("Bracket material remains Steel",
Fixture = "parts/Bracket.ipt",
Tags = ["fixture", "material"])]
public void Bracket_material_is_steel(InventorTestContext context)
{
Inventor.PartDocument part = context.OpenPartFixture();
TestbenchAssert.Equal("Steel", part.ActiveMaterial.DisplayName);
}
For an assembly with referenced parts, copy its entire fixture directory first:
[InventorApiFact("Gearbox opens with all references", Tags = ["assembly"])]
public void Gearbox_references_resolve(InventorTestContext context)
{
string directory = context.CopyFixtureDirectoryToTemp("assemblies/Gearbox");
string assemblyPath = Path.Combine(directory, "Gearbox.iam");
Inventor.AssemblyDocument assembly = context.Adapter.OpenFixture<Inventor.AssemblyDocument>(assemblyPath);
TestbenchAssert.True(assembly.AllReferencedDocuments.Count > 0);
}
7. UI + COM test for an addin
using ExtrabbitCode.Inventor.Testbench.Abstractions;
using ExtrabbitCode.Inventor.Testbench.UI;
using FlaUI.Core.Definitions;
public sealed class ExportDialogTests
{
[InventorUiFact("Export button opens the dialog and exports STEP",
Fixture = "assemblies/Gearbox/Gearbox.iam",
Tags = ["ui", "export", "combined"])]
public void Export_button_creates_step(InventorTestContext context)
{
Inventor.AssemblyDocument assembly = context.OpenAssemblyFixture();
using InventorUiSession ui = InventorUiSession.Attach(context);
ui.RequireByName("Export", ControlType.Button).AsButton().Invoke();
var dialog = ui.WaitForWindow("Export");
string expected = context.ArtifactPath("Gearbox.step");
ui.SetTextByName("Output file", expected);
dialog.FindFirstDescendant(cf => cf.ByName("Export"))!.AsButton().Invoke();
TestbenchWait.UntilAsync(
() => File.Exists(expected),
description: "STEP export").GetAwaiter().GetResult();
context.AddFileArtifact(expected, "step-export");
TestbenchAssert.True(new FileInfo(expected).Length > 0);
context.AddArtifacts(ui.CaptureDiagnostics(context.TestWorkingDirectory, "export-complete"));
}
}
Prefer Automation ID where the addin exposes one; otherwise use accessible name plus control type. Avoid screen coordinates. Always verify functional success through COM or the output file rather than a screenshot alone.
8. Output, waits, and artifacts
Frequently used helpers:
context.Output.WriteLine("Readable trace shown in Testbench");
await TestbenchWait.UntilAsync(() => condition, TimeSpan.FromSeconds(15));
string path = context.ArtifactPath("result.pdf");
context.AddFileArtifact(path, "pdf");
context.AddArtifacts(ui.CaptureDiagnostics(context.TestWorkingDirectory, "failure-state"));
Registered files are copied into the permanent result directory before the temporary test directory is deleted. They appear in JUnit and in the Testbench details panel.
9. Build and load the DLL
dotnet build .\tests\MyInventorAddin.Testbench
In the Testbench app:
- Select Add test DLL in the left sidebar.
- Choose
tests\MyInventorAddin.Testbench\bin\Debug\net8.0-windows10.0.19041.0\MyInventorAddin.Testbench.dll. - Use the Logic, Inventor, UI, or AI tab to inspect one category.
- Select one or more installed Inventor versions for Inventor/UI tests.
- Run the full filtered category or use the play button on one test row.
- Inspect trace output, duration, per-version result badges, artifacts, JUnit, or source code.
The fixture root for an external DLL defaults to a fixtures directory beside that DLL. Copy fixtures to output as shown in the project file, or keep an output-side fixtures folder.
9b. Display an existing xunit suite
Addin repositories usually already own an xunit test project. Testbench can host those suites without a rewrite:
- Adding a DLL that references
xunit.corecreates a suite in dotnet test mode. Discovery reads[Fact]/[Theory]metadata without loading the assembly, so the suite may target a newer framework (e.g. net10) than the app. - Running shells out to
dotnet test <dll>and reads the JUnit report back. The test project must reference theJunitXml.TestLoggerNuGet package. - A class-level
[Collection]name or a trait containing "inventor" marks a test as Inventor kind for the tab filters; everything else counts as Logic.
The app can also be launched preloaded from another repository:
ExtrabbitCode.Inventor.Testbench.App.exe --add-assembly C:\repo\tests\bin\...\MyAddin.Tests.dll
--add-assembly is repeatable, persists like picker-added DLLs, and preselects
the first suite. The same run works headless via the CLI:
dotnet run --project .\src\ExtrabbitCode.Inventor.Testbench.Console -- dotnet-run --assembly <dll> [--filter <fqn-substring>]
10. AI visual review with your model provider
[InventorAiFact] has its own Testbench tab. Testbench defines IAiVisualReviewer but deliberately does not own credentials or force a model vendor. Implement the interface in the test project using your OpenAI, Azure, or local-model client:
[InventorAiFact("No controls overlap at 150% DPI", Tags = ["ai", "visual"])]
public async Task Dialog_has_no_visual_defects(InventorTestContext context)
{
using InventorUiSession ui = InventorUiSession.Attach(context);
string image = ui.CaptureDiagnostics(context.TestWorkingDirectory, "dialog")
.First(artifact => artifact.Kind == "ui-screenshot").Path;
IAiVisualReviewer reviewer = new CompanyVisualReviewer(
Environment.GetEnvironmentVariable("AI_API_KEY")!);
await context.ReviewImageAsync(
reviewer,
image,
"Approve only if labels are readable and no controls overlap or clip.");
}
The helper persists the structured result as an ai-review JSON artifact, writes findings to trace, and fails when Approved is false. Pass requireApproval: false while introducing advisory reviews. The concrete CompanyVisualReviewer is application-specific because authentication, data-retention policy, model choice, and endpoint ownership belong to the consuming organization.
Practical test pyramid
- Put parsing, naming, configuration, and validation into many
[InventorFact]tests. - Use
[InventorApiFact]for the smaller set that proves Inventor document behavior. - Use
[InventorUiFact]only for interaction surfaces that COM cannot exercise. - Use
[InventorAiFact]for visual/exploratory residue, backed by deterministic evidence.
This keeps the suite fast and stable while still testing what users actually see.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0-windows10.0.19041 is compatible. net9.0-windows was computed. net10.0-windows was computed. |
-
net8.0-windows10.0.19041
- ExtrabbitCode.Inventor.Testbench (>= 0.2.3)
- FlaUI.Core (>= 5.0.0)
- FlaUI.UIA2 (>= 5.0.0)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.