Skip to content

Adopt Swift Testing #6048

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

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .swift-format
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"indentation" : {
"spaces" : 4
},
"lineLength": 120,
"rules" : {
"NoAccessLevelOnExtensionDeclaration": false
}
}
3 changes: 2 additions & 1 deletion Source/SwiftLintCoreMacros/RuleConfigurationMacros.swift
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,8 @@ enum AutoConfigParser: MemberMacro {
"""
do {
try \(raw: option).apply(configuration, ruleID: Parent.identifier)
} catch let issue as Issue where issue == Issue.nothingApplied(ruleID: Parent.identifier) {
} catch let issue as SwiftLintCore.Issue
where issue == Issue.nothingApplied(ruleID: Parent.identifier) {
// Acceptable. Continue.
}
"""
Expand Down
33 changes: 18 additions & 15 deletions Tests/FrameworkTests/AccessControlLevelTests.swift
Original file line number Diff line number Diff line change
@@ -1,21 +1,24 @@
import SwiftLintCore
import XCTest
import Testing

final class AccessControlLevelTests: SwiftLintTestCase {
func testDescription() {
XCTAssertEqual(AccessControlLevel.private.description, "private")
XCTAssertEqual(AccessControlLevel.fileprivate.description, "fileprivate")
XCTAssertEqual(AccessControlLevel.internal.description, "internal")
XCTAssertEqual(AccessControlLevel.package.description, "package")
XCTAssertEqual(AccessControlLevel.public.description, "public")
XCTAssertEqual(AccessControlLevel.open.description, "open")
@Suite
struct AccessControlLevelTests {
@Test
func description() {
#expect(AccessControlLevel.private.description == "private")
#expect(AccessControlLevel.fileprivate.description == "fileprivate")
#expect(AccessControlLevel.internal.description == "internal")
#expect(AccessControlLevel.package.description == "package")
#expect(AccessControlLevel.public.description == "public")
#expect(AccessControlLevel.open.description == "open")
}

func testPriority() {
XCTAssertLessThan(AccessControlLevel.private, .fileprivate)
XCTAssertLessThan(AccessControlLevel.fileprivate, .internal)
XCTAssertLessThan(AccessControlLevel.internal, .package)
XCTAssertLessThan(AccessControlLevel.package, .public)
XCTAssertLessThan(AccessControlLevel.public, .open)
@Test
func priority() {
#expect(AccessControlLevel.private < .fileprivate)
#expect(AccessControlLevel.fileprivate < .internal)
#expect(AccessControlLevel.internal < .package)
#expect(AccessControlLevel.package < .public)
#expect(AccessControlLevel.public < .open)
}
}
186 changes: 99 additions & 87 deletions Tests/FrameworkTests/BaselineTests.swift
Original file line number Diff line number Diff line change
@@ -1,44 +1,63 @@
import Foundation
import Testing

@testable import SwiftLintBuiltInRules
@testable import SwiftLintCore
import XCTest

private var temporaryDirectoryPath: String {
let result = URL(
fileURLWithPath: NSTemporaryDirectory(),
isDirectory: true
).path

#if os(macOS)
return "/private" + result
#else
return result
#endif

private let currentDirectory = FileManager.default.currentDirectoryPath

struct ResetCurrentDirectory: TestScoping, TestTrait {
private var temporaryDirectoryPath: String {
let result = URL(
fileURLWithPath: NSTemporaryDirectory(),
isDirectory: true
).path

#if os(macOS)
return "/private" + result
#else
return result
#endif
}

func provideScope(
for test: Test,
testCase: Test.Case?,
performing function: () async throws -> Void
) async throws {
#expect(FileManager.default.changeCurrentDirectoryPath(temporaryDirectoryPath))
defer {
#expect(FileManager.default.changeCurrentDirectoryPath(currentDirectory))
}
try await function()
}
}

final class BaselineTests: XCTestCase {
@Suite(.rulesRegistered)
struct BaselineTests {
private static let example = """
import Foundation
import SwiftLintFramework

class Example: NSObject {
private var foo: Int
private var bar: String

init(foo: Int, bar: String) {
self.foo = foo
self.bar = bar
} // init
func someFunction() -> Int {
foo * 10
} // someFunction
func someOtherFunction() -> String {
bar
} // someOtherFunction
func yetAnotherFunction() -> (Int, String) {
(foo, bar)
} // yetAnotherFunction
}
"""
import Foundation
import SwiftLintFramework

class Example: NSObject {
private var foo: Int
private var bar: String

init(foo: Int, bar: String) {
self.foo = foo
self.bar = bar
} // init
func someFunction() -> Int {
foo * 10
} // someFunction
func someOtherFunction() -> String {
bar
} // someOtherFunction
func yetAnotherFunction() -> (Int, String) {
(foo, bar)
} // yetAnotherFunction
}
"""

private static let ruleDescriptions = [
ArrayInitRule.description,
Expand All @@ -47,10 +66,6 @@ final class BaselineTests: XCTestCase {
DirectReturnRule.description,
]

private actor CurrentDirectoryHolder {
static var currentDirectoryPath: String?
}

private static func violations(for filePath: String?) -> [StyleViolation] {
ruleDescriptions.violations(for: filePath)
}
Expand All @@ -59,55 +74,56 @@ final class BaselineTests: XCTestCase {
Baseline(violations: ruleDescriptions.violations(for: filePath))
}

override static func setUp() {
super.setUp()
CurrentDirectoryHolder.currentDirectoryPath = FileManager.default.currentDirectoryPath
XCTAssertTrue(FileManager.default.changeCurrentDirectoryPath(temporaryDirectoryPath))
}

override static func tearDown() {
if let currentDirectoryPath = CurrentDirectoryHolder.currentDirectoryPath {
XCTAssertTrue(FileManager.default.changeCurrentDirectoryPath(currentDirectoryPath))
CurrentDirectoryHolder.currentDirectoryPath = nil
}
super.tearDown()
}

func testWritingAndReading() throws {
@Test(ResetCurrentDirectory())
func writingAndReading() throws {
try withExampleFileCreated { sourceFilePath in
let baselinePath = temporaryDirectoryPath.stringByAppendingPathComponent(UUID().uuidString)
try Baseline(violations: Self.violations(for: sourceFilePath)).write(toPath: baselinePath)
let baselinePath = FileManager.default.currentDirectoryPath.stringByAppendingPathComponent(
UUID().uuidString)
try Baseline(violations: Self.violations(for: sourceFilePath)).write(
toPath: baselinePath)
defer {
try? FileManager.default.removeItem(atPath: baselinePath)
}
let newBaseline = try Baseline(fromPath: baselinePath)
XCTAssertEqual(newBaseline, Self.baseline(for: sourceFilePath))
#expect(newBaseline == Self.baseline(for: sourceFilePath))
}
}

func testUnchangedViolations() throws {
@Test(ResetCurrentDirectory())
func unchangedViolations() throws {
try withExampleFileCreated { sourceFilePath in
XCTAssertEqual(Self.baseline(for: sourceFilePath).filter(Self.violations(for: sourceFilePath)), [])
#expect(Self.baseline(for: sourceFilePath).filter(Self.violations(for: sourceFilePath)) == [])
}
}

func testShiftedViolations() throws {
@Test(ResetCurrentDirectory())
func shiftedViolations() throws {
try withExampleFileCreated { sourceFilePath in
let baseline = Self.baseline(for: sourceFilePath)
let violations = try Self.violations(for: sourceFilePath).lineShifted(by: 2, path: sourceFilePath)
XCTAssertEqual(baseline.filter(violations), [])
#expect(baseline.filter(violations) == [])
}
}

func testNewViolation() throws {
@Test(ResetCurrentDirectory())
func newViolation() throws {
try testViolationDetection(
violationRuleDescriptions: Self.ruleDescriptions,
newViolationRuleDescription: EmptyCollectionLiteralRule.description,
insertionIndex: 2
)
}

func testViolationDetection() throws {
@Test(
ResetCurrentDirectory(),
arguments: [
ArrayInitRule.description,
BlockBasedKVORule.description,
ClosingBraceRule.description,
DirectReturnRule.description,
]
)
func violationDetection(_ ruleDescription: RuleDescription) throws {
let violationRuleDescriptions = [
ArrayInitRule.description,
BlockBasedKVORule.description,
Expand All @@ -121,36 +137,30 @@ final class BaselineTests: XCTestCase {
ClosingBraceRule.description,
]

let ruleDescriptions = [
ArrayInitRule.description,
BlockBasedKVORule.description,
ClosingBraceRule.description,
DirectReturnRule.description,
]

for ruleDescription in ruleDescriptions {
for insertionIndex in 0..<violationRuleDescriptions.count {
try testViolationDetection(
violationRuleDescriptions: violationRuleDescriptions,
newViolationRuleDescription: ruleDescription,
insertionIndex: insertionIndex
)
}
for insertionIndex in 0..<violationRuleDescriptions.count {
try testViolationDetection(
violationRuleDescriptions: violationRuleDescriptions,
newViolationRuleDescription: ruleDescription,
insertionIndex: insertionIndex
)
}
}

func testCompare() throws {
@Test(ResetCurrentDirectory())
func compare() throws {
try withExampleFileCreated { sourceFilePath in
let ruleDescriptions = Self.ruleDescriptions + Self.ruleDescriptions
let violations = ruleDescriptions.violations(for: sourceFilePath)
let numberofViolationsToDrop = 3
let oldBaseline = Baseline(violations: Array(violations.dropFirst(numberofViolationsToDrop)).reversed())
let oldBaseline = Baseline(
violations: Array(violations.dropFirst(numberofViolationsToDrop)).reversed()
)
let newViolations = Array(
try violations.lineShifted(by: 2, path: sourceFilePath).dropLast(numberofViolationsToDrop)
)
let newBaseline = Baseline(violations: newViolations.reversed())
XCTAssertEqual(oldBaseline.compare(newBaseline), Array(newViolations.prefix(numberofViolationsToDrop)))
XCTAssertEqual(newBaseline.compare(oldBaseline), Array(violations.suffix(numberofViolationsToDrop)))
#expect(oldBaseline.compare(newBaseline) == Array(newViolations.prefix(numberofViolationsToDrop)))
#expect(newBaseline.compare(oldBaseline) == Array(violations.suffix(numberofViolationsToDrop)))
}
}

Expand All @@ -174,14 +184,16 @@ final class BaselineTests: XCTestCase {
location: Location(file: sourceFilePath, line: line, character: 1)
)
newViolations.insert(violation, at: insertionIndex)
XCTAssertEqual(baseline.filter(newViolations), [violation])
#expect(baseline.filter(newViolations) == [violation])
}
}

private func withExampleFileCreated(_ block: (String) throws -> Void) throws {
let sourceFilePath = temporaryDirectoryPath.stringByAppendingPathComponent("\(UUID().uuidString).swift")
let sourceFilePath = FileManager.default.currentDirectoryPath.stringByAppendingPathComponent(
"\(UUID().uuidString).swift"
)
guard let data = Self.example.data(using: .utf8) else {
XCTFail("Could not convert example code to data using UTF-8 encoding")
Issue.record("Could not convert example code to data using UTF-8 encoding")
return
}
try data.write(to: URL(fileURLWithPath: sourceFilePath))
Expand All @@ -195,7 +207,7 @@ final class BaselineTests: XCTestCase {
private extension [StyleViolation] {
func lineShifted(by shift: Int, path: String) throws -> [StyleViolation] {
guard shift > 0 else {
XCTFail("Shift must be positive")
Issue.record("Shift must be positive")
return self
}
var lines = SwiftLintFile(path: path)?.lines.map(\.content) ?? []
Expand Down
Loading
Loading