ViewInspector
ViewInspector copied to clipboard
How to build failing test for change in view
I have a test I wrote to confirm a bug that I found, where the failure to include an @Published
on an array in my viewModel meant that the view would not immediately update when a method was called that added an item to the array, even though the viewModel data had changed. Functionally, what would be seen was that when another change was made, the expected initial change would be visible as the ForEach
that was accessing that array would also be updated.
I wrote the following test that I expected to fail, that counted the number of rows in the section before the method was called, then called the method that should result in a row being added, and then examining the new row count:
// Setup
let viewModel = await ViewModelType()
let view = await ViewType(viewModel: viewModel)
let rows = try view.inspect().findAll(ItemRowType.self)
let baselineCount = rows.count
// Process under test
await viewModel.actions?.addItem()
// Test expectations
let finalRows = try view.inspect().findAll(ItemRowType.self)
let finalCount = finalRows.count
XCTAssertTrue(finalCount == baselineCount + 1, "Expected \(baselineCount + 1) final count but found \(finalCount)")
Unfortunately, this test did not fail even when the bug was present. It would correctly find three rows in baselineCount
(the ViewModel was initialised with some existing data), and find four rows present in finalCount
, while the bug remained functionally.
My guess is that most likely, calling the second view.inspect()
results in the view being updated? Given my bug was a failure for the view to be updated, this thus hides the problem I was trying to test, which is the failure for the view to be updated when the data model changed.
Is there another mechanism in ViewInspector that would let me test this? For example, is there a mechanism to observe calls to update the view or similar, so that I could assert that such an update has been called, after my await viewModel.actions?.addItem()
is called?