Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Help testing update by async func #197

Open
atsu0127 opened this issue Sep 19, 2022 · 2 comments
Open

Help testing update by async func #197

atsu0127 opened this issue Sep 19, 2022 · 2 comments
Labels
help wanted Extra attention is needed

Comments

@atsu0127
Copy link

atsu0127 commented Sep 19, 2022

I wrote a View and test that is updated by an asynchronous function in SwiftUI. But the test failed.
I would like to know how I should write tests in this case.

View

import SwiftUI

struct ContentView: View {
    internal var didAppear: ((Self) -> Void)?
    @State var count = 0
    
    var body: some View {
        NavigationView {
            VStack {
                Text(count.description)
                    .tag("count")
            }
            .onAppear { self.didAppear?(self) }
            .navigationTitle("TestApp")
            .toolbar {
                ToolbarItem(placement: .navigationBarTrailing){
                    Button {
                        Task {
                            await self.update()
                        }
                    } label: {
                        Label("update", systemImage: "arrow.clockwise")
                    }
                    .tag("updateButton")
                }
            }
        }
    }
    
    func update() async {
        try? await Task.sleep(until: .now + .seconds(1), clock: .continuous)
        self.count += 3
    }
}

Test

import XCTest
import ViewInspector
@testable import TestApp

extension ContentView: Inspectable {}

final class TestAppTests: XCTestCase {
    
    func testSample() throws {
        let startCount = "0"
        let incCount = "3"
        var sut = ContentView()
        
        let exp = sut.on(\.didAppear) { view in
            var count = try view.find(viewWithTag: "count").text().string()
            XCTAssertEqual(count, startCount)
            
            try view.find(viewWithTag: "updateButton").button().tap()
            
            count = try view.find(viewWithTag: "count").text().string()
            XCTAssertEqual(count, incCount) // testSample(): XCTAssertEqual failed: ("0") is not equal to ("3")
        }
        
        ViewHosting.host(view: sut)
        wait(for: [exp], timeout: 2.0)
    }
}
@nalexn nalexn added the help wanted Extra attention is needed label Dec 4, 2022
@nh7a
Copy link
Contributor

nh7a commented Oct 20, 2023

@atsu0127 you just have to wait until it's set.

final class TestAppTests: XCTestCase {

    @MainActor
    func testSample() throws {
        let startCount = "0"
        let incCount = "3"
        var sut = ContentView()

        let e = expectation(description: "for Task")
        let exp = sut.on(\.didAppear) { view in
            var count = try view.find(viewWithTag: "count").text().string()
            XCTAssertEqual(count, startCount)

            Task {
                try view.find(viewWithTag: "updateButton").button().tap()
                try await Task.sleep(until: .now + .seconds(1), clock: .continuous)

                count = try view.find(viewWithTag: "count").text().string()
                XCTAssertEqual(count, incCount) // 🆗
                e.fulfill()
            }
        }

        ViewHosting.host(view: sut)
        wait(for: [e, exp], timeout: 2.0)
    }
}

@sisoje
Copy link

sisoje commented Feb 2, 2024

@nh7a Waiting for a fixed amount of time for async to finish is not optimal.

@atsu0127 I suggest you to try my approach where I track each body evaluation by index, and it allows me to write async/await tests: https://github.com/sisoje/testable-view-swiftui

I use a different production code setup and view hosting though.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
help wanted Extra attention is needed
Projects
None yet
Development

No branches or pull requests

4 participants