Unable to unit test SwiftUI code.

Originator:you
Number:rdar://FB7778358 Date Originated:2020-06-24
Status:Open Resolved:
Product:SwiftUI Framework Product Version:
Classification:Suggestion Reproducible:
 
Hi,

I would like to be able to unit test my swift UI views. This is something that's possible (though, a bit clunky at times) with UIKit/Appkit views, but it appears the suggested approach to unit testing SwiftUI code is "don't".

Also attached is a code sample of a simple swift UI view that demonstrates a bit what I have in mind/would like.

I would love to be able to easily, quickly, and in an automated way, verify interactions between SwiftUI code and their related models. Right now, there's no way to do that. There does exist community/open source libraries that help (https://github.com/nalexn/ViewInspector is the one I found, which uses reflection to retrieve data, and some type-unsafe ways to interact with views. In addition, every time SwiftUI adds more views, the library needs to be updated), but a first-party way would be much preferable because it can provide access to the swift UI view tree in a generic and type-safe way.

Thank you,
Rachel

---

Included file: SettingsTest.swift:

```swift
// Hi!
// This is a bit of sample code that I was playing with in my most recent attempt at exploring unit testing SwiftUI.
// For simplicity, I inlined and simplified the relevant dependencies 
// Quick background, the app is an astrophotography app, and this is turning on/off certain debug settings in the image alignment pipeline.

import XCTest
import SwiftUI

final class Settings: ObservableObject {
    @Published var drawDetectedStars: Bool = false
}

struct SettingsView: View {
    @ObservedObject var settings: Settings

    var body: some View {
        VStack(alignment: .leading) {
            // Show logs
            Text("Debug").font(Font.system(.headline))
            // Draw stars
            Toggle("Draw Stars", isOn: self.$settings.drawDetectedStars)
                .accessibility(identifier: "drawStars")
            Spacer()
        }
        .padding(EdgeInsets(top: 0, leading: 16, bottom: 0, trailing: 16))
        .navigationBarTitle("Settings")
    }
}

class TestSettingsView: XCTestCase {
    func testTogglingDrawStars() throws {
        let settings = Settings()
        let view = SettingsView(settings: settings)

        let toggle = try XCTUnwrap(view.query("#drawStars") as? Toggle) // In this sample, I'm using XPath/css query syntax.
        
        XCTAssertFalse(toggle.isOn) // Assert that it starts in the off position

        toggle.toggle()
        XCTAssertTrue(toggle.isOn) // Not necessary, but shows that I'd expect this property to be true now.

        XCTAssertTrue(settings.drawDetectedStars) // This is the interaction I'm actually trying to verify here.

        // now, let's turn it off.
        toggle.toggle()
        XCTAssertFalse(settings.drawDetectedStars) // This is the interaction I'm actually trying to verify here.
    }
}
```

Comments


Please note: Reports posted here will not necessarily be seen by Apple. All problems should be submitted at bugreport.apple.com before they are posted here. Please only post information for Radars that you have filed yourself, and please do not include Apple confidential information in your posts. Thank you!