FlaUIQATouch 1.1.5

dotnet tool install --global FlaUIQATouch --version 1.1.5
                    
This package contains a .NET tool you can call from the shell/command line.
dotnet new tool-manifest
                    
if you are setting up this repo
dotnet tool install --local FlaUIQATouch --version 1.1.5
                    
This package contains a .NET tool you can call from the shell/command line.
#tool dotnet:?package=FlaUIQATouch&version=1.1.5
                    
nuke :add-package FlaUIQATouch --version 1.1.5
                    

FlaUIQATouch (C#)

NuGet License: MIT

QA Touch reporter for FlaUI (.NET desktop UI automation via NUnit / MSTest).
Reads NUnit3 XML or TRX result files produced by dotnet test / nunit-console
and automatically creates modules, test cases, and a test run in QA Touch.
Ships as a single NuGet package — usable both as a library reference and a dotnet tool CLI.


Table of Contents


Features

  • Parses NUnit3 XML and TRX (MSTest / VSTest) result files
  • Auto-creates modules (test suites) in QA Touch from test class names
  • Auto-creates test cases with pre-built step templates
  • Creates a test run and uploads all results in one go
  • Supports bulk result upload with automatic fallback to individual uploads
  • Attaches error messages as comments on failed test results
  • Resolves or creates milestones automatically
  • Single package — works as both a NuGet library and a dotnet tool CLI
  • Targets .NET 8.0+ (compatible with .NET 8, 9, 10, and later)
  • Built-in 429 rate-limit retry with exponential backoff (3 retries, 500ms base)
  • Input validation — clear errors for missing or empty configuration

Prerequisites

  • .NET SDK 8.0 or later (for building / CLI)
  • A QA Touch account with:
    • Your subdomain (e.g. mycompany from mycompany.qatouch.com)
    • An API token (Settings > API Token in QA Touch)
    • A project key (visible in QA Touch project URL)
    • A user key for test run assignment

Install

dotnet tool install --global FlaUIQATouch

This gives you the flaui-qatouch-upload command.

As a Library Reference

dotnet add package FlaUIQATouch

For programmatic use in your .NET 8.0+ projects.


Quick Start

# 1. Run your FlaUI tests and produce results
dotnet test --logger "nunit;LogFilePath=TestResults/results.xml"

# 2. Upload results to QA Touch
flaui-qatouch-upload \
  --results TestResults/results.xml \
  --domain mycompany \
  --token YOUR_API_TOKEN \
  --project PROJ \
  --assign user-key

# 3. Or upload as BDD (Gherkin) test cases
flaui-qatouch-upload \
  --results TestResults/results.xml \
  --domain mycompany \
  --token YOUR_API_TOKEN \
  --project PROJ \
  --assign user-key \
  --bdd

Library Usage

Add the NuGet package to your project, then use FlaUIQATouchReporter to upload results programmatically:

using FlaUIQATouch;

// Configure the reporter
using var reporter = new FlaUIQATouchReporter(new FlaUIQATouchReporterOptions
{
    Domain        = "mycompany",                          // QA Touch subdomain
    ApiToken      = "YOUR_API_TOKEN",                     // QA Touch API token
    ProjectKey    = "PROJ",                               // QA Touch project key
    AssignTo      = "user-key",                           // user key for test run
    ResultsFile   = @".\TestResults\results.xml",         // NUnit3 XML or .trx
    MilestoneName = "Sprint 12",                          // auto-created if missing
    Tag           = "flaui",                              // tag on the test run
});

// Parse results + create modules/cases/run + upload
await reporter.RunAsync();

Example: BDD Mode

Set BddMode = true to create missing test cases as BDD (Gherkin) scenarios via the QA Touch /testCase/bdd endpoint instead of the standard step-based endpoint:

using FlaUIQATouch;

using var reporter = new FlaUIQATouchReporter(new FlaUIQATouchReporterOptions
{
    Domain      = "mycompany",
    ApiToken    = "YOUR_API_TOKEN",
    ProjectKey  = "PROJ",
    AssignTo    = "user-key",
    ResultsFile = @".\TestResults\results.xml",
    BddMode     = true,   // <-- creates BDD cases with Gherkin scenarios
});

await reporter.RunAsync();

Each auto-created test case will contain a Gherkin scenario like:

Scenario: Verify instrument name is displayed
GIVEN the application is launched and ready
WHEN I execute the test: Verify instrument name is displayed
THEN it should complete successfully

Example: Post-test upload in a console app

// UploadResults.csproj — a small console app
using FlaUIQATouch;

var options = new FlaUIQATouchReporterOptions
{
    Domain      = Environment.GetEnvironmentVariable("QATOUCH_DOMAIN")!,
    ApiToken    = Environment.GetEnvironmentVariable("QATOUCH_TOKEN")!,
    ProjectKey  = Environment.GetEnvironmentVariable("QATOUCH_PROJECT")!,
    AssignTo    = Environment.GetEnvironmentVariable("QATOUCH_ASSIGN")!,
    ResultsFile = args.Length > 0 ? args[0] : "TestResults/results.xml",
};

using var reporter = new FlaUIQATouchReporter(options);
await reporter.RunAsync();
dotnet test --logger "nunit;LogFilePath=TestResults/results.xml"
dotnet run --project UploadResults.csproj -- TestResults/results.xml

CLI Usage

flaui-qatouch-upload --results <path> --domain <domain> --token <token>
                     --project <key> --assign <user-key> [options]

Examples

# NUnit3 XML results
flaui-qatouch-upload \
  --results TestResults/results.xml \
  --domain mycompany \
  --token abc123 \
  --project PROJ \
  --assign user-key

# TRX results with custom milestone
flaui-qatouch-upload \
  --results TestResults/results.trx \
  --domain mycompany \
  --token abc123 \
  --project PROJ \
  --assign user-key \
  --milestone-name "Release 2.0" \
  --tag regression

# BDD mode — create Gherkin scenarios in QA Touch
flaui-qatouch-upload \
  --results TestResults/results.xml \
  --domain mycompany \
  --token abc123 \
  --project PROJ \
  --assign user-key \
  --bdd

# Use an existing module and milestone (skip auto-creation)
flaui-qatouch-upload \
  --results results.xml \
  --domain mycompany \
  --token abc123 \
  --project PROJ \
  --assign user-key \
  --testsuite MOD-123 \
  --milestone-key MIL-456 \
  --no-create-cases

CLI Help

flaui-qatouch-upload --help

Configuration Options

Library Options (FlaUIQATouchReporterOptions)

Property Type Default Required Description
Domain string Yes QA Touch subdomain (e.g. mycompany)
ApiToken string Yes QA Touch API token
ProjectKey string Yes QA Touch project key
AssignTo string Yes User key to assign the test run to
ResultsFile string Yes Path to NUnit3 XML or TRX file
TestsuiteId string? null No Fixed module key (skips auto-creation of modules)
MilestoneName string "FlaUI Automation" No Milestone name (reused if exists, created if not)
MilestoneKey string? null No Existing milestone key (skips milestone lookup/creation)
CreateCases bool true No Auto-create test cases that don't exist in QA Touch
BddMode bool false No Create missing test cases as BDD (Gherkin) type instead of step-based
Tag string "flaui" No Tag applied to the test run

CLI Arguments

Argument Required Description
--results <path> Yes Path to NUnit3 XML or TRX results file
--domain <domain> Yes QA Touch subdomain
--token <token> Yes QA Touch API token
--project <key> Yes QA Touch project key
--assign <user-key> Yes User key to assign the test run
--testsuite <key> No Fixed module key (skips auto-create)
--milestone-name <name> No Milestone name (default: "FlaUI Automation")
--milestone-key <key> No Existing milestone key (skips creation)
--tag <tag> No Tag applied to the test run (default: "flaui")
--no-create-cases No Do not auto-create missing test cases
--bdd No Create missing test cases as BDD (Gherkin) type
--help, -h No Show help message

Supported Result Formats

Format How to Produce File Extension
NUnit3 XML dotnet test --logger "nunit;LogFilePath=results.xml" .xml
NUnit3 XML nunit-console --result=results.xml .xml
TRX (MSTest/VSTest) dotnet test --logger "trx;LogFileName=results.trx" .trx

Note: For NUnit3 XML output with dotnet test, install the NUnit3TestAdapter and NunitXml.TestLogger NuGet packages in your test project.


How It Works

The reporter follows this workflow when RunAsync() is called:

  1. Parse — Reads the results file and extracts test names, suite names, statuses, and error messages
  2. Resolve modules — Groups tests by suite name; looks up existing modules in QA Touch or creates new ones
  3. Resolve test cases — Matches parsed test names to existing QA Touch test cases (by normalized title); creates missing cases with step templates if CreateCases is true
  4. Resolve milestone — Uses the provided MilestoneKey, or finds/creates a milestone by MilestoneName
  5. Create test run — Creates a new test run in QA Touch linked to the milestone with all mapped case keys
  6. Upload results — Posts results in bulk; failed tests with error messages are uploaded individually with comments; falls back to individual uploads on bulk failure

Status Mapping

Test Result QA Touch Status Status ID
Passed passed 1
Failed / Error failed 5
Ignored / Inconclusive / NotRunnable blocked 3
Other untested 2

BDD Mode

BDD Mode changes how missing test cases are created in QA Touch. Instead of creating standard step-based test cases, it uses the QA Touch BDD API (POST /testCase/bdd) to create cases with Gherkin scenarios.

When to Use BDD Mode

  • Your tests follow BDD / Given-When-Then patterns
  • You want test cases in QA Touch to display as Gherkin scenarios
  • You're writing behavior-driven FlaUI tests with descriptive names

How It Works

  1. Parsing — Test results are parsed the same way as standard mode (NUnit3 XML or TRX)
  2. Module resolution — Modules are created/matched identically to standard mode
  3. Case creation — When a test case doesn't exist in QA Touch and CreateCases is true:
    • Standard mode: Creates a case with pre-built steps via POST /testCase
    • BDD mode: Creates a case with a Gherkin scenario via POST /testCase/bdd
  4. Result upload — Works identically in both modes

Generated Gherkin Format

For each test, the reporter generates a scenario from the test name:

Scenario: <test title>
GIVEN the application is launched and ready
WHEN I execute the test: <test title>
THEN it should complete successfully

For example, a test named GivenAppIsLaunched_WhenMainWindowAppears_ThenTitleIsVisible produces:

Scenario: GivenAppIsLaunched_WhenMainWindowAppears_ThenTitleIsVisible
GIVEN the application is launched and ready
WHEN I execute the test: GivenAppIsLaunched_WhenMainWindowAppears_ThenTitleIsVisible
THEN it should complete successfully

API Payload

The BDD endpoint receives:

Field Value
projectKey Your project key
sectionKey Module key (auto-resolved from test suite name)
caseTitle Test name
feature_script The generated Gherkin scenario
description "BDD Scenario: <test title>"
reference Full test name (namespace + class + method)

Enable BDD Mode

CLI:

flaui-qatouch-upload --results results.xml --domain myco --token xxx \
  --project PROJ --assign ukey --bdd

Library:

new FlaUIQATouchReporterOptions { BddMode = true, /* ... */ }

PowerShell script (if using the upload helper):

.\upload-to-qatouch.ps1 -Domain myco -Token xxx -ProjectKey PROJ -AssignTo ukey -Bdd

Note: BDD mode only affects newly created test cases. Existing cases in QA Touch are matched by title and left unchanged. Result uploads work the same way regardless of mode.


Project Structure

flaUIQATouchCSharp/
├── FlaUIQATouch.sln                          # Solution file
├── LICENSE                                    # MIT License
├── README.md                                  # This file
└── src/
    └── FlaUIQATouch/                          # Single NuGet package (net8.0)
        ├── FlaUIQATouch.csproj
        ├── Program.cs                         # CLI entry point (flaui-qatouch-upload)
        ├── QATouchClient.cs                   # HTTP client for QA Touch REST API
        ├── ResultParser.cs                    # NUnit3 XML & TRX parser
        └── FlaUIQATouchReporter.cs            # Main reporter (orchestrates everything)

CI/CD Examples

GitHub Actions

name: FlaUI Tests + QA Touch

on: [push, pull_request]

jobs:
  test:
    runs-on: windows-latest
    steps:
      - uses: actions/checkout@v4

      - name: Setup .NET
        uses: actions/setup-dotnet@v4
        with:
          dotnet-version: '8.0.x'

      - name: Run FlaUI tests
        run: dotnet test --logger "nunit;LogFilePath=TestResults/results.xml"

      - name: Install QA Touch CLI
        run: dotnet tool install --global FlaUIQATouch

      - name: Upload results to QA Touch
        if: always()
        run: |
          flaui-qatouch-upload --results TestResults/results.xml `
            --domain ${{ secrets.QATOUCH_DOMAIN }} `
            --token ${{ secrets.QATOUCH_TOKEN }} `
            --project ${{ secrets.QATOUCH_PROJECT }} `
            --assign ${{ secrets.QATOUCH_ASSIGN }}

      # Or use --bdd to create Gherkin scenarios in QA Touch:
      # - name: Upload results to QA Touch (BDD)
      #   if: always()
      #   run: |
      #     flaui-qatouch-upload --results TestResults/results.xml `
      #       --domain ${{ secrets.QATOUCH_DOMAIN }} `
      #       --token ${{ secrets.QATOUCH_TOKEN }} `
      #       --project ${{ secrets.QATOUCH_PROJECT }} `
      #       --assign ${{ secrets.QATOUCH_ASSIGN }} `
      #       --bdd

Azure DevOps

trigger:
  - main

pool:
  vmImage: 'windows-latest'

steps:
  - task: UseDotNet@2
    inputs:
      version: '8.0.x'

  - script: dotnet test --logger "nunit;LogFilePath=TestResults/results.xml"
    displayName: 'Run FlaUI tests'

  - script: dotnet tool install --global FlaUIQATouch
    displayName: 'Install QA Touch CLI'

  - script: >
      flaui-qatouch-upload
      --results TestResults/results.xml
      --domain $(QATOUCH_DOMAIN)
      --token $(QATOUCH_TOKEN)
      --project $(QATOUCH_PROJECT)
      --assign $(QATOUCH_ASSIGN)
    displayName: 'Upload results to QA Touch'
    condition: always()

  # Or use --bdd to create Gherkin scenarios in QA Touch:
  # - script: >
  #     flaui-qatouch-upload
  #     --results TestResults/results.xml
  #     --domain $(QATOUCH_DOMAIN)
  #     --token $(QATOUCH_TOKEN)
  #     --project $(QATOUCH_PROJECT)
  #     --assign $(QATOUCH_ASSIGN)
  #     --bdd
  #   displayName: 'Upload results to QA Touch (BDD)'
  #   condition: always()

API Reference

FlaUIQATouchReporter

Member Description
FlaUIQATouchReporter(FlaUIQATouchReporterOptions options) Creates a new reporter instance
Task RunAsync() Parses results, resolves/creates QA Touch entities, and uploads results
void Dispose() Disposes the underlying HTTP client

ResultParser

Member Description
static List<ParsedTest> ParseResultsFile(string filePath) Auto-detects NUnit3 XML or TRX and parses test results
static string NormalizeTitle(string title) Normalizes a test name for matching (lowercase, alphanumeric + spaces)

QATouchClient

Member Description
Task<List<JsonElement>> GetTestCasesAsync(string? moduleKey) Retrieves test cases (paginated)
Task CreateTestCaseAsync(...) Creates a test case with steps
Task<JsonElement> CreateBddTestCaseAsync(...) Creates a BDD test case with a Gherkin feature_script via /testCase/bdd
Task<List<JsonElement>> GetModulesAsync() Retrieves all modules (paginated)
Task<JsonElement> CreateModuleAsync(string name, string? parentKey) Creates a module
Task<List<JsonElement>> GetMilestonesAsync() Retrieves all milestones
Task CreateMilestoneAsync(string name) Creates a milestone
Task<JsonElement> CreateTestRunAsync(...) Creates a test run with specific cases
Task<JsonElement> UpdateResultsAsync(string runKey, List<BulkResult> results) Bulk-updates test run results
Task<JsonElement> AddResultWithCommentAsync(...) Adds a single result with optional comment and screenshot

Troubleshooting

Issue Solution
Unrecognised results format Ensure the file is valid NUnit3 XML (<test-run>) or TRX (<TestRun>)
No test cases found Check that the results file contains <test-case> (NUnit) or <UnitTestResult> (TRX) elements
API Error 401 Verify your ApiToken and Domain are correct
API Error 404 Verify the ProjectKey exists in your QA Touch account
Unable to resolve milestone key Check that your QA Touch plan supports milestones
Unmapped: <test name> The test name didn't match any QA Touch case; enable CreateCases or check title normalization
CLI not found after install Ensure ~/.dotnet/tools is in your PATH
API Error 429 Rate-limited — the built-in retry (3 attempts, exponential backoff) should handle this automatically
ArgumentException on startup A required option (Domain, ApiToken, ProjectKey) is empty or null

Changelog

1.1.4

  • Fix: GetTestCasesAsync() pagination now uses deduplication instead of per_page-based stop condition. The API returns variable item counts per page, which caused pagination to stop at page 1 even when more pages existed.
  • Fix: moduleKey query parameter is silently ignored by the /getAllTestCases API. Filtering by module is now done client-side using item.module_key.

License

MIT — see LICENSE for details.

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  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. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

This package has no dependencies.

Version Downloads Last Updated
1.1.5 1,249 4/28/2026
1.1.4 302 4/8/2026
1.1.2 153 4/6/2026
1.1.1 143 4/3/2026
1.1.0 123 4/3/2026
1.0.1 309 4/1/2026
1.0.0 115 4/1/2026