Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve failing log output of tests #840

Merged
merged 8 commits into from
Dec 2, 2016
10 changes: 7 additions & 3 deletions Tests/SwiftLintFrameworkTests/IntegrationTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,13 @@ class IntegrationTests: XCTestCase {

func testSwiftLintAutoCorrects() {
let swiftFiles = config.lintableFilesForPath("")
XCTAssertEqual(swiftFiles.flatMap({
Linter(file: $0, configuration: config).correct()
}), [])
let corrections = swiftFiles.flatMap { Linter(file: $0, configuration: config).correct() }
for correction in corrections {
correction.location.file!.withStaticString {
XCTFail(correction.ruleDescription.description,
file: $0, line: UInt(correction.location.line!))
}
}
}
}

Expand Down
73 changes: 62 additions & 11 deletions Tests/SwiftLintFrameworkTests/TestHelpers.swift
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,38 @@ private func cleanedContentsAndMarkerOffsets(from contents: String) -> (String,
return (contents as String, markerOffsets.sorted())
}

private func render(violations: [StyleViolation], in contents: String) -> String {
var contents = (contents as NSString).lines().map { $0.content }
for violation in violations.sorted(by: { $0.location > $1.location }) {
guard let line = violation.location.line,
let character = violation.location.character else { continue }

let message = String(repeating: " ", count: character - 1) + "^ " + [
"\(violation.severity.rawValue.lowercased()): ",
"\(violation.ruleDescription.name) Violation: ",
violation.reason,
" (\(violation.ruleDescription.identifier))"].joined()
if line >= contents.count {
contents.append(message)
} else {
contents.insert(message, at: line)
}
}
return (["```"] + contents + ["```"]).joined(separator: "\n")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't this equivalent and simpler?

return "```\n\(contents)\n```"

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

contents is [String].

}

private func render(locations: [Location], in contents: String) -> String {
var contents = (contents as NSString).lines().map { $0.content }
for location in locations.sorted(by: > ) {
guard let line = location.line, let character = location.character else { continue }
var content = contents[line - 1]
let index = content.index(content.startIndex, offsetBy: character - 1)
content.insert("↓", at: index)
contents[line - 1] = content
}
return (["```"] + contents + ["```"]).joined(separator: "\n")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't this equivalent and simpler?

return "```\n\(contents)\n```"

Copy link
Collaborator Author

@norio-nomura norio-nomura Dec 1, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here also contents is [String]

}

extension Configuration {
fileprivate func assertCorrection(_ before: String, expected: String) {
guard let path = NSURL(fileURLWithPath: NSTemporaryDirectory(), isDirectory: true)
Expand Down Expand Up @@ -105,32 +137,51 @@ extension XCTestCase {
let nonTriggers = ruleDescription.nonTriggeringExamples

// Non-triggering examples don't violate
XCTAssertEqual(nonTriggers.flatMap({ violations($0, config: config) }), [])
for nonTrigger in nonTriggers {
let unexpectedViolations = violations(nonTrigger, config: config)
if unexpectedViolations.isEmpty { continue }
let nonTriggerWithViolations = render(violations: unexpectedViolations, in: nonTrigger)
XCTFail("nonTriggeringExample violated: \n\(nonTriggerWithViolations)")
}

var violationsCount = 0
var expectedViolationsCount = 0
// Triggering examples violate
for trigger in triggers {
let triggerViolations = violations(trigger, config: config).sorted {
$0.location < $1.location
}
violationsCount += triggerViolations.count
let triggerViolations = violations(trigger, config: config)

// Triggering examples with violation markers violate at the marker's location
let (cleanTrigger, markerOffsets) = cleanedContentsAndMarkerOffsets(from: trigger)
if markerOffsets.isEmpty {
expectedViolationsCount += 1
if triggerViolations.isEmpty {
XCTFail("triggeringExample did not violate: \n```\n\(trigger)\n```")
}
continue
}
expectedViolationsCount += markerOffsets.count
let file = File(contents: cleanTrigger)
let expectedLocations = markerOffsets.map { Location(file: file, characterOffset: $0) }

// Assert violations on unexpected location
let violationsAtUnexpectedLocation = triggerViolations
.filter { !expectedLocations.contains($0.location) }
if !violationsAtUnexpectedLocation.isEmpty {
XCTFail("triggeringExample violate at unexpected location: \n" +
"\(render(violations: violationsAtUnexpectedLocation, in: trigger))")
}

// Assert locations missing vaiolation
let violatedLocations = triggerViolations.map { $0.location }
let locationsWithoutViolation = expectedLocations
.filter { !violatedLocations.contains($0) }
if !locationsWithoutViolation.isEmpty {
XCTFail("triggeringExample did not violate at expected location: \n" +
"\(render(locations: locationsWithoutViolation, in: cleanTrigger))")
}

XCTAssertEqual(triggerViolations.count, expectedLocations.count)
for (triggerViolation, expectedLocation) in zip(triggerViolations, expectedLocations) {
XCTAssertEqual(triggerViolation.location, expectedLocation,
"'\(trigger)' violation didn't match expected location.")
}
}
// Triggering examples violate
XCTAssertEqual(violationsCount, expectedViolationsCount)

// Comment doesn't violate
XCTAssertEqual(
Expand Down