Neue App hinzufügen

Registriere deine zu testende Anwendung (AUT) in GlobalConfig, wähle das passende Plattform-Tool, und prüfe, dass sie aufgelöst wird, bevor du auch nur einen Control modellierst.

← Zurück zur Übersicht · 🇬🇧 English · ← Konzepte · Controls hinzufügen →


Entscheide, welches Plattform-Tool zu deiner App passt

Jede zu testende Anwendung (AUT) ist ein Eintrag in GlobalConfig.apps — ein type+tool-Paar, das dem Framework sagt, über welche Runtime-Strategy es Aufrufe auflöst. Wähle die Zeile, die zu deiner App passt:

Deine App ist … type tool Status
eine Web-App (browser-gerendert) 'Web' 'Playwright' Verfügbar
eine Windows-Desktop-App 'Desktop' 'Appium-Windows' Verfügbar
eine macOS-Desktop-App 'Desktop' 'Mac2' Typ definiert, noch nicht ausgeliefert
eine Android-App 'Mobile' 'UiAutomator2' Typ definiert, noch nicht ausgeliefert
eine iOS-App 'Mobile' 'XCUITest' Typ definiert, noch nicht ausgeliefert

💡 Was “Typ definiert, noch nicht ausgeliefert” bedeutet. Die AppConfig-Union hat bereits eine Form für macOS-/Android-/iOS-Einträge — TypeScript akzeptiert sie, nichts hindert dich daran, sie zu schreiben. Aber für Mac2/UiAutomator2/XCUITest ist heute keine Runtime-Strategy registriert: die erste Action oder Check gegen so einen Eintrag schlägt zur Laufzeit fehl mit StrategyRegistry: No factory registered for tool "...". Siehe FAQ für den aktuellen Stand. Web und Windows-Desktop sind die beiden Plattformen mit einer echten Runtime dahinter — der Rest dieser Seite behandelt beide.


Registriere eine Web-App

Füge einen Eintrag zu 2_Apps/1_Global/GlobalConfig.ts hinzu — die minimale Form braucht nur type, tool und baseUrl:

// 2_Apps/1_Global/GlobalConfig.ts
export const apps = {
    DeineApp: {
        type: 'Web',
        tool: 'Playwright',
        baseUrl: 'https://<deine-app-domain>',
    },
} as const;

Ein realistischer Eintrag trennt die URL meist in eine eigene Konstante, damit ein Wechsel zwischen Staging und Produktion nur eine Zeile statt das ganze Objekt berührt:

// 2_Apps/1_Global/GlobalConfig.ts
export const URL_DEINE_APP = process.env.DEINE_APP_URL ?? 'https://staging.<deine-app-domain>';

export const apps = {
    DeineApp: {
        type: 'Web',
        tool: 'Playwright',
        baseUrl: URL_DEINE_APP,
        headless: true,
    },
} as const;

headless spielt nur eine Rolle, wenn ein Control oder ein eigenständiger Inspector-Lauf einen Browser selbst bootstrapped, ohne eine injizierte Playwright-Page — ein TestCase über die normale Playwright-Test-Runner-Fixture ignoriert es. Sobald der Eintrag existiert, löst Core.defineExecutionStep('DeineApp', 'Start', (env) => ...) env.page/env.url automatisch daraus auf — siehe TestSteps bauen.

Scaffolde eine Web-App automatisch per CLI

Die Schritte oben — _Skeleton kopieren, den App-Namen-Platzhalter ersetzen, den GlobalConfig.apps-Eintrag hinzufügen, die globale Barrel-Datei verdrahten — gibt es auch als einen einzigen Befehl:

npx cc-testframework create-web-app --name DemoWeb --url http://localhost:8080

