This is my first time replying to a forum post, so bear with me haha.
If you want to unit test views, you need to hold all their data in viewModels (which is the recommended architecture, so you should always do that anyways). So create a viewmodel for your view that would hold the gameType variable and then create a function that would either set it to 1 or 2 (if you only need 2 options for your radio buttons, just hold the info in a bool | if you need more options, use an enum, that way you leave no space for weird errors when you mistype an Int).
So here's your viewModel:
class YourViewModel: ObservableObject {
@Published var gameType: Int = 1
func changeGameType(to number: Int) {
DispatchQueue.main.async { // Important! View updates should only be made from main thread
self.gameType = number
}
}
}
}
Your view:
struct YourView: View {
@ObservedObject private var viewModel = YourViewModel()
var body: some View {
YourButtonView(title: "Change Game Type to 2", selectedGameType: $viewModel.gameType) {
viewModel.changeGameType(to: 2)
}
}
}
Your button view: (not a radio button obvs, adapt to needs)
struct YourButtonView: View {
let title: String
let action: () -> Void
@Binding var selectedGameType: Int
init(title: String, selectedGameType: Binding<Int>, action: @escaping () -> Void) {
self.title = title
self._selectedGameType = selectedGameType
self.action = action
}
var body: some View {
Button(title, action: action)
}
}
And the unit test:
func testGameType() {
// Note: Since we used DispatchQueue.main.async in our function testing the function as if it was a synchronous one will fail!
// So we will use Combine instead
// Given
let viewModel = YourViewModel()
let expectation = XCTestExpectation(description: "Changes game type to 2.")
var cancellable: AnyCancellable?
cancellable = viewModel.$gameType
.dropFirst() // We remove the inital value (in our case 1)
.sink { gameType in
// Assert new gameType value
XCTAssert(
gameType == 2,
"Value expected to be 2, but got \(gameType) instead"
)
// Fulfill expectation
expectation.fulfill()
}
// When ( We imitate the radio button press by calling its function )
viewModel.changeGameType(to: 2)
// Then
wait(for: [expectation], timeout: 1)
}