Comment tester les fonctions de lancement dans Swift?

Comment tester si une fonction dans Swift 2.0 jette ou non? Comment affirmer que le bon ErrorType est lancé?

21
demandé sur Fabio Poloni 2015-09-30 10:30:54

4 réponses

EDIT: mise à jour du code pour Swift 4.1.

Voici la dernière version Swift de la 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 Error enum a des valeurs associées, vous pouvez soit faire en sorte que votre Error enum soit conforme à Equatable, soit 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
        }
    }
37
répondu Ferschae Naej 2018-05-14 07:06:33

Au moins de Xcode 7.3 (peut-être plus tôt) vous pouvez utiliser intégré XCTAssertThrowsError():

    XCTAssertThrowsError(try methodThatThrows())

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

entrez la description de l'image ici

Si vous voulez vérifier si l'erreur levée est d'un type concret, vous pouvez utiliser errorHandler paramètre 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)
    }
14
répondu Fyodor Volchyok 2016-03-24 07:45:29

É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 va jeter un FifthError si 5 est donnée à la fonction et FirstError si 1 est donné.

Pour tester, qu'une fonction exécute avec succès le test unitaire pourrait ressembler à ceci:

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

Le let _ peut également être remplacé par n'importe quel autre nom, de sorte que vous pouvez tester davantage la sortie.

Pour affirmer qu'une fonction lance, peu importe ce que ErrorType le test unitaire pourrait ressembler à ceci:

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

Si vous voulez pour tester un ErrorType spécifique, c'est fait avec 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 le catch pour le corriger ErrorType
  • XCTFail() et return pour tous les autres catch
  • XCTFail() si aucun catch n'est exécuté

Compte tenu de ces exigences, un cas 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
répondu Fabio Poloni 2015-09-30 07:30:54

Test de lancement D'erreur Swift 4.1 pour les 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
répondu Deco 2018-05-13 12:00:16