Как выполнить функции тестового броска в Swift?

Как протестировать функцию в Swift 2.0 бросках или нет? Как утверждать, что ErrorType правильный ErrorType?

Ответы

Ответ 1

EDIT: обновлен код для Swift 4.1.

Здесь последняя версия Swift Fyodor Volchyok отвечает, кто использовал 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)
        }
    }

Если в вашем перечислении Error указаны связанные значения, вы можете либо перечислить Error в Equatable, либо использовать оператор 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
        }
    }

Ответ 2

По крайней мере, в Xcode 7.3 (возможно, раньше) вы могли бы использовать встроенный XCTAssertThrowsError():

XCTAssertThrowsError(try methodThatThrows())

Если во время теста ничего не выдается, вы увидите что-то вроде этого:

enter image description here

Если вы хотите проверить, имеет ли выброшенная ошибка какой-то конкретный тип, вы можете использовать параметр errorHandler в 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)
}

Ответ 3

Учитывая следующие функции и декларации:

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
    }
}

Эта функция FifthError если 5 дается функции и FirstError если FirstError 1.

Чтобы проверить, что функция успешно запускает unit тест, может выглядеть следующим образом:

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

let _ также может быть заменено любым другим именем, поэтому вы можете дополнительно проверить результат.

Чтобы утверждать, что функция выбрасывает, независимо от того, какой ErrorType может выглядеть так:

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

Если вы хотите протестировать конкретный ErrorType это делается с помощью do-catch -statement. Это не лучший способ по сравнению с другими языками.

Вы должны убедиться, что вы...

  • return в catch для правильного типа ErrorType
  • XCTFail() и return для всех остальных catch
  • XCTFail() если catch не выполняется

Учитывая эти требования, тестовый пример может выглядеть так:

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

Ответ 4

Swift 4.1 Ошибка метания теста для связанных значений

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."))
    }
}

Ответ 5

Вы можете использовать эту функцию:

func XCTAssertThrowsError<T, E: Error & Equatable>(
  _ expression: @autoclosure () throws -> T,
  error: E,
  in file: StaticString = #file,
  line: UInt = #line
  ) {
  var thrownError: Error?
  XCTAssertThrowsError(
    try expression(),
    file: file,
    line: line) {
      thrownError = $0
  }

  XCTAssertTrue(
    thrownError is E,
    "Unexpected error type: \(type(of: thrownError))",
    file: file,
    line: line
  )

  XCTAssertEqual(
    thrownError as? E,
    error,
    file: file,
    line: line
  )
}

Пример:

XCTAssertThrowsError(try funcThatThrowsSpecificError(), error: SpecificErrorEnum.someError)