测试SwiftUI主体视图和属性

时间:2019-06-06 14:11:46

标签: ios swift tdd swiftui

我正在研究如何对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结构的对齐方式?

2 个答案:

答案 0 :(得分:2)

.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 ,因为它调用了{{ 1}}(使用更具体的返回类型创建重载方法总是可以的)。例如,在font(_:)上调用font方法时,返回类型为:

Button

好吧,这已经不再是普通的ModifiedContent<Button<Text>, _EnvironmentKeyWritingModifier<Font?>> 了,而是一个包装的非常复杂的类型,因为它没有像Text一样具有自身的重载,因此它调用了'normal'方法。

Button实例上调用multilineTextAlignment时会发生什么?

Text

没有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>> } 的重载,就像font方法的重载一样。这意味着返回类型不同于新的Text实例。现在我们陷入了一个复杂的时间。

幸运的是,该复杂类型有一个Text属性。执行此操作时,您的测试将编译:

content

否定了XCTAssertEqual(Text("Hello World").font(.title).fontWeight(.bold).multilineTextAlignment(.leading).content, text) 属性:)?

运行测试时,content变量并非像您期望的那样是body类型,但是具有另一个非常复杂的类型,这就是测试失败的原因。要通过测试,请执行以下操作:

Text

答案 1 :(得分:1)

您可以使用ViewInspector库对SwiftUI层次进行单元测试:

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