Journal

SwiftUI ViewInspector tests with an AI prompt: a guide

ViewInspector lets you assert on a SwiftUI view in a plain unit test. Pair it with a tight AI prompt and injectable views, and the tests stay fast and real.

SwiftUI ViewInspector tests with an AI prompt: a guide: the App Store logo as a frosted glass icon on a pink and blue gradient with bubbles

TL;DR

To unit test SwiftUI views, use ViewInspector, an open-source library that reads and asserts on a view's contents in a plain unit test with no simulator. To generate the tests with AI, give Claude Code or Cursor the view, the real ViewInspector API, and a rule to assert on behavior rather than pixels. The bigger lever is building small, injectable views in the first place, which is far easier when you start from a free VP0 design than from a blank prompt.

To unit test SwiftUI views, the practical tool is ViewInspector, an open-source library with more than 2,600 stars that lets you read and assert on a view’s contents in a plain unit test, with no simulator and no UI test runner. The reliable way to generate those tests with AI is to give Claude Code or Cursor the view, the ViewInspector API, and a strict rule to assert on structure and behavior rather than pixels. The tests are only as good as the views, though, so the bigger lever is building small, injectable screens in the first place, which is far easier when you start from a real design instead of generating a tangled view from a blank prompt.

The sections below cover what ViewInspector does, how to prompt an AI builder to write the tests, where the generated tests go wrong, and how to make your SwiftUI testable from the start.

What is ViewInspector and why use it for SwiftUI tests?

ViewInspector is a library that traverses a SwiftUI view’s hierarchy at test time so you can assert on it directly. SwiftUI views are value types with an opaque body, which is why you cannot inspect them with normal reflection, and it is the gap ViewInspector fills using its own traversal. You can find a child view, read the text inside it, trigger a button’s action, toggle a binding, and confirm the resulting state, all inside a standard unit test.

The reason this matters is speed and focus. A XCUITest launches the whole app in the simulator, drives the real UI, and takes seconds per test, which makes a large suite slow and flaky. A ViewInspector test runs in-process in milliseconds and checks one specific thing, so you can have hundreds of them and still get fast feedback. It works with both XCTest and Apple’s newer Swift Testing framework, so it fits whichever runner your project uses.

It does not replace end-to-end UI tests. It replaces the much larger category of tests that only need to confirm a view shows the right content and reacts correctly to state, which is most of them.

How do ViewInspector unit tests actually work?

A ViewInspector test calls .inspect() on the view, navigates to the part you care about, and asserts on it. The shape is short once the pattern clicks.

import ViewInspector
import Testing
@testable import MyApp

@Test func priceLabelShowsTotal() throws {
    let model = CartModel(items: [Item(price: 9), Item(price: 3)])
    let view = CartSummary(model: model)
    let total = try view.inspect().find(text: "Total: 12")
    #expect(try total.string() == "Total: 12")
}

You can also drive interaction: find a button, call its tap(), and then assert that the model changed. For views whose content depends on @State that updates asynchronously, ViewInspector provides an inspection callback so the assertions run after the state settles rather than racing it. The official SwiftUI documentation describes how state drives the view, and ViewInspector is what lets you verify that wiring without rendering to a screen.

The mental model is to test the contract of the view: given this state, it shows this content and these controls, and tapping a control changes state in this way. That contract is stable even when layout details change, which keeps the tests from breaking on every visual tweak.

Writing an AI prompt that generates ViewInspector tests

A good prompt names the library, points the model at the real view, and forbids the two things AI gets wrong most: inventing API and testing the wrong layer. Paste the view’s source, then constrain the request:

Write unit tests for this SwiftUI view using ViewInspector and Swift Testing.
Rules:
- Use only real ViewInspector API: inspect(), find(text:), find(ViewType...), tap(), callOnChange. Do not invent methods.
- Test behavior and content, not layout or exact pixel positions.
- For each test, set up the model, render the view, assert on what the user would see, then assert on state after interaction.
- Inject the model through the initializer; do not reach into private state.
- Cover the empty state, a populated state, and one interaction.
Return one test per behavior with a descriptive name.

The constraints carry the prompt. Telling the model to use only real ViewInspector methods cuts down hallucinated API, and telling it to assert on behavior keeps the tests from breaking on cosmetic changes. If your AI builder still produces methods that do not exist, a short read on why Cursor hallucinates SwiftUI covers how to ground it in the real API.

What AI gets wrong in SwiftUI tests

Generated SwiftUI tests fail in a few predictable ways, and knowing them turns a broken first draft into a quick fix. The most common is invented API: the model writes view.inspect().button("Save") or some plausible-looking method ViewInspector does not have, because it is pattern-matching other testing libraries. Replace it with the real find and tap calls.

The second is testing the wrong layer. AI often asserts on exact spacing, frame sizes, or view order by index, which produces tests that break the moment you adjust the layout. Good ViewInspector tests find views by their content or type, not by position. The third is ignoring async state, where the test asserts before an @State update has applied; the fix is the inspection callback that waits for the state to settle.