Das kopiert das mitgelieferte _Skeleton-Template (12 Controls, TS_Main/TS_Dialog/TS_Message/TS_Execution/TS_Custom plus ihre .i18n.json-Kataloge) nach 2_Apps/<N>_DemoWeb/<N> ist der nächste freie Nummern-Präfix, automatisch aus deinen bestehenden 2_Apps/-Ordnern ermittelt —, ersetzt jeden __APP_NAME__-Platzhalter in den kopierten Dateien durch DemoWeb, und fügt den passenden Eintrag zu 2_Apps/1_Global/GlobalConfig.ts hinzu:

// 2_Apps/1_Global/GlobalConfig.ts
export const apps = {
    DemoWeb: {
        type: 'Web',
        tool: 'Playwright',
        baseUrl: 'http://localhost:8080',
    },
} as const;

Danach verdrahtet er die App zusätzlich in 2_Apps/1_Global/References.ts — die globale Barrel-Datei, über die jeder TestCase importiert (import * as Project from '@GlobalRef') —, sodass Project.DemoWeb.* sofort importierbar ist, ohne manuelle Bearbeitung:

// 2_Apps/1_Global/References.ts
export * as DemoWeb from '../2_DemoWeb/References';

Die Re-Export-Zeile übernimmt dabei den Import-Stil, den deine Barrel-Datei bereits überwiegend nutzt — einen relativen Pfad wie oben gezeigt, oder @Apps/2_DemoWeb/References, wenn deine bestehenden App-Zeilen bereits diese Path-Alias-Form verwenden.

Flag Pflicht Beschreibung
--name <Name> Ja Der App-Name — ein gültiger Identifier (Buchstaben, Ziffern, Unterstrich; darf nicht mit einer Ziffer beginnen). Wird sowohl als Suffix des 2_Apps/<N>_<Name>/-Ordners als auch als apps-/Barrel-Export-Schlüssel verwendet.
--url <url> Ja Basis-URL der zu testenden Anwendung — http://, https:// oder file://.
--project-dir <pfad> Nein Projekt-Root, der 2_Apps/ enthält (standardmäßig automatisch erkannt — der Befehl sucht ausgehend von deinem aktuellen Verzeichnis aufwärts nach 2_Apps/1_Global/GlobalConfig.ts unter ., ./pm und ./tests).
--dry-run Nein Zeigt den Plan — Zielordner, Dateien, die geschrieben würden, den GlobalConfig.ts-Eintrag und den References.ts-Plan — ohne die Festplatte anzufassen.
--json Nein Gibt zusätzlich zur menschenlesbaren Ausgabe eine maschinell parsbare JSON-Zusammenfassung aus (inklusive eines referencesUpdated-Felds, siehe unten), für Skripting oder CI.
--help Nein Zeigt die Verwendung.

Der Befehl beendet sich bei Erfolg mit Exit-Code 0, bei einem Anwenderfehler mit 2 (ungültiges --name/--url, kein Projekt-Root gefunden, oder das Ziel bereits registriert). Er ist idempotent: er verweigert das Überschreiben eines bestehenden 2_Apps/<N>_<Name>/-Ordners oder eines doppelten apps-Schlüssels, und er lässt References.ts unangetastet, wenn ein Re-Export für diesen Namen bereits existiert — ein erneuter Lauf gegen eine bereits gescaffoldete App schlägt also sicher fehl, statt etwas zu überschreiben.

Das referencesUpdated-Feld der --json-Zusammenfassung berichtet, was mit der Barrel-Datei passiert ist: true (die Re-Export-Zeile wurde geschrieben), false (nichts zu schreiben — die App hatte bereits eine, oder es existiert gar keine Barrel-Datei) oder "skipped-example" für den unten beschriebenen Pre-Onboarding-Fall.

💡 Der eine Fall, der noch einen manuellen Schritt braucht. Ist die globale Barrel-Datei deines Projekts noch die nicht aktivierte 2_Apps/1_Global/References.ts.example (seit dem Scaffolden nie umbenannt oder ausgefüllt), überspringt der Befehl die Barrel-Verdrahtung sanft — er fasst eine .example-Datei nie an — und gibt die genaue Re-Export-Zeile aus, die du nach der Aktivierung hinzufügst. Benenne References.ts.example in References.ts um, fülle die darin beschriebenen Pflicht-Re-Exports aus, und füge dann die ausgegebene Zeile selbst hinzu. Das ist das einzige Szenario, in dem Project.DemoWeb.* nicht sofort nach Abschluss des Befehls importierbar ist.

