Тестирование представлений и свойств тела SwiftUI - PullRequest
4 голосов
/ 06 июня 2019

Я сейчас работаю над тем, как тестировать код представления 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?

1 Ответ

3 голосов
/ 06 июня 2019

Существует два расширения для .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
}

Когда вы выполняете метод .font для Text struct, вы получите новый Text с примененным шрифтом, потому что он вызывает перегрузку font(_:) (создание перегруженного метода с более конкретным типом возврата всегда нормально).Когда вы вызываете метод шрифта, например, для Button, тип возвращаемого значения:

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

Ну, это больше не нормальный Button, а обернутый довольно сложный тип, потому что он неУ него нет собственной перегрузки, как у Text, поэтому он вызывает «нормальный» метод.

Что произошло, когда вы вызвали 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>>
}

Перегрузка Text отсутствует, как и для метода шрифта.Это означает, что тип возвращаемого значения отличается от нового 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)
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...