A fourth, subtler one is tests that pass for the wrong reason, asserting that a view exists without checking what it contains. Those give false confidence. Reviewing generated tests the same way you would review generated code is worth the time, and a look at running a SwiftUI code audit covers what to check beyond tests.

Making your SwiftUI testable in the first place

Tests are only as good as the views, and the most testable views share three traits: they are small, they take their dependencies through the initializer, and they keep logic out of body. A 300-line view that reads a global singleton is hard to test no matter how good the tooling, because you cannot set up its state in isolation. A small view that receives an @Observable model can be rendered with any state you want and checked directly.

This is where the starting point matters more than the test framework. When you build screens from a real design, they come out structured and consistent, which makes them straightforward to test; when you generate them from a vague prompt, they come out tangled, and the tests inherit the mess. Starting from a free VP0 design gives the AI builder real structure to implement, because each design has a machine-readable source page Claude Code, Cursor, or Rork can read from a pasted link. The views you get are easier to both build and test, and you can pair this with the broader advanced SwiftUI patterns that keep state ownership clean. Clean state ownership is exactly what makes a view injectable, and injectable is what makes it testable.

ViewInspector vs XCUITest vs snapshot testing

Each SwiftUI testing approach answers a different question, so the strongest suites use more than one. The split is clearest as a table.

ApproachBest forSpeedBreaks when
ViewInspectorContent and behavior of a view given stateFast, in-processThe view’s contract changes
XCUITestFull user flows across screensSlow, simulatorA flow or navigation path changes
Snapshot testingCatching unintended visual changesMediumThe design intentionally changes

Use ViewInspector for the bulk of your tests, the per-view checks that confirm content and interaction. Add a small number of XCUITests for the critical end-to-end flows like sign-in and checkout. Add snapshot tests when visual regressions are a real risk and you want a pixel diff to catch them. Leaning entirely on XCUITest is the common mistake, because the suite gets slow and flaky long before it gets thorough.

Common ViewInspector setup issues

A few setup details trip people up, and they are quick to fix once you know them. Tests need @testable import of your app module so ViewInspector can reach internal views, plus import ViewInspector itself. Recent versions of the library dropped the old requirement to add an Inspectable conformance to every view, so if you are following an older tutorial that tells you to write extension MyView: Inspectable {}, you can usually skip it on a current version; check the library’s README for the version you installed.

The other frequent issue is asynchronous content. When a view loads data into @State and then renders it, an immediate assertion runs before the state updates, so the test fails intermittently. The fix is the inspection callback that fires after the update, rather than reading the view synchronously. Flaky async tests are nearly always this, not a bug in the view.

Key takeaways: unit testing SwiftUI with ViewInspector and AI

Use ViewInspector for fast, in-process tests that assert on a view’s content and behavior, and keep XCUITest for a handful of critical flows. Prompt your AI builder with the real ViewInspector API and a rule to test behavior over layout, then review the generated tests for invented methods and assertions that pass for the wrong reason. Most of all, build small, injectable views, since testability is decided when you write the view, not when you write the test. Starting from a free VP0 design gives you that structure for nothing, while a commissioned, fully-tested screen build can cost $5,000 or more.

You can browse VP0 designs to start from a screen that is already structured cleanly enough to test.

Frequently asked questions

What is the best way to write SwiftUI unit tests with an AI prompt?

Use ViewInspector as the library and prompt Claude Code or Cursor with the real view, the actual ViewInspector API, and a rule to assert on behavior and content rather than layout. Building the view from a free VP0 design first makes the tests easier, because a cleanly structured, injectable view is straightforward to set up in isolation. Then review the generated tests for invented methods and for assertions that only check a view exists without checking what it contains.

How can I use ViewInspector to test an iOS app built with AI?

Add ViewInspector to your test target, import your app module with @testable, and write tests that render a view with a known model, find elements by content or type, and assert on the result. For interactions, find a control, call its action, and check the state afterward. The same approach works whether the view was hand-written or generated, as long as the view takes its dependencies through the initializer rather than reaching into globals.

What is the safest way to generate SwiftUI tests with Claude Code or Cursor?

Constrain the model to real ViewInspector methods, require behavior-level assertions, and review every generated test before trusting it. AI frequently invents testing API and writes tests that pass without verifying anything meaningful, so treat generated tests as a first draft to audit, not a finished suite. Running them against an intentionally broken version of the view is a quick way to confirm they actually fail when they should.

Can VP0 provide a free SwiftUI or React Native template to test against?

Yes. VP0 is a free iOS app design library where every design has a machine-readable source page an AI builder reads from a pasted link, and designs come in SwiftUI and React Native variants. Starting from a design produces a structured, injectable view, which is exactly the kind of view that is simple to cover with ViewInspector tests.

