Skip to content

Instantly share code, notes, and snippets.

@junebash
Created July 29, 2020 23:45
Show Gist options
  • Save junebash/6da6efdd3a1bd9e62a994ef72bdcea67 to your computer and use it in GitHub Desktop.
Save junebash/6da6efdd3a1bd9e62a994ef72bdcea67 to your computer and use it in GitHub Desktop.

Revisions

  1. Jon Bash created this gist Jul 29, 2020.
    116 changes: 116 additions & 0 deletions CodeChallengeTestCases.swift
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,116 @@
    struct CodeChallengeTestCases<Input, Output> {
    var title: String?
    var expected: KeyValuePairs<Input, Output>
    var solution: (Input) -> Output

    init(
    title: String? = nil,
    expected: KeyValuePairs<Input, Output> = [:],
    solution: @escaping (Input) -> Output)
    {
    self.title = title
    self.expected = expected
    self.solution = solution
    }
    }

    extension CodeChallengeTestCases {
    struct Failure {
    let input: Input
    let expectedOutput: Output
    let actualOutput: Output

    func print() {
    Swift.print("Input: \t\(input)\n"
    + "Expected: \t\(expectedOutput)\n"
    + "Actual output:\t\(actualOutput)"
    )
    }
    }

    var isEmpty: Bool { expected.isEmpty }

    func evaluate(_ outputEqualsExpected: (Output, Output) -> Bool) -> [Failure] {
    expected.compactMap { ioPair -> Failure? in
    let o = output(for: ioPair.key)
    let e = ioPair.value

    if outputEqualsExpected(o, e) {
    return nil
    } else {
    return Failure(input: ioPair.key, expectedOutput: e, actualOutput: o)
    }
    }
    }

    func printFailures(_ outputEqualsExpected: (Output, Output) -> Bool) {
    printFailures(evaluate(outputEqualsExpected))
    }

    func printFailures(_ failures: [Failure]) {
    let titleText = title ?? "\(Input.self) -> \(Output.self)"

    if failures.isEmpty {
    print("All tests passed for '\(titleText)'!\n")
    return
    }

    print("Tests failed for '\(titleText)':")
    for f in failures {
    printEvaluation(for: f.input,
    expected: f.expectedOutput,
    actual: f.actualOutput)
    }
    print("\n----------------\n")
    }

    func printEvaluations() {
    expected.forEach { ioPair in
    printEvaluation(for: ioPair.key,
    expected: ioPair.value,
    actual: solution(ioPair.key))
    }
    }
    }

    extension CodeChallengeTestCases where Output: Equatable {
    func evaluate() -> [Failure] {
    evaluate { $0 == $1 }
    }

    func printFailures() {
    printFailures { $0 == $1 }
    }
    }

    extension CodeChallengeTestCases {
    private func output(for input: Input) -> Output {
    solution(input)
    }

    private func printEvaluation(
    for input: Input,
    expected: Output,
    actual: Output)
    {
    print("Input: \t\(input)\n"
    + "Expected: \t\(expected)\n"
    + "Actual output:\t\(actual)"
    )
    }
    }

    extension Array {
    func print<I, O>() where Element == CodeChallengeTestCases<I, O>.Failure {
    let titleText = "\(I.self) -> \(O.self)"

    if self.isEmpty {
    Swift.print("All tests passed for '\(titleText)'!\n")
    return
    }

    Swift.print("Tests failed for '\(titleText)':")
    self.forEach { $0.print() }
    Swift.print("\n----------------\n")
    }
    }