Here's an example of some test code for a crossword project I worked on. (Blah blah views blah blah employer, this was a side project.)
This code tests arrow-key movement in a crossword grid. Inside each Pair
is an input (a board selection state plus a movement direction) and an output (a resulting board selection state). The assertCustom
function comes from TestCleaner, and handles some boilerplate around unwrapping the test values and keeping track of what lines they came from so we can forward those to XCTAssert*
.
// n.b. 'S' and 'C' are local test utility functions to make Selection and Coordinate values.
let testCases: [TestPair<(Selection?, MovementDirection), Selection?>] = [
// Invalid state. Jump to top left corner.
Pair((S(blackSquare, .horizontal), .up), S(upperLeftCorner, .horizontal)),
Pair((S(blackSquare, .horizontal), .down), S(upperLeftCorner, .horizontal)),
Pair((S(blackSquare, .horizontal), .left), S(upperLeftCorner, .horizontal)),
Pair((S(blackSquare, .horizontal), .right), S(upperLeftCorner, .horizontal)),
/* ✂️ snip about 80 similar lines ✂️ */
// End of 29 Down
Pair((S(endOfTwentyNineDown, .vertical), .up), S(C(col: 7, row: 8), .vertical)),
Pair((S(endOfTwentyNineDown, .vertical), .down), S(C(col: 8, row: 5), .vertical)),
Pair((S(endOfTwentyNineDown, .vertical), .left), S(endOfTwentyNineDown, .horizontal)),
Pair((S(endOfTwentyNineDown, .vertical), .right), S(endOfTwentyNineDown, .horizontal)),
]
assertCustom(testCases: testCases) { (pair, file, line) in
let ((selection, direction), expectedResult) = try (pair.left, pair.right)
// 👀 This is the actual function being tested
let next = nextSelection(from: selection, direction: direction, puzzle: initialState.puzzle)
// ✅ And here's the assertion
XCTAssertEqual(next, expectedResult, file: file, line: line)
}