> ## Documentation Index
> Fetch the complete documentation index at: https://docs.flowdeck.studio/llms.txt
> Use this file to discover all available pages before exploring further.

# Test Commands

> Run and discover unit and UI tests

## flowdeck test

Run unit and UI tests.

```bash theme={null}
# After 'flowdeck config set', run tests with saved settings
flowdeck test

# Explicitly keep Simulator.app closed during simulator tests
flowdeck test --headless

# Run all tests (without config set)
flowdeck test -w MyApp.xcworkspace -s MyScheme -S "iPhone 16"

# Run tests on macOS
flowdeck test -D "My Mac"

# Run specific tests with --only
flowdeck test --only MyTests/LoginTests
flowdeck test --only MyTests/LoginTests/testLogin
flowdeck test --only "MyTests/Login Tests/test Login Success"

# Skip specific tests
flowdeck test --skip MyTests/SlowTests
flowdeck test --skip MyTests/IntegrationTests

# Multiple test targets
flowdeck test --test-targets "UnitTests,IntegrationTests"

# Run a specific test plan (name or path)
flowdeck test --plan "Smoke"
flowdeck test --plan "TestPlans/Smoke.xctestplan"
flowdeck test --plan "Smoke" --only MyTests/LoginTests

# Output modes
flowdeck test                  # Summary only (default)
flowdeck test -v               # Detailed output with exact test verdict markers
flowdeck test --progress       # Show pass/fail as tests complete
flowdeck test --streaming      # Clean output for file capture
flowdeck test --json           # JSON for CI/automation

# Pass arguments to xcodebuild
flowdeck test --xcodebuild-options='-parallel-testing-enabled YES'
flowdeck test --xcodebuild-options='-enableCodeCoverage YES'
flowdeck test --xcodebuild-options='-resultBundlePath /tmp/results.xcresult'
flowdeck test --xcodebuild-env='CI=true'

# Show usage examples
flowdeck test --examples
```

### Options

| Option                        | Short | Description                                                                                                              |
| ----------------------------- | ----- | ------------------------------------------------------------------------------------------------------------------------ |
| `--examples`                  |       | Show usage examples                                                                                                      |
| `--project <path>`            | `-p`  | Project directory                                                                                                        |
| `--workspace <path>`          | `-w`  | Path to workspace (.xcworkspace) or project (.xcodeproj)                                                                 |
| `--scheme <name>`             | `-s`  | Scheme name                                                                                                              |
| `--configuration <name>`      | `-C`  | Build configuration (Debug/Release)                                                                                      |
| `--simulator <name>`          | `-S`  | Simulator name/UDID (REQUIRED for iOS/tvOS/watchOS)                                                                      |
| `--device <name>`             | `-D`  | Device name/UDID (use "My Mac" for macOS)                                                                                |
| `--derived-data-path <path>`  | `-d`  | Derived data path (default: `~/Library/Developer/FlowDeck/DerivedData`)                                                  |
| `--config <path>`             | `-c`  | Path to an explicit command config file                                                                                  |
| `--test-targets <targets>`    |       | Specific test targets to run (comma-separated)                                                                           |
| `--test-cases <cases>`        |       | Specific test cases to run (comma-separated, format: TargetName/ClassName/testMethod)                                    |
| `--only <tests>`              |       | Run only specific tests (suite methods: TargetName/ClassName/testMethod; top-level Swift Testing: TargetName/function()) |
| `--skip <tests>`              |       | Skip specific tests (format: TargetName/ClassName or TargetName/ClassName/testMethod)                                    |
| `--plan <name-or-path>`       |       | Test plan name or .xctestplan path                                                                                       |
| `--json`                      | `-j`  | Output as JSON                                                                                                           |
| `--verbose`                   | `-v`  | Show detailed xcodebuild output with exact raw test verdict markers                                                      |
| `--progress`                  |       | Show test results as they complete (pass/fail per test)                                                                  |
| `--streaming`                 |       | Stream clean formatted test results (no escape codes, for file capture)                                                  |
| `--headless`                  |       | Explicitly keep Simulator.app closed during simulator tests; ignored for macOS and physical-device targets               |
| `--xcodebuild-options <args>` |       | Extra xcodebuild arguments (e.g., `--xcodebuild-options='-parallel-testing-enabled YES'`)                                |
| `--xcodebuild-env <vars>`     |       | Xcodebuild environment variables (e.g., 'CI=true')                                                                       |

<Note>
  After running `flowdeck config set`, workspace, scheme, and simulator are saved to project state.
  CLI parameters are only required if you haven't run `flowdeck config set`, or to override saved values.
  Use `--device "My Mac"` for macOS builds.
</Note>

<Note>
  `--config` here means the explicit command config file format. It is separate from `.flowdeck/config.json` and `.flowdeck/config.local.json`.
