【问题标题】:Testing SwiftUI body views and properties测试 SwiftUI 主体视图和属性
【发布时间】:2019-06-06 14:11:46
【问题描述】:

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

【问题讨论】:

  • 您是否尝试将text 转换为'_ModifiedContent<Text, _EnvironmentKeyWritingModifier<HAlignment>>' 而不是Text
  • 不幸的是,这会产生进一步的编译器错误:Global function 'XCTAssertEqual(_:_:_:file:line:)' requires that '_EnvironmentKeyWritingModifier<HAlignment>' conform to 'Equatable'

标签: ios swift tdd swiftui


【解决方案1】:

.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 上调用字体方法时,返回类型为:

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

嗯,这不再是普通的Button,而是一个非常复杂的包装类型,因为它不像 Text 那样有自己的重载,所以它调用“普通”方法。

当您在 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)
}

【讨论】:

  • 我试过你的解决方案,但我收到了这个错误。 ``` 使用未声明的类型 '_ModifiedContent'``` 以及 Use of unresolved identifier 'Text' 。我正在使用这个版本的 Xcode Version 11.0 (11A419c)
  • @user2924482 我只能猜到你错过了一个导入语句
  • 我错过了什么?
【解决方案2】:

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-04-14
    • 2021-01-31
    • 1970-01-01
    • 2016-12-06
    • 2020-05-18
    • 2021-10-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多