Führe ihn zuerst mit --dry-run aus, um genau zu sehen, was auf die Festplatte geschrieben würde (und wie der References.ts-Plan aussieht), ohne etwas zu schreiben:

npx cc-testframework create-web-app --name DemoWeb --url http://localhost:8080 --dry-run

💡 Baust du stattdessen gegen eine Windows-Desktop-AUT? Siehe Scaffolde eine Desktop-App automatisch per CLI weiter unten — das Appium-Windows-Pendant zu diesem Befehl, derselbe Workflow.

Registriere eine Electron-App

Eine Electron-App — Rechner-artige, gepackte Desktop-Apps, die auf Electron aufbauen, oder jede App, die du selbst darauf baust — ist eine Web-App, getestet über Playwright, keine Desktop-App, getestet über Appium. Ihre Oberfläche ist ein Chromium-Renderer, reines DOM, kein nativer UIA-Baum — sie wird also mit demselben type/tool-Paar registriert wie eine Browser-Web-App. Der einzige Unterschied ist, wie die App gestartet wird: executablePath zeigt auf die ausführbare Datei der gepackten App, statt dass baseUrl eine URL zum Öffnen bekommt.

💡 Ein-Befehl-Abkürzung. npx cc-testframework create-electron-app --name <DeineApp> --executable-path <pfad> scaffoldet und registriert das in einem Schritt — siehe Neue App scaffolden — Electron-App.

// 2_Apps/1_Global/GlobalConfig.ts
export const apps = {
    MeineElectronApp: {
        type: 'Web',
        tool: 'Playwright',
        executablePath: 'C:\\Pfad\\zu\\MeineElectronApp.exe', // die .exe der gepackten Electron-App
        // args: ['--flag'], // optionale Start-Argumente
    },
} as const;

type bleibt 'Web', tool bleibt 'Playwright' — es ist ein einziges Config-Shape, keine separate Typ-/Tool-Kombination. Ob executablePath (statt baseUrl) gesetzt ist, entscheidet, ob der Eintrag als Electron erkannt wird.

Eine Electron-App wird aus ihrem eigenen, dedizierten _Skeleton_Electron-Root gescaffoldet, nicht aus dem Browser-_Skeleton. Ihre Lifecycle-Steps tragen dieselben schlichten Namen wie eine Browser-Web-App — TS_Execution_Start/_Close/_Restart —, da eine gescaffoldete App immer genau eine der beiden Varianten ist (Browser-Web oder Electron), nie beide gleichzeitig — es gibt also keine Namenskollision zu vermeiden und keinen *Electron-Suffix. Diese Steps rufen intern Core.I_ElectronHandler auf, der den Prozess über Playwrights _electron.launch() statt chromium.launch() startet und danach das erste Fenster der App als Session-Page verwendet.

💡 Nach dem Start ist es eine normale Web-Page. Sobald TS_Execution_Start gelaufen ist, ist das Electron-Fenster eine gewöhnliche Playwright-Page — ein Chromium-gerendertes DOM. Jeder bestehende Web-Control und jeder TS_Main/TS_Dialog/TS_Message-Step funktioniert unverändert dagegen; es gibt keine separate, Electron-spezifische Control-API zu lernen.

Voraussetzung: executablePath muss auf die .exe (oder das plattform-äquivalente Binary) der gepackten Electron-App zeigen, auf der Maschine, die den Testprozess ausführt — dieselbe App, die du sonst per Doppelklick öffnen würdest.


Registriere eine Windows-Desktop-App

