ViewInspector is a library for unit testing SwiftUI views.
It allows for traversing a view hierarchy at runtime providing direct access to the underlying View
structs.
SwiftUI view is a function of state. We could provide it with the input but could not verify the output... Until now!
Use one of the find
functions to quickly locate a specific view or assert there are none of such:
try sut.inspect().find(button: "Back")
try sut.inspect().findAll(ViewType.Text.self,
where: { try $0.attributes().isBold() })
Check out this section in the guide for the reference.
Standard SwiftUI views are no longer a black box:
let sut = Text("Completed by \(72.51, specifier: "%.1f")%").font(.caption)
let string = try sut.inspect().text().string(locale: Locale(identifier: "es"))
XCTAssertEqual(string, "Completado por 72,5%")
XCTAssertEqual(try sut.inspect().text().attributes().font(), .caption)
Each view has its own set of inspectable parameters, you can refer to the API coverage document to see what's available for a particular SwiftUI view.
Obtain a copy of your custom view with actual state and references from the hierarchy of any depth:
let sut = try view.inspect().find(CustomView.self).actualView()
XCTAssertTrue(sut.viewModel.isUserLoggedIn)
The library can operate with various types of the view's state, such as @Binding
, @State
, @ObservedObject
and @EnvironmentObject
.
You can simulate user interaction by programmatically triggering system-control callbacks:
try sut.inspect().find(button: "Close").tap()
let list = try view.inspect().list()
try list[5].view(RowItemView.self).callOnAppear()
The library provides helpers for writing asynchronous tests for views with callbacks.
Check out the API coverage.
ViewInspector is using the official Swift reflection API to dissect the view structures. So it'll be production-friendly even if you could somehow ship the test target to the production.
Assure you're adding the framework to your unit-test target. Do NOT add it to the main build target.
https://github.com/nalexn/ViewInspector
github "nalexn/ViewInspector"
pod 'ViewInspector'
Please refer to the Inspection guide. You can also check out my other project that harnesses the ViewInspector for testing the entire UI.
Contributions are welcomed! If you see an unsupported view or modifier, you can either open an issue (so I could prioritize such SwiftUI APIs over the rest), or try to crack it yourself: use the print("\(Inspector.print(<#view#>) as AnyObject)")
as the starting point of the investigation.