</Note>

<Note>
  On failed test runs, FlowDeck prints the extracted failure reason plus `Full log: <absolute-path>` for the persisted raw xcodebuild output. Read that file directly before rerunning with `--verbose`.
</Note>

<Note>
  Simulator tests already execute without opening Simulator.app. `--headless` makes that intent explicit for app-hosted and agent workflows while preserving the same execution behavior. The flag is ignored for macOS and physical-device targets.
</Note>

### Finalized Result Bundles

Every real run waits for xcodebuild to finish and saves one finalized test bundle at `~/.flowdeck/logs/<project-hash>/test.xcresult`. The build-for-testing phase uses a separate FlowDeck diagnostics bundle, so the two phases never compete for the same `-resultBundlePath`.

To choose the test bundle path, pass `-resultBundlePath` through `--xcodebuild-options`. If more than one value is present across config and CLI sources, the final value wins. FlowDeck removes duplicate forms and applies the selected path only to `test-without-building`.

`--verbose` prints stable terminal markers: `** TEST SUCCEEDED **`, `** TEST FAILED **`, or `** TEST EXECUTE FAILED **`. A nonzero xcodebuild status, including 65, always produces a failed command.

### Test Filtering

The `--only` option supports multiple formats:

* **Full path**: `MyAppTests/LoginTests/testValidLogin` - runs a specific test method
* **Top-level Swift Testing function**: `MyAppTests/topLevelTest()` - omits the synthetic discovery class
* **Class name**: `LoginTests` - runs all tests in that class
* **Method name**: `testValidLogin` - runs all tests with that method name (across classes)

You can specify multiple tests by using `--only` multiple times or separating with commas.

When `--plan` is combined with `--only` or `--test-cases`, FlowDeck resolves
the filter against that plan's enabled and selected tests. Exclusions in other
plans do not affect the run. Without `--plan`, discovery follows the scheme's
default test plan.

If the selected plan is not attached to the scheme, its file is missing, or
its contents cannot be read, FlowDeck stops before running tests and suggests
`flowdeck test plans` to inspect the scheme's available plans.

### Config File Format

The `--config` parameter accepts the explicit command config format:

```json theme={null}
{
  "workspace": "MyApp.xcworkspace",
  "scheme": "MyApp",
  "configuration": "Debug",
  "platform": "iOS",
  "version": "18.0",
  "derivedDataPath": "/custom/path"
}
```

For macOS builds, set `platform` to `"macOS"` (no simulator needed).

### JSON Output

When using `--json`, the command outputs newline-delimited JSON events during execution, followed by a final test result:

```json theme={null}
{"type":"status","stage":"COMPILING","message":"Building for testing..."}
{"type":"status","stage":"TESTING","message":"Running tests on iPhone 16..."}
{"type":"test_started","data":{"testId":"LoginTests/testValidLogin"}}
{"type":"test_passed","data":{"testId":"LoginTests/testValidLogin","duration":0.023}}
{"type":"test_failed","data":{"testId":"LoginTests/testInvalidLogin","duration":0.045,"failure_message":"XCTAssertEqual failed","file_name":"LoginTests.swift","line_number":42}}
{"schema":"flowdeck.test","schemaVersion":"1.1.0","success":false,"totalTests":2,"passedTests":1,"failedTests":1,"skippedTests":0,"resultBundlePath":"/Users/me/.flowdeck/logs/abc123/test.xcresult"}
```

**Event Types:**

| Type           | Description                                                                                            |
| -------------- | ------------------------------------------------------------------------------------------------------ |
| `status`       | Progress updates with `stage` and `message`                                                            |
| `test_started` | Test execution started with `data.testId`                                                              |
| `test_passed`  | Test passed with `data.testId` and `data.duration`                                                     |
| `test_failed`  | Test failed with `data.testId`, duration, message, file, and line details                              |
| `test_skipped` | Test skipped with `data.testId` and optional reason                                                    |
| Final snapshot | Top-level `flowdeck.test` result with authoritative counts, `success`, and optional `resultBundlePath` |

**Final Result (Success):**

```json theme={null}
{
  "schema": "flowdeck.test",
  "schemaVersion": "1.1.0",
  "success": true,
  "totalTests": 42,
  "passedTests": 42,
  "failedTests": 0,
  "skippedTests": 0,
  "duration": 12.5,
  "passedTestNames": ["LoginTests/testValidLogin", "..."],
  "skippedTestNames": [],
  "failures": [],
  "resultBundlePath": "/Users/me/.flowdeck/logs/abc123/test.xcresult"
}
```

**Final Result (Failure):**

```json theme={null}
{
  "schema": "flowdeck.test",
  "schemaVersion": "1.1.0",
  "success": false,
  "totalTests": 42,
  "passedTests": 40,
  "failedTests": 2,
  "skippedTests": 0,
  "duration": 15.3,
  "passedTestNames": ["..."],
  "skippedTestNames": [],
  "failures": [
    {
      "testName": "LoginTests/testInvalidLogin",
      "reason": "XCTAssertEqual failed: (\"expected\") is not equal to (\"actual\")",
      "fileName": "LoginTests.swift",
      "lineNumber": 42,
      "duration": 0.045
    }
  ],
  "resultBundlePath": "/Users/me/.flowdeck/logs/abc123/test.xcresult"
}
```

## flowdeck test discover

Discover all available tests in a project by parsing test source files. This uses static source analysis (like Xcode's Test Navigator) and does not require building the project.

```bash theme={null}
# After 'flowdeck config set', discover tests with saved settings
flowdeck test discover

# Discover tests (without config set)
flowdeck test discover -w MyApp.xcworkspace -s MyScheme

# Output as JSON (for tooling)
flowdeck test discover --json

# Filter tests by name
flowdeck test discover --filter Login
flowdeck test discover -F Login

# Apply a specific test plan's selections and skips
flowdeck test discover --plan Smoke

# Include tests that are skipped in the scheme or test plan
flowdeck test discover --include-skipped-tests
```

### Options

| Option                    | Short | Description                                                                    |
| ------------------------- | ----- | ------------------------------------------------------------------------------ |
| `--project <path>`        | `-p`  | Project directory                                                              |
| `--workspace <path>`      | `-w`  | Path to workspace (.xcworkspace) or project (.xcodeproj) (also accepts `--ws`) |
| `--scheme <name>`         | `-s`  | Scheme name (also accepts `--sch`)                                             |
| `--config <path>`         | `-c`  | Path to an explicit command config file (also accepts `--cfg`)                 |
| `--filter <query>`        | `-F`  | Filter tests by name (case-insensitive)                                        |
| `--plan <name-or-path>`   |       | Test plan name or .xctestplan path                                             |
| `--json`                  | `-j`  | Output as JSON                                                                 |
| `--include-skipped-tests` |       | Include tests that are skipped in the scheme or test plan (marked as skipped)  |
| `--examples`              | `-e`  | Show usage examples                                                            |

<Note>
  Test discovery uses static source parsing and doesn't require building. It finds `XCTestCase` subclasses, `test*` methods, `@Suite` structs, and `@Test` functions directly from source files. By default, tests that are disabled in the scheme's default plan (or the plan selected with `--plan`) are excluded from results. Use `--include-skipped-tests` to include excluded and unselected tests with `isSkipped: true`.
</Note>

<Note>
  If `--plan` appears on both `flowdeck test` and `flowdeck test discover`, the
  value after `discover` takes precedence. Missing, unavailable, or malformed
  plans fail discovery and point to `flowdeck test plans`.
</Note>

### JSON Output

```json theme={null}
{
  "schema": "flowdeck.test",
  "schemaVersion": "1.1.0",
  "tests": [
    {
      "target": "MyAppTests",
      "class": "LoginTests",
      "method": "testValidLogin",
      "identifier": "MyAppTests/LoginTests/testValidLogin",
      "file": "LoginTests.swift",
      "filePath": "/path/to/LoginTests.swift",
      "lineNumber": 15,
      "isSkipped": false
    }
  ]
}
```

***

## flowdeck test plans

List test plans referenced by a scheme. This reads the scheme file and does not build the project.

```bash theme={null}
# After 'flowdeck config set', list plans with saved settings
flowdeck test plans

# List plans (without config set)
flowdeck test plans -w MyApp.xcworkspace -s MyScheme

# Output as JSON (for tooling)
flowdeck test plans --json
```

### Options

| Option               | Short | Description                                                                    |
| -------------------- | ----- | ------------------------------------------------------------------------------ |
| `--project <path>`   | `-p`  | Project directory                                                              |
| `--workspace <path>` | `-w`  | Path to workspace (.xcworkspace) or project (.xcodeproj) (also accepts `--ws`) |
| `--scheme <name>`    | `-s`  | Scheme name (also accepts `--sch`)                                             |
| `--config <path>`    | `-c`  | Path to an explicit command config file (also accepts `--cfg`)                 |
| `--json`             | `-j`  | Output as JSON                                                                 |
| `--examples`         | `-e`  | Show usage examples                                                            |

### JSON Output

```json theme={null}
{
  "schema": "flowdeck.test",
  "schemaVersion": "1.1.0",
  "plans": [
    {
      "name": "Smoke",
      "reference": "container:App/TestPlans/Smoke.xctestplan",
      "path": "/path/to/App/TestPlans/Smoke.xctestplan",
      "isDefault": true,
      "isMissing": false
    }
  ]
}
```