💡 Electron-basierte Windows-App? Registriere sie stattdessen als Web-App — siehe Registriere eine Electron-App oben. Ihre Oberfläche ist ein Chromium-DOM, kein nativer UIA-Baum, sie läuft also über Playwright, nicht über Appium/WinAppDriver.

Eine Windows-Desktop-AUT braucht einen executable-Pfad statt einer baseUrl, plus optional eine appiumUrl für den Appium-/WinAppDriver-Server:

// 2_Apps/1_Global/GlobalConfig.ts
export const apps = {
    DeineDesktopApp: {
        type: 'Desktop',
        tool: 'Appium-Windows',
        executable: 'C:\\Users\\Public\\<DeineApp>\\<DeineApp>.exe',
        appiumUrl: 'http://host.docker.internal:4723',
    },
} as const;
  • executable ist der absolute Pfad, den WinAppDriver als appium:app-Capability übergibt — er muss auf der Maschine existieren, auf der der Appium-Server selbst läuft, nicht zwingend auf der, die den Testprozess ausführt.
  • appiumUrl ist optional. Lässt du sie weg, löst das Framework einen sinnvollen Default über eine dreistufige Prioritätskette auf (expliziter Wert → Umgebungsvariable APPIUM_URL → Plattform-Default) — siehe API-Referenz — Sektion 14 und FAQ für die vollständige Kette und Troubleshooting.
  • capabilities akzeptiert ein optionales Record<string, unknown>, das über die Default-WinAppDriver-Capabilities des Frameworks gemerged wird, für alles App-Spezifische, das die beiden Felder oben nicht abdecken.

Scaffolde eine Desktop-App automatisch per CLI

Das Desktop-Pendant zu create-web-app — derselbe Ein-Befehl-Workflow, aber für eine Appium-Windows-Desktop-AUT statt einer Playwright-Web-AUT:

npx cc-testframework create-desktop-app --name DemoDesktop --executable "C:\apps\Demo.exe"
  create-web-app create-desktop-app
Kopiertes Skeleton _Skeleton _Skeleton_Desktop
Ziel-Flag --url <url> --executable <pfad> (+ optional --appium-url <url>)
GlobalConfig.apps-Eintrag type: 'Web', tool: 'Playwright', baseUrl type: 'Desktop', tool: 'Appium-Windows', executable, appiumUrl
Skeleton-Inhalt 12 Controls, TS_Main/Dialog/Message/Execution/Custom 12 Controls, TS_Main/Dialog/Message/Execution (kein TS_Custom)

Das kopiert das mitgelieferte _Skeleton_Desktop-Template nach 2_Apps/<N>_DemoDesktop/ — dieselbe automatische Nummern-Präfix-Ermittlung und __APP_NAME__-Substitution wie bei create-web-app — und fügt den passenden Eintrag zu GlobalConfig.ts hinzu:

// 2_Apps/1_Global/GlobalConfig.ts
export const apps = {
    DemoDesktop: {
        type: 'Desktop',
        tool: 'Appium-Windows',
        executable: 'C:\\apps\\Demo.exe',
        appiumUrl: 'http://host.docker.internal:4723',
    },
} as const;

Er verdrahtet 2_Apps/1_Global/References.ts genau wie create-web-app — dasselbe Alias-Stil-Mirroring, dieselbe Idempotenz, derselbe .example-Pre-Onboarding-Soft-Skip — siehe Scaffolde eine Web-App automatisch per CLI oben für die vollständige Erklärung dieses Mechanismus; sie wird hier nicht wiederholt.

