spy let points: [CGPoint] = [ CGPoint(x: 0, y: 0), CGPoint(x: 10, y: 0), CGPoint(x: 10, y: 10), CGPoint(x: 0, y: 10), CGPoint(x: 0, y: 0) ] let rect = CGRect( origin: .zero, size: CGSize(width: 1, height: 1) ) var respectedTuples: NSMutableArray = [] // 1 touch - expect 1 point tuple sut.startTouching(points[0], in: rect) sut.touchEnd() respectedTuples = [NSValue(cgPoint: points[0])] XCTAssertEqual(spy.storageStroke?.pathTuples, respectedTuples) // 2 touches - expect 2 point tuples sut.startTouching(points[0], in: rect) sut.touchesMoved(points[1], in: rect) sut.touchEnd() respectedTuples = [ NSValue(cgPoint: points[0]), NSValue(cgPoint: points[1]) ] XCTAssertEqual(spy.storageStroke?.pathTuples, respectedTuples) // 3 touches - expect 1 point and 1 array(2) tuples sut.startTouching(points[0], in: rect) sut.touchesMoved(points[1], in: rect) sut.touchesMoved(points[2], in: rect) sut.touchEnd() respectedTuples = [ NSValue(cgPoint: points[0]), [ NSValue(cgPoint: points[1]), NSValue(cgPoint: points[2]) ] ] XCTAssertEqual(spy.storageStroke?.pathTuples, respectedTuples) // 4 touches - expect 1 point and 1 array(3) tuples sut.startTouching(points[0], in: rect) sut.touchesMoved(points[1], in: rect) sut.touchesMoved(points[2], in: rect) sut.touchesMoved(points[3], in: rect) sut.touchEnd() respectedTuples = [ NSValue(cgPoint: points[0]), [ NSValue(cgPoint: points[1]), NSValue(cgPoint: points[2]), NSValue(cgPoint: points[3]) ] ] XCTAssertEqual(spy.storageStroke?.pathTuples, respectedTuples) // 5 touches - expect 2 point and 1 array(3) tuples sut.startTouching(points[0], in: rect) sut.touchesMoved(points[1], in: rect) sut.touchesMoved(points[2], in: rect) sut.touchesMoved(points[3], in: rect) sut.touchesMoved(points[4], in: rect) sut.touchEnd() // In the current behavior, we'll adjust the 4th point to be the average of the 3rd and 5th. let forthPoint = CGPoint( x: (points[2].x + points[4].x) / 2, y: (points[2].y + points[4].y) / 2 ) respectedTuples = [ NSValue(cgPoint: points[0]), [ NSValue(cgPoint: points[1]), NSValue(cgPoint: points[2]), NSValue(cgPoint: forthPoint) ], NSValue(cgPoint: points[4]) ] XCTAssertEqual(spy.storageStroke?.pathTuples, respectedTuples) } And so on …