Skip to content

Commit c2d8414

Browse files
authored
Refactor dump help tests (#696)
The dump help tests previously included the json text in the Swift source files as multiline strings. This made updating them very tedious and made diffs hard to follow. This commit moves each of the json dumps into their own files and adds an easy way of recording new ones as needed.
1 parent 9289e31 commit c2d8414

38 files changed

+2867
-2983
lines changed

Package.swift

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -98,10 +98,12 @@ var package = Package(
9898
resources: [.copy("CountLinesTest.txt")]),
9999
.testTarget(
100100
name: "ArgumentParserGenerateDoccReferenceTests",
101-
dependencies: ["ArgumentParserTestHelpers"]),
101+
dependencies: ["ArgumentParserTestHelpers"],
102+
exclude: ["Snapshots"]),
102103
.testTarget(
103104
name: "ArgumentParserGenerateManualTests",
104-
dependencies: ["ArgumentParserTestHelpers"]),
105+
dependencies: ["ArgumentParserTestHelpers"],
106+
exclude: ["Snapshots"]),
105107
.testTarget(
106108
name: "ArgumentParserPackageManagerTests",
107109
dependencies: ["ArgumentParser", "ArgumentParserTestHelpers"],
@@ -113,7 +115,7 @@ var package = Package(
113115
.testTarget(
114116
name: "ArgumentParserUnitTests",
115117
dependencies: ["ArgumentParser", "ArgumentParserTestHelpers"],
116-
exclude: ["CMakeLists.txt"]),
118+
exclude: ["CMakeLists.txt", "Snapshots"]),
117119
]
118120
)
119121

[email protected]

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -99,10 +99,12 @@ var package = Package(
9999
resources: [.copy("CountLinesTest.txt")]),
100100
.testTarget(
101101
name: "ArgumentParserGenerateDoccReferenceTests",
102-
dependencies: ["ArgumentParserTestHelpers"]),
102+
dependencies: ["ArgumentParserTestHelpers"],
103+
exclude: ["Snapshots"]),
103104
.testTarget(
104105
name: "ArgumentParserGenerateManualTests",
105-
dependencies: ["ArgumentParserTestHelpers"]),
106+
dependencies: ["ArgumentParserTestHelpers"],
107+
exclude: ["Snapshots"]),
106108
.testTarget(
107109
name: "ArgumentParserPackageManagerTests",
108110
dependencies: ["ArgumentParser", "ArgumentParserTestHelpers"],
@@ -114,7 +116,7 @@ var package = Package(
114116
.testTarget(
115117
name: "ArgumentParserUnitTests",
116118
dependencies: ["ArgumentParser", "ArgumentParserTestHelpers"],
117-
exclude: ["CMakeLists.txt"]),
119+
exclude: ["CMakeLists.txt", "Snapshots"]),
118120
]
119121
)
120122

Sources/ArgumentParserTestHelpers/TestHelpers.swift

Lines changed: 121 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -269,33 +269,6 @@ public func AssertHelp<T: ParsableCommand, U: ParsableCommand>(
269269
AssertEqualStrings(actual: helpString, expected: expected, file: file, line: line)
270270
}
271271

272-
public func AssertDump<T: ParsableArguments>(
273-
for _: T.Type, equals expected: String,
274-
file: StaticString = #filePath, line: UInt = #line
275-
) throws {
276-
do {
277-
_ = try T.parse(["--experimental-dump-help"])
278-
XCTFail(file: file, line: line)
279-
} catch {
280-
let dumpString = T.fullMessage(for: error)
281-
try AssertJSONEqualFromString(actual: dumpString, expected: expected, for: ToolInfoV0.self, file: file, line: line)
282-
}
283-
284-
try AssertJSONEqualFromString(actual: T._dumpHelp(), expected: expected, for: ToolInfoV0.self, file: file, line: line)
285-
}
286-
287-
public func AssertJSONEqualFromString<T: Codable & Equatable>(actual: String, expected: String, for type: T.Type, file: StaticString = #filePath, line: UInt = #line) throws {
288-
if #available(macOS 10.13, iOS 11.0, tvOS 11.0, watchOS 4.0, *) {
289-
AssertEqualStrings(actual: actual, expected: expected, file: file, line: line)
290-
}
291-
292-
let actualJSONData = try XCTUnwrap(actual.data(using: .utf8), file: file, line: line)
293-
let actualDumpJSON = try XCTUnwrap(JSONDecoder().decode(type, from: actualJSONData), file: file, line: line)
294-
295-
let expectedJSONData = try XCTUnwrap(expected.data(using: .utf8), file: file, line: line)
296-
let expectedDumpJSON = try XCTUnwrap(JSONDecoder().decode(type, from: expectedJSONData), file: file, line: line)
297-
XCTAssertEqual(actualDumpJSON, expectedDumpJSON)
298-
}
299272