Flag Pflicht Beschreibung
--name <Name> Ja Dieselbe Regel wie bei create-web-app — ein gültiger Identifier, verwendet als Ordner-Suffix und als apps-/Barrel-Export-Schlüssel.
--executable <pfad> Ja Pfad zur .exe der App auf dem Appium-/Windows-Host, nicht auf der Maschine, die diesen Befehl ausführt — wird nicht gegen das lokale Dateisystem geprüft.
--appium-url <url> Nein Appium-Server-URL. Default: http://host.docker.internal:4723 (der Devcontainer→Windows-Host-Default).
--project-dir <pfad> Nein Wie bei create-web-app.
--dry-run Nein Wie bei create-web-app — zeigt den Plan (Zielordner, GlobalConfig.ts-Eintrag, References.ts-Plan), ohne die Festplatte anzufassen.
--json Nein Wie bei create-web-app — die JSON-Zusammenfassung ergänzt executable/appiumUrl neben referencesUpdated.
--help Nein Zeigt die Verwendung.

Dieselben Exit-Codes (0/2) und dieselben Idempotenz-Garantien wie bei create-web-app.

💡 Scaffolding läuft überall; das Ausführen der Tests braucht den Appium-Host. Der Befehl fasst den Pfad in --executable nie an — er schreibt lediglich einen String in GlobalConfig.ts, funktioniert also von jeder Maschine aus, auch von einem Devcontainer ohne angebundenen Windows-Host. Die generierten TestCases tatsächlich auszuführen braucht einen erreichbaren Appium-/WinAppDriver-Server unter --appium-url, mit der .exe auf diesem Host vorhanden — siehe FAQ — Wie findet das Framework den Appium-Server bei Desktop-Tests? und die appiumUrl-Erklärung oben.

Führe ihn zuerst mit --dry-run aus, genau wie create-web-app:

npx cc-testframework create-desktop-app --name DemoDesktop --executable "C:\apps\Demo.exe" --dry-run

UWP-/Windows-Store-Apps: executable akzeptiert auch eine AUMID

Nicht jede Windows-App ist eine klassische Win32-.exe. UWP-Apps — der Taschenrechner und die meisten Microsoft-Store-Apps — haben keine gewöhnliche Programmdatei, auf die man zeigen könnte. Für diese akzeptiert executable stattdessen eine AppUserModelId (AUMID) anstelle eines Dateipfads. Es ist dasselbe Feld in beiden Fällen — die app-Capability von WinAppDriver startet einen .exe-Pfad und eine AUMID transparent, ohne zusätzliches Feld und ohne zusätzlichen Schritt:

// 2_Apps/1_Global/GlobalConfig.ts
export const apps = {
    Calc: {
        type: 'Desktop',
        tool: 'Appium-Windows',
        executable: 'Microsoft.WindowsCalculator_8wekyb3d8bbwe!App', // AUMID
    },
} as const;

💡 Die AUMID einer App finden. Führe Get-StartApps in einer PowerShell-Sitzung auf der Maschine aus, auf der der Appium-Server läuft — der Befehl listet jede installierte Start-Menü-App zusammen mit ihrer AUMID. Für eine bestimmte App eingrenzen: Get-StartApps | Where-Object AppID -like "*Calculator*". Scaffoldest du den App-Eintrag über das Setup-Tooling des Frameworks, schlägt dessen Store-App-Picker die AUMID automatisch nach — der manuelle Get-StartApps-Weg oben ist der Fallback dafür, oder direkt nutzbar.

Voraussetzungen: Die Store-App muss auf der Maschine installiert sein, auf der WinAppDriver läuft, und eine erreichbare Appium-/WinAppDriver-Session wird so oder so benötigt — siehe FAQ — Wie findet das Framework den Appium-Server bei Desktop-Tests?.


Registriere eine Mobile-App

GlobalConfig.apps akzeptiert heute schon einen type: 'Mobile'-Eintrag, in dieser Form:

// 2_Apps/1_Global/GlobalConfig.ts
export const apps = {
    DeineMobileApp: {
        type: 'Mobile',
        tool: 'UiAutomator2', // oder 'XCUITest' für iOS
        appPath: '/pfad/zu/DeineApp.apk', // oder eine Bundle-ID für eine bereits installierte iOS-App
    },
} as const;

