web-dev-qa-db-fra.com

Comment tester les fonctions de lancer dans Swift?

Comment tester si une fonction dans Swift 2.0 jette ou non? Comment affirmer que la bonne ErrorType est lancée?

28
Fabio Poloni

EDIT: Mise à jour du code pour Swift 4.1.

Voici la dernière version Swift de réponse de Fyodor Volchyok qui a utilisé XCTAssertThrowsError:

    enum MyError: Error {
        case someExpectedError
        case someUnexpectedError
    }

    func functionThatThrows() throws {
        throw MyError.someExpectedError
    }

    func testFunctionThatThrows() {
        XCTAssertThrowsError(try functionThatThrows()) { error in
            XCTAssertEqual(error as! MyError, MyError.someExpectedError)
        }
    }

Si votre enumbre Error a des valeurs associées, vous pouvez avoir votre enumération Error se conformer à Equatable ou utiliser l'instruction if case:

    enum MyError: Error, Equatable {
        case someExpectedError
        case someUnexpectedError
        case associatedValueError(value: Int)
    }

    func functionThatThrows() throws {
        throw MyError.associatedValueError(value: 10)
    }

    // Equatable pattern: simplest solution if you have a simple associated value that can be tested inside 1 XCTAssertEqual
    func testFunctionThatThrows() {
        XCTAssertThrowsError(try functionThatThrows()) { error in
            XCTAssertEqual(error as! MyError, MyError.associatedValueError(value: 10))
        }
    }

    // if case pattern: useful if you have one or more associated values more or less complex (struct, classes...)
    func testFunctionThatThrows() {
        XCTAssertThrowsError(try functionThatThrows()) { error in
            guard case MyError.associatedValueError(let value) = error else {
                return XCTFail()
            }

            XCTAssertEqual(value, 10)
            // if you have several values or if they require more complex tests, you can do it here
        }
    }
46
Ferschae Naej

Au moins sur Xcode 7.3 (peut-être plus tôt), vous pouvez utiliser la fonction XCTAssertThrowsError() intégrée:

    XCTAssertThrowsError(try methodThatThrows())

Si rien n'est jeté pendant le test, vous verrez quelque chose comme ceci:

 enter image description here

Si vous voulez vérifier si l'erreur renvoyée est de type concret, vous pouvez utiliser le paramètre errorHandler de XCTAssertThrowsError():

    enum Error: ErrorType {
        case SomeExpectedError
        case SomeUnexpectedError
    }

    func functionThatThrows() throws {
        throw Error.SomeExpectedError
    }

    XCTAssertThrowsError(try functionThatThrows(), "some message") { (error) in
        XCTAssertEqual(error as? Error, Error.SomeExpectedError)
    }
18
Fyodor Volchyok

Étant donné les fonctions et déclarations suivantes:

enum SomeError: ErrorType {
    case FifthError
    case FirstError
}

func throwingFunction(x: Int) throws {
    switch x {
    case 1:
        throw SomeError.FirstError
    case 5:
        throw SomeError.FifthError
    default:
        return
    }
}

Cette fonction lancera une FifthError si 5 est donnée à la fonction et FirstError si 1 est donné.

Pour vérifier qu’une fonction exécute correctement le test unitaire, elle pourrait se présenter comme suit:

func testNotError() {
    guard let _ = try? throwingFunction(2) else {
        XCTFail("Error thrown")
        return
    }
}

Le let _ peut également être remplacé par tout autre nom, ce qui vous permet de tester davantage la sortie.

Pour affirmer qu'une fonction renvoie, peu importe la ErrorType, le test unitaire pourrait ressembler à ceci:

func testError() {
    if let _ = try? throwingFunction(5) {
        XCTFail("No error thrown")
        return
    }
}

Si vous voulez tester une ErrorType spécifique, utilisez une instruction do-catch-. Ce n'est pas la meilleure façon par rapport aux autres langues.

Vous devez vous assurer que vous ...

  • return dans catch pour le ErrorType correct
  • XCTFail() et return pour tous les autres catch
  • XCTFail() si aucune catch n'est exécutée

Étant donné ces exigences, un scénario de test pourrait ressembler à ceci:

func testFifthError() {
    do {
        try throwingFunction(5)
    } catch SomeError.FifthError {
        return
    } catch {
        XCTFail("Wrong error thrown")
        return
    }
    XCTFail("No error thrown")
}
10
Fabio Poloni

Swift 4.1 Erreur lors du test des valeurs associées

enum ParseError: Error, Equatable {
    case unexpectedArgument(String)
}

func testWithNoSchemaButWithOneArgument() {
    XCTAssertThrowsError(try Args(withSchema: "", andArguments: ["-x"])) { error in
        XCTAssertEqual(error as? ParseError, ParseError.unexpectedArgument("Argument(s) -x unexpected."))
    }
}
0
Declan McKenna