300273
extension XCTest {
301274
public var debugURL: URL {
@@ -304,13 +277,15 @@ extension XCTest {
304277
? bundleURL.deletingLastPathComponent()
305278
: bundleURL
306279
}
307-
280+
281+
@discardableResult
308282
public func AssertExecuteCommand(
309283
command: String,
310284
expected: String? = nil,
311285
exitCode: ExitCode = .success,
312-
file: StaticString = #filePath, line: UInt = #line) throws
313-
{
286+
file: StaticString = #filePath,
287+
line: UInt = #line
288+
) throws -> String {
314289
try AssertExecuteCommand(
315290
command: command.split(separator: " ").map(String.init),
316291
expected: expected,
@@ -319,12 +294,14 @@ extension XCTest {
319294
line: line)
320295
}
321296

297+
@discardableResult
322298
public func AssertExecuteCommand(
323299
command: [String],
324300
expected: String? = nil,
325301
exitCode: ExitCode = .success,
326-
file: StaticString = #filePath, line: UInt = #line) throws
327-
{
302+
file: StaticString = #filePath,
303+
line: UInt = #line
304+
) throws -> String {
328305
#if os(Windows)
329306
throw XCTSkip("Unsupported on this platform")
330307
#endif
@@ -335,7 +312,7 @@ extension XCTest {
335312
guard (try? commandURL.checkResourceIsReachable()) ?? false else {
336313
XCTFail("No executable at '\(commandURL.standardizedFileURL.path)'.",
337314
file: file, line: line)
338-
return
315+
return ""
339316
}
340317

341318
#if !canImport(Darwin) || os(macOS)
@@ -355,7 +332,7 @@ extension XCTest {
355332
if #available(macOS 10.13, *) {
356333
guard (try? process.run()) != nil else {
357334
XCTFail("Couldn't run command process.", file: file, line: line)
358-
return
335+
return ""
359336
}
360337
} else {
361338
process.launch()
@@ -380,65 +357,14 @@ extension XCTest {
380357
#else
381358
throw XCTSkip("Not supported on this platform")
382359
#endif
383-
}
384-
385-
public func AssertJSONOutputEqual(
386-
command: String,
387-
expected: String,
388-
file: StaticString = #filePath,
389-
line: UInt = #line
390-
) throws {
391-
#if os(Windows)
392-
throw XCTSkip("Unsupported on this platform")
393-
#endif
394-
395-
let splitCommand = command.split(separator: " ")
396-
let arguments = splitCommand.dropFirst().map(String.init)
397-
398-
let commandName = String(splitCommand.first!)
399-
let commandURL = debugURL.appendingPathComponent(commandName)
400-
guard (try? commandURL.checkResourceIsReachable()) ?? false else {
401-
XCTFail("No executable at '\(commandURL.standardizedFileURL.path)'.",
402-
file: file, line: line)
403-
return
404-
}
405-
406-
#if !canImport(Darwin) || os(macOS)
407-
let process = Process()
408-
if #available(macOS 10.13, *) {
409-
process.executableURL = commandURL
410-
} else {
411-
process.launchPath = commandURL.path
412-
}
413-
process.arguments = arguments
414-
415-
let output = Pipe()
416-
process.standardOutput = output
417-
let error = Pipe()
418-
process.standardError = error
419-
420-
if #available(macOS 10.13, *) {
421-
guard (try? process.run()) != nil else {
422-
XCTFail("Couldn't run command process.", file: file, line: line)
423-
return
424-
}
425-
} else {
426-
process.launch()
427-
}
428-
process.waitUntilExit()
429-
430-
let outputString = try XCTUnwrap(String(data: output.fileHandleForReading.readDataToEndOfFile(), encoding: .utf8))
431-
XCTAssertTrue(error.fileHandleForReading.readDataToEndOfFile().isEmpty, "Error occurred with `--experimental-dump-help`")
432-
try AssertJSONEqualFromString(actual: outputString, expected: expected, for: ToolInfoV0.self, file: file, line: line)
433-
#else
434-
throw XCTSkip("Not supported on this platform")
435-
#endif
360+
return outputActual
436361
}
437362

438363
public func AssertGenerateManual(
439364
multiPage: Bool,
440365
command: String,
441-
expected: String,
366+
expected: URL,
367+
record: Bool = false,
442368
file: StaticString = #filePath,
443369
line: UInt = #line
444370
) throws {
@@ -459,17 +385,29 @@ extension XCTest {
459385
if multiPage {
460386
command.append("--multi-page")
461387
}
462-
try AssertExecuteCommand(
388+
let actual = try AssertExecuteCommand(
463389
command: command,
464-
expected: expected,
465-
exitCode: .success,
466390
file: file,
467391
line: line)
392+
393+
if record || !FileManager.default.fileExists(atPath: expected.path) {
394+
let recordedValue = actual + "\n"
395+
try recordedValue.write(to: expected, atomically: true, encoding: .utf8)
396+
XCTFail("Recorded new baseline", file: file, line: line)
397+
} else {
398+
let expected = try String(contentsOf: expected, encoding: .utf8)
399+
AssertEqualStrings(
400+
actual: actual,
401+
expected: expected.trimmingCharacters(in: .whitespacesAndNewlines),
402+
file: file,
403+
line: line)
404+
}
468405
}
469406

470407
public func AssertGenerateDoccReference(
471408
command: String,
472-
expected: String,
409+
expected: URL,
410+
record: Bool = false,
473411
file: StaticString = #filePath,
474412
line: UInt = #line
475413
) throws {
@@ -482,11 +420,99 @@ extension XCTest {
482420
"generate-docc-reference", commandURL.path,
483421
"--output-directory", "-",
484422
]
485-
try AssertExecuteCommand(
423+
let actual = try AssertExecuteCommand(
486424
command: command,
487-
expected: expected,
488-
exitCode: .success,
489425
file: file,
490426
line: line)
427+
if record || !FileManager.default.fileExists(atPath: expected.path) {
428+
let recordedValue = actual + "\n"
429+
try recordedValue.write(to: expected, atomically: true, encoding: .utf8)
430+
XCTFail("Recorded new baseline", file: file, line: line)
431+
} else {
432+
let expected = try String(contentsOf: expected, encoding: .utf8)
433+
AssertEqualStrings(
434+
actual: actual,
435+
expected: expected.trimmingCharacters(in: .whitespacesAndNewlines),
436+
file: file,
437+
line: line)
438+
}
439+
}
440+
441+
public func AssertDump<T: ParsableArguments>(
442+
type: T.Type,
443+
expected: URL,
444+
record: Bool = false,
445+
file: StaticString = #filePath,
446+
line: UInt = #line
447+
) throws {
448+
let cliOutput: String
449+
do {
450+
_ = try T.parse(["--experimental-dump-help"])
451+
XCTFail(file: file, line: line)
452+
return
453+
} catch {
454+
cliOutput = T.fullMessage(for: error)
455+
}
456+
457+
let apiOutput = T._dumpHelp()
458+
AssertEqualStrings(actual: cliOutput, expected: apiOutput)
459+
460+
if record || !FileManager.default.fileExists(atPath: expected.path) {
461+
let recordedValue = apiOutput + "\n"
462+
try recordedValue.write(to: expected, atomically: true, encoding: .utf8)
463+
XCTFail("Recorded new baseline", file: file, line: line)
464+
} else {
465+
let expected = try String(contentsOf: expected, encoding: .utf8)
466+
try AssertJSONEqualFromString(
467+
actual: apiOutput,
468+
expected: expected,
469+
for: ToolInfoV0.self,
470+
file: file,
471+
line: line)
472+
}
473+
}
474+
475+
public func AssertDump(
476+
command: String,
477+
expected: URL,
478+
record: Bool = false,
479+
file: StaticString = #filePath,
480+
line: UInt = #line
481+
) throws {
482+
let actual = try AssertExecuteCommand(
483+
command: command + " --experimental-dump-help",
484+
expected: nil,
485+
file: file,
486+
line: line)
487+
if record || !FileManager.default.fileExists(atPath: expected.path) {
488+
let recordedValue = actual + "\n"
489+
try recordedValue.write(to: expected, atomically: true, encoding: .utf8)
490+
XCTFail("Recorded new baseline", file: file, line: line)
491+
} else {
492+
let expected = try String(contentsOf: expected, encoding: .utf8)
493+
try AssertJSONEqualFromString(
494+
actual: actual,
495+
expected: expected,
496+
for: ToolInfoV0.self,
497+
file: file,
498+
line: line)
499+
}
500+
}
501+
502+
public func AssertJSONEqualFromString<T: Codable & Equatable>(actual: String, expected: String, for type: T.Type, file: StaticString = #filePath, line: UInt = #line) throws {
503+
if #available(macOS 10.13, iOS 11.0, tvOS 11.0, watchOS 4.0, *) {
504+
AssertEqualStrings(
505+
actual: actual.trimmingCharacters(in: .whitespacesAndNewlines),
506+
expected: expected.trimmingCharacters(in: .whitespacesAndNewlines),
507+
file: file,
508+
line: line)
509+
}
510+
511+
let actualJSONData = try XCTUnwrap(actual.data(using: .utf8), file: file, line: line)
512+
let actualDumpJSON = try XCTUnwrap(JSONDecoder().decode(type, from: actualJSONData), file: file, line: line)
513+
514+
let expectedJSONData = try XCTUnwrap(expected.data(using: .utf8), file: file, line: line)
515+
let expectedDumpJSON = try XCTUnwrap(JSONDecoder().decode(type, from: expectedJSONData), file: file, line: line)
516+
XCTAssertEqual(actualDumpJSON, expectedDumpJSON)
491517
}
492518
}

Tests/ArgumentParserGenerateDoccReferenceTests/ColorGenerateDoccReferenceTests.swift

Lines changed: 0 additions & 44 deletions
This file was deleted.

0 commit comments

Comments
 (0)