What common errors happen when vibe coding SwiftUI tests?

The usual ones are hallucinated ViewInspector methods that do not exist, tests that assert on layout or view index and break on any cosmetic change, async tests that read state before it updates, and tests that confirm a view is present without checking its content. All four are easy to miss because the suite still goes green, so a manual pass over generated tests, plus running them against a deliberately broken view, catches the ones that are not really testing anything.

What the VP0 community is asking

What is the best way to write SwiftUI unit tests with an AI prompt?

Use ViewInspector as the library and prompt Claude Code or Cursor with the real view, the actual ViewInspector API, and a rule to assert on behavior and content rather than layout. Building the view from a free VP0 design first makes the tests easier, because a cleanly structured, injectable view is straightforward to set up in isolation. Then review the generated tests for invented methods and for assertions that only check a view exists without checking what it contains.

How can I use ViewInspector to test an iOS app built with AI?

Add ViewInspector to your test target, import your app module with @testable, and write tests that render a view with a known model, find elements by content or type, and assert on the result. For interactions, find a control, call its action, and check the state afterward. The same approach works whether the view was hand-written or generated, as long as the view takes its dependencies through the initializer rather than reaching into globals.

What is the safest way to generate SwiftUI tests with Claude Code or Cursor?

Constrain the model to real ViewInspector methods, require behavior-level assertions, and review every generated test before trusting it. AI frequently invents testing API and writes tests that pass without verifying anything meaningful, so treat generated tests as a first draft to audit, not a finished suite. Running them against an intentionally broken version of the view is a quick way to confirm they actually fail when they should.

Can VP0 provide a free SwiftUI or React Native template to test against?

Yes. VP0 is a free iOS app design library where every design has a machine-readable source page an AI builder reads from a pasted link, and designs come in SwiftUI and React Native variants. Starting from a design produces a structured, injectable view, which is exactly the kind of view that is simple to cover with ViewInspector tests.

What common errors happen when vibe coding SwiftUI tests?

The usual ones are hallucinated ViewInspector methods that do not exist, tests that assert on layout or view index and break on any cosmetic change, async tests that read state before it updates, and tests that confirm a view is present without checking its content. All four are easy to miss because the suite still goes green, so a manual pass over generated tests, plus running them against a deliberately broken view, catches the ones that are not really testing anything.

Part of the Native Apple & SwiftUI: The iOS Ecosystem hub. Browse all VP0 topics →

Keep reading

Fix Memory Leaks in AI-Generated SwiftUI Code: a vivid neon 3D App Store icon on an orange, pink and blue gradient
Workflows 6 min read

Fix Memory Leaks in AI-Generated SwiftUI Code

AI-generated SwiftUI leaks in predictable ways: strong self in closures, uncancelled Combine, live timers. Here is how to spot and fix each with Instruments.

Lawrence Arya · June 4, 2026
Apple Sign In Required Rejection: Fix It in SwiftUI: a glass app tile showing the VP0 logo on a pink and blue gradient
Workflows 5 min read

Apple Sign In Required Rejection: Fix It in SwiftUI

Rejected because Sign in with Apple is missing? If you offer Google or Facebook login, Apple requires it too. Here is the SwiftUI fix that clears review.

Lawrence Arya · June 1, 2026
Spline 3D Model Background in SwiftUI: A Practical Guide: a reflective 3D App Store icon on a blue and purple gradient
Guides 9 min read

Spline 3D Model Background in SwiftUI: A Practical Guide

A Spline scene behind a SwiftUI interface looks alive because the GPU draws it live. Here is the embed, the performance caps, and when to choose SceneKit.

Lawrence Arya · June 10, 2026
SwiftUI App Intents Template for Apple Intelligence Apps: a glossy App Store icon on a blue, pink and orange gradient with bubbles
Guides 9 min read

SwiftUI App Intents Template for Apple Intelligence Apps

App Intents are how Apple Intelligence, Siri, Shortcuts, and Spotlight reach an app. Here is the template structure that gives an agent the right pattern.

Lawrence Arya · June 10, 2026
SwiftUI Code Audit Service: What to Buy and What It Costs: the App Store logo as a glossy glass icon on a purple and blue gradient with floating bubbles
Guides 9 min read

SwiftUI Code Audit Service: What to Buy and What It Costs

A SwiftUI code audit is judgment as a deliverable: a ranked map of what is fragile in your AI-built app. Here is what to buy, prepare, and expect to pay for.

Lawrence Arya · June 10, 2026
Zaawansowany SwiftUI tutorial: advanced iOS UI with AI: a glass iPhone UI wireframe icon on a holographic purple gradient
Guides 11 min read

Zaawansowany SwiftUI tutorial: advanced iOS UI with AI

Advanced (zaawansowany) SwiftUI comes down to state, performance, navigation, and animation. Here is how to get each right and build faster with AI.

Lawrence Arya · June 10, 2026