TypeScript akzeptiert diesen Eintrag, und GlobalConfig.apps typprüft sauber — aber wie die Tabelle oben zeigt, ist für UiAutomator2/XCUITest noch keine Runtime-Strategy registriert, sodass eine Control-Action gegen diesen Eintrag zur Laufzeit statt zur Compile-Zeit fehlschlägt. Registriere ihn schon jetzt, wenn du die Form für später bereit haben willst; verlass dich aber nicht darauf, dass er heute eine echte Session auflöst.


Registriere mehr als eine App

GlobalConfig.apps ist ein einziges Objekt — die meisten Projekte wachsen mit der Zeit auf mehrere Einträge, Familien beliebig gemischt:

// 2_Apps/1_Global/GlobalConfig.ts
export const apps = {
    DeineWebApp: {
        type: 'Web',
        tool: 'Playwright',
        baseUrl: URL_DEINE_WEB_APP,
    },
    DeineDesktopApp: {
        type: 'Desktop',
        tool: 'Appium-Windows',
        executable: 'C:\\Users\\Public\\<DeineApp>\\<DeineApp>.exe',
    },
} as const;

Jeder Schlüssel steht für sich — ein TestCase, der Steps aus DeineWebApp und DeineDesktopApp in derselben Datei komponiert, funktioniert genauso wie einer mit Steps aus nur einer App, weil jeder defineTestStep/defineExecutionStep-Aufruf ohnehin schon seinen eigenen App-Schlüssel trägt. Füge einen neuen Schlüssel hinzu, sobald eine neue AUT zu deiner Testsuite dazukommt; bestehende Einträge und die darauf aufgebauten TestCases bleiben unberührt.


Prüfe, dass deine App erreichbar ist

Ein Einzeiler-Paar TS_Execution_Start/TS_Execution_Close — die vollständige Datei siehe TestSteps bauen — bestätigt, dass der Eintrag aufgelöst wird, bevor du in Controls investierst:

// 3_Cases/TC_Smoke.spec.ts
import * as Project from '@GlobalRef';

Project.Core.test('TC_Smoke', async () => {
    Project.Core.Step.setCurrentTestCaseName('TC_Smoke');
    await Project.DeineApp.TS_Execution_Start();
    await Project.DeineApp.TS_Execution_Close();
});

Führe ihn mit npx playwright test 3_Cases/TC_Smoke.spec.ts aus pm/ heraus aus — siehe Ausführen und Debuggen für Flags und Optionen.

Häufige Fehlschläge und ihr Fix:

Fehler Ursache Fix
unknown appName 'DeineApp' Tippfehler, oder der Eintrag fehlt in GlobalConfig.apps Prüfe, dass die Schreibweise des Schlüssels exakt stimmt, inklusive Groß-/Kleinschreibung
Web app 'DeineApp' has no 'baseUrl' type: 'Web'-Eintrag ohne baseUrl-Feld Füge baseUrl zum Eintrag hinzu
Desktop app 'DeineApp' has no 'executable' type: 'Desktop', tool: 'Appium-Windows'-Eintrag ohne executable Füge den absoluten .exe-Pfad hinzu
StrategyRegistry: No factory registered for tool "..." Eintrag nutzt Mac2, UiAutomator2 oder XCUITest Noch nicht lauffähig — siehe Entscheide, welches Plattform-Tool zu deiner App passt oben
Playwright läuft beim Navigieren zu baseUrl in ein Timeout App von der Testmaschine aus nicht erreichbar (VPN, falsche Umgebungs-URL, Container-Networking) Prüfe, ob die URL sich von derselben Maschine/demselben Container aus im normalen Browser öffnet

Nächster Schritt: modelliere deine Controls

Mit registrierter und erreichbarer App modellierst du als Nächstes die interaktiven Elemente ihrer Screens als Controls.

Weiter: Controls hinzufügen — Locators, Actions, und wo die Control-Datei hingehört.


📧 Fragen? Kontakt: jens.szelag@itsbusiness.ch

itsbusiness AG · Bern · Schweiz