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ürMac2/UiAutomator2/XCUITestist heute keine Runtime-Strategy registriert: die erste Action oder Check gegen so einen Eintrag schlägt zur Laufzeit fehl mitStrategyRegistry: 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. BenenneReferences.ts.exampleinReferences.tsum, fülle die darin beschriebenen Pflicht-Re-Exports aus, und füge dann die ausgegebene Zeile selbst hinzu. Das ist das einzige Szenario, in demProject.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_Startgelaufen ist, ist das Electron-Fenster eine gewöhnliche Playwright-Page — ein Chromium-gerendertes DOM. Jeder bestehende Web-Control und jederTS_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;
executableist der absolute Pfad, den WinAppDriver alsappium: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.appiumUrlist optional. Lässt du sie weg, löst das Framework einen sinnvollen Default über eine dreistufige Prioritätskette auf (expliziter Wert → UmgebungsvariableAPPIUM_URL→ Plattform-Default) — siehe API-Referenz — Sektion 14 und FAQ für die vollständige Kette und Troubleshooting.capabilitiesakzeptiert ein optionalesRecord<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
--executablenie an — er schreibt lediglich einen String inGlobalConfig.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.exeauf diesem Host vorhanden — siehe FAQ — Wie findet das Framework den Appium-Server bei Desktop-Tests? und dieappiumUrl-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-StartAppsin 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 manuelleGet-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