Skip to content

Latest commit

 

History

History
138 lines (112 loc) · 4.51 KB

tests.md

File metadata and controls

138 lines (112 loc) · 4.51 KB

Testing Apexy

What to test?

You can test all the Endpoints and models which contain business logic.

Endpoint

In the case of Endpoint, test how it creates the URLRequest object (method makeRequest):

  • HTTP method
  • URL address
  • HTTP Body
  • HTTP headers

Example

There is a BookListEndpoint in the example project. This endpoint is used to obtain a list of books. The following example shows how to test this Endpoint.

import ExampleAPI
import XCTest

final class BookListEndpointTests: XCTestCase {

    func testMakeRequest() throws {
        let endpoint = BookListEndpoint()

        let urlRequest = try endpoint.makeRequest()
        
        XCTAssertEqual(urlRequest.httpMethod, "GET")
        XCTAssertNil(urlRequest.httpBody)
        XCTAssertEqual(urlRequest.url?.absoluteString, "books")
    }
}

This test checks that:

  • HTTP method equals to "GET"
  • HTTP body doesn't exist
  • URL equals to "books"

Model

If a model object contains business logic, then this object must be tested. For example, if a model object has computed properties where data is formatted.

You can also test the decoding of a model object in the case of complex transformations, for example, converting a string to a date.

/// An abstract access code that has an expiration date
struct Code: Decodable, Equatable {
    /// Code value, e.g. "1234"
    let code: String
    /// Code expiration date
    let endDate: Date
}

final class CodeTests: XCTestCase {

    func testDecode() throws {
        let json = """
        {
            "code": "1234",
            "end_date": "2019-03-21T13:13:36Z"
        }
        """.data(using: .utf8)!

        let code = try JSONDecoder().decode(Code.self, from: json)

        XCTAssertEqual(
            code.endDate,
            makeDate(year: 2019, month: 3, day: 21, hour: 13, minute: 13, second: 36))
    }

    private func makeDate(year: Int, month: Int, day: Int, hour: Int, minute: Int, second: Int) -> Date {
        return DateComponents(
            calendar: .current,
            timeZone: TimeZone(secondsFromGMT: 0),
            year: year, month: month, day: day,
            hour: hour, minute: minute, second: second).date!
    }
}

Helpers

The following helpers can be used to improve readability and reduce the amount of code in tests:

Asserts.swift

func assertGET(_ urlRequest: URLRequest, file: StaticString = #file, line: UInt = #line) {
    guard let method = urlRequest.httpMethod else {
        return XCTFail("The request does not contains HTTP method", file: file, line: line)
    }
    XCTAssertEqual(method, "GET", file: file, line: line)
    XCTAssertNil(urlRequest.httpBody, "GET request must not contains body", file: file, line: line)
}

func assertPOST(_ urlRequest: URLRequest, file: StaticString = #file, line: UInt = #line) {
    guard let method = urlRequest.httpMethod else {
        return XCTFail("The request does not contains HTTP method", file: file, line: line)
    }
    XCTAssertEqual(method, "POST", file: file, line: line)
}

func assertDELETE(_ urlRequest: URLRequest, file: StaticString = #file, line: UInt = #line) {
    guard let method = urlRequest.httpMethod else {
        return XCTFail("The request does not contains HTTP method", file: file, line: line)
    }
    XCTAssertEqual(method, "DELETE", file: file, line: line)
}

func assertPATCH(_ urlRequest: URLRequest, file: StaticString = #file, line: UInt = #line) {
    guard let method = urlRequest.httpMethod else {
        return XCTFail("The request does not contains HTTP method", file: file, line: line)
    }
    XCTAssertEqual(method, "PATCH", file: file, line: line)
}

func assertPath(_ urlRequest: URLRequest, _ path: String, file: StaticString = #file, line: UInt = #line) {
    guard let url = urlRequest.url else {
        return XCTFail("The request does not contains HTTP method", file: file, line: line)
    }
    XCTAssertEqual(url.path, path, "Paths does not equal", file: file, line: line)
}

func assertURL(_ urlRequest: URLRequest, _ urlString: String, file: StaticString = #file, line: UInt = #line) {
    guard let url = urlRequest.url else {
        return XCTFail("The request does not contains HTTP method", file: file, line: line)
    }
    XCTAssertEqual(url.absoluteString, urlString, "URLs does not equal", file: file, line: line)
}

The example above could be written like this:

func testMakeRequest() throws {
    let endpoint = BookListEndpoint()
    let urlRequest = try endpoint.makeRequest()
    
    assertGET(urlRequest)
    assertURL(urlRequest, "books")
}