Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,20 @@ waitForIdleTimeout: 3000 # Device idle wait (ms), 0 to disable
- assertVisible: "Welcome"
```

## Visual Regression (`assertScreenshot`)

`assertScreenshot` compares the current screen (optionally cropped with `cropOn`) against a reference PNG.

- **First run:** if the reference file is missing, maestro-runner writes the captured screenshot as the new baseline and passes.
- **Re-baseline:** overwrite existing baselines with `--update-screenshots` (or `MAESTRO_UPDATE_SCREENSHOTS=true`).
- On mismatch, a `{name}_diff.png` overlay is written next to the reference.
- Pixel comparison is device-, resolution-, and OS-specific — pin your device config and set `thresholdPercentage` deliberately (default `95`).

```bash
maestro-runner test flows/visual.yaml # seeds missing baselines
maestro-runner test --update-screenshots flows/visual.yaml
```

## Requirements

- **Android testing:** `adb` (Android SDK Platform-Tools)
Expand Down
13 changes: 13 additions & 0 deletions pkg/cli/test.go
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,11 @@ Examples:
Usage: "When to capture screenshots/hierarchy: on-failure (default), always, never",
Value: "on-failure",
},
&cli.BoolFlag{
Name: "update-screenshots",
Usage: "Overwrite existing assertScreenshot baselines with the current screen (missing baselines are always seeded on first run)",
EnvVars: []string{"MAESTRO_UPDATE_SCREENSHOTS"},
},

// Emulator management flags (start-emulator, auto-start-emulator,
// shutdown-after, boot-timeout) are global flags defined in cli.go.
Expand Down Expand Up @@ -532,6 +537,9 @@ type RunConfig struct {
// Artifacts
Artifacts executor.ArtifactMode // When to capture screenshots/hierarchy

// UpdateScreenshots overwrites existing assertScreenshot baselines.
UpdateScreenshots bool

// Cloud provider (detected from AppiumURL, nil if not a cloud provider)
CloudProvider cloud.Provider
CloudMeta map[string]string
Expand Down Expand Up @@ -715,6 +723,7 @@ func runTest(c *cli.Context) error {
NoFlutterFallback: getBool("no-flutter-fallback"),
AndroidTCPForward: getBool("android-tcp-forward"),
Artifacts: parseArtifactMode(getString("artifacts")),
UpdateScreenshots: getBool("update-screenshots"),
}

// Apply waitForIdleTimeout with priority:
Expand Down Expand Up @@ -1362,6 +1371,7 @@ func executeSingleDevice(cfg *RunConfig, flows []flow.Flow) (*executor.RunResult
OutputDir: cfg.OutputDir,
Parallelism: 0,
Artifacts: cfg.Artifacts,
UpdateScreenshots: cfg.UpdateScreenshots,
Device: deviceInfo,
App: buildAppReport(driver),
RunnerVersion: Version,
Expand Down Expand Up @@ -1404,6 +1414,7 @@ func ExecuteFlowWithDriver(driver core.Driver, cfg *RunConfig, f flow.Flow) (*ex
OutputDir: cfg.OutputDir,
Parallelism: 0,
Artifacts: cfg.Artifacts,
UpdateScreenshots: cfg.UpdateScreenshots,
Device: deviceInfo,
App: buildAppReport(driver),
RunnerVersion: Version,
Expand Down Expand Up @@ -1729,6 +1740,7 @@ func executeAppiumSingleSession(cfg *RunConfig, flows []flow.Flow) (*executor.Ru
OutputDir: cfg.OutputDir,
Parallelism: 0,
Artifacts: cfg.Artifacts,
UpdateScreenshots: cfg.UpdateScreenshots,
Device: deviceInfo,
App: buildAppReport(driver),
RunnerVersion: Version,
Expand Down Expand Up @@ -2597,6 +2609,7 @@ func createParallelRunner(cfg *RunConfig, workers []executor.DeviceWorker, platf
OutputDir: cfg.OutputDir,
Parallelism: 0,
Artifacts: cfg.Artifacts,
UpdateScreenshots: cfg.UpdateScreenshots,
Device: deviceInfo,
App: buildAppReport(firstDriver),
RunnerVersion: Version,
Expand Down
Loading