簡體   English   中英

測試SwiftUI主體視圖和屬性

[英]Testing SwiftUI body views and properties

我正在研究如何對SwiftUI視圖代碼進行單元測試。

我有以下定義:

struct ContentView : View {
    var body: some View {

        Text("Hello World")
            .font(.title)
            .fontWeight(.bold) 
    }
}

我可以這樣測試:

    func testBody() {
        let cv = ContentView()

        let body = cv.body

        XCTAssertNotNil(body)

        guard let text = body as? Text else { XCTFail(); return }

        XCTAssertEqual(Text("Hello World").font(.title).fontWeight(.bold), text)
    }

但是,一旦我想測試文本對齊方式,就會遇到問題:

生產代碼:

struct ContentView : View {
    var body: some View {

        Text("Hello World")
            .font(.title)
            .fontWeight(.bold)
        .multilineTextAlignment(.leading)
    }
}

和測試代碼:

    func testBody() {
        let cv = ContentView()

        let body = cv.body

        XCTAssertNotNil(body)

        guard let text = body as? Text else { XCTFail(); return }

        // COMPILER ERROR ON NEXT LINE
        XCTAssertEqual(Text("Hello World").font(.title).fontWeight(.bold).multilineTextAlignment(.leading), text)  
    }

...然后出現以下編譯器錯誤:

Cannot convert value of type 'Text' to expected argument type '_ModifiedContent<Text, _EnvironmentKeyWritingModifier<HAlignment>>'

如何測試Text結構的對齊方式?

.font(_:)有兩個擴展名,即:

extension View {
    /// Sets the default font for text in this view.
    ///
    /// - Parameter font: The default font to use in this view.
    /// - Returns: A view with the default font set to the value you supply.
    public func font(_ font: Font?) -> Self.Modified<_EnvironmentKeyWritingModifier<Font?>>
}

extension Text {
    /// Sets the font to use when displaying this text.
    ///
    /// - Parameter font: The font to use when displaying this text.
    /// - Returns: Text that uses the font you specify.
    public func font(_ font: Font?) -> Text
}

Text結構上執行方法.font時, 您將使用所應用的字體返回一個新的Text ,因為它調用了font(_:)的重載(創建具有更特定返回類型的重載方法總是可以的) 。 當您在例如Button上調用font方法時,返回類型為:

ModifiedContent<Button<Text>, _EnvironmentKeyWritingModifier<Font?>>

好吧,這不再是普通的Button ,而是一個包裝的非常復雜的類型,因為它不像Text那樣具有自身的重載,因此它稱為“ normal”方法。

當您在Text實例上調用multilineTextAlignment時會發生什么?

extension View {

    /// Sets the alignment of multiline text in this view.
    ///
    /// - Parameter alignment: A value you use to align lines of text to the
    ///   left, right, or center.
    /// - Returns: A view that aligns the lines of multiline `Text` instances
    ///   it contains.
    public func multilineTextAlignment(_ alignment: HAlignment) -> Self.Modified<_EnvironmentKeyWritingModifier<HAlignment>>
}

Text沒有重載,就像font方法一樣。 這意味着返回類型與新的Text實例不同。 現在,我們陷入了一個復雜的時期。

幸運的是,該復雜類型具有content屬性。 執行此操作時,您的測試將編譯:

XCTAssertEqual(Text("Hello World").font(.title).fontWeight(.bold).multilineTextAlignment(.leading).content, text)

注意到content屬性:)?

運行測試時, body變量不是您想要的那樣為Text類型,而是具有另一個非常復雜的類型,這就是測試失敗的原因。 要通過測試,請執行以下操作:

func testBody() {
    let cv = ContentView()

    let body = cv.body

    XCTAssertNotNil(body)

    // Yuk!! Ugly cast, but don't know how to fix it since yeah, it is the type of the body...
    guard let text = body as? (_ModifiedContent<Text, _EnvironmentKeyWritingModifier<HAlignment>>) else { XCTFail(); return }

    // No compile error :) and a passing test!
    XCTAssertEqual(Text("Hello World").font(.title).fontWeight(.bold).multilineTextAlignment(.leading).content, text.content)
}

您可以使用ViewInspector庫對SwiftUI層次結構進行單元測試:

let view = ContentView()
let string = try view.inspect().text().string()
XCTAssertEqual(string, "Hello, world!")

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM