Adopt Swift Testing

This commit is contained in:
Danny Mösch
2025-02-01 15:26:32 +01:00
parent aebc360391
commit fd066c2dc1
142 changed files with 6369 additions and 4847 deletions
+1
View File
@@ -9,6 +9,7 @@ build:macos --crosstool_top=@local_config_apple_cc//:toolchain
build:macos --host_crosstool_top=@local_config_apple_cc//:toolchain
build --macos_minimum_os=13.5 --host_macos_minimum_os=13.5
test --macos_minimum_os=14.8 --host_macos_minimum_os=14.8 # Swift Testing libraries are compiled for macOS 14+.
build --disk_cache=~/.bazel_cache
build --experimental_remote_cache_compression
build --remote_build_event_upload=minimal
+9
View File
@@ -0,0 +1,9 @@
{
"indentation" : {
"spaces" : 4
},
"lineLength": 120,
"rules" : {
"NoAccessLevelOnExtensionDeclaration": false
}
}
+1
View File
@@ -0,0 +1 @@
6.2
+1
View File
@@ -73,6 +73,7 @@ file_name:
- RuleConfigurationMacros.swift
- SwiftSyntax+SwiftLint.swift
- TestHelpers.swift
- Traits.swift
excluded_paths:
- Tests/GeneratedTests/GeneratedTests_\d\d\.swift
- Tests/FileSystemAccessTests/.+\.swift
+2 -2
View File
@@ -78,13 +78,13 @@ public macro SwiftSyntaxRule(foldExpressions: Bool = false,
)
@attached(body)
macro TemporaryDirectory() = #externalMacro(
package macro TemporaryDirectory() = #externalMacro(
module: "SwiftLintCoreMacros",
type: "TemporaryDirectory"
)
@attached(body)
macro WorkingDirectory(path: String) = #externalMacro(
package macro WorkingDirectory(path: String) = #externalMacro(
module: "SwiftLintCoreMacros",
type: "WorkingDirectory"
)
@@ -21,7 +21,7 @@ enum DisabledWithoutSourceKit: ExtensionMacro {
try ExtensionDeclSyntax("""
extension \(type) {
private static let postMessage: Void = {
Issue.genericWarning(\(raw: message)).print()
SwiftLintCore.Issue.genericWarning(\(raw: message)).print()
}()
func notifyRuleDisabledOnce() {
@@ -49,7 +49,7 @@ enum AutoConfigParser: MemberMacro {
}
}
return [
DeclSyntax(try FunctionDeclSyntax("mutating func apply(configuration: Any) throws(Issue)") {
DeclSyntax(try FunctionDeclSyntax("mutating func apply(configuration: Any) throws(SwiftLintCore.Issue)") {
for option in nonInlinedOptions {
"""
if $\(raw: option).key.isEmpty {
@@ -61,7 +61,7 @@ enum AutoConfigParser: MemberMacro {
"""
do {
try \(raw: option).apply(configuration, ruleID: Parent.identifier)
} catch let issue where issue == Issue.nothingApplied(ruleID: Parent.identifier) {
} catch let issue where issue == SwiftLintCore.Issue.nothingApplied(ruleID: Parent.identifier) {
// Acceptable. Continue.
}
"""
@@ -83,7 +83,10 @@ enum AutoConfigParser: MemberMacro {
"""
if !supportedKeys.isSuperset(of: configuration.keys) {
let unknownKeys = Set(configuration.keys).subtracting(supportedKeys)
Issue.invalidConfigurationKeys(ruleID: Parent.identifier, keys: unknownKeys).print()
SwiftLintCore.Issue.invalidConfigurationKeys(
ruleID: Parent.identifier,
keys: unknownKeys
).print()
}
"""
"""
@@ -115,7 +118,7 @@ enum AcceptableByConfigurationElement: ExtensionMacro {
try ExtensionDeclSyntax("""
extension \(type): AcceptableByConfigurationElement {
\(raw: accessLevel)func asOption() -> OptionType { .symbol(rawValue) }
\(raw: accessLevel)init(fromAny value: Any, context ruleID: String) throws(Issue) {
\(raw: accessLevel)init(fromAny value: Any, context ruleID: String) throws(SwiftLintCore.Issue) {
if let value = value as? String, let newSelf = Self(rawValue: value) {
self = newSelf
} else {
@@ -125,6 +125,12 @@ package struct LintOrAnalyzeOptions {
package struct LintOrAnalyzeCommand {
package static func run(_ options: LintOrAnalyzeOptions) async throws {
if let workingDirectory = options.workingDirectory {
let currentDirectory = FileManager.default.currentDirectoryPath
defer {
if !FileManager.default.changeCurrentDirectoryPath(currentDirectory) {
queuedFatalError("Could not change back to the original directory '\(currentDirectory)'.")
}
}
if !FileManager.default.changeCurrentDirectoryPath(workingDirectory) {
throw SwiftLintError.usageError(
description: """
+7 -3
View File
@@ -134,9 +134,11 @@ private extension SwiftLintDev.Rules.Register {
// swiftlint:disable:next blanket_disable_command superfluous_disable_command
// swiftlint:disable single_test_class type_name
import TestHelpers
import Testing
@testable import SwiftLintBuiltInRules
@testable import SwiftLintCore
import TestHelpers
\(testClassesString)
@@ -189,8 +191,10 @@ private extension SwiftLintDev.Rules.Register {
let shardRules = rulesContext.shardRules(forIndex: shardIndex)
let testClasses = shardRules.map { testName in """
final class \(testName)GeneratedTests: SwiftLintTestCase {
func testWithDefaultConfiguration() {
@Suite(.rulesRegistered)
struct \(testName)GeneratedTests {
@Test
func withDefaultConfiguration() {
verifyRule(\(testName).description)
}
}
@@ -1,22 +1,28 @@
@testable import SwiftLintBuiltInRules
import TestHelpers
import Testing
final class AttributesRuleTests: SwiftLintTestCase {
func testAttributesWithAlwaysOnSameLine() {
@testable import SwiftLintBuiltInRules
@Suite(.rulesRegistered)
struct AttributesRuleTests {
@Test
func attributesWithAlwaysOnSameLine() {
// Test with custom `always_on_same_line`
let nonTriggeringExamples = [
Example("@objc var x: String"),
Example("@objc func foo()"),
Example("@nonobjc\n func foo()"),
Example("""
class Foo {
@objc private var object: RLMWeakObjectHandle?
@objc private var property: RLMProperty?
}
"""),
Example("""
@objc(XYZFoo) class Foo: NSObject {}
"""),
Example(
"""
class Foo {
@objc private var object: RLMWeakObjectHandle?
@objc private var property: RLMProperty?
}
"""),
Example(
"""
@objc(XYZFoo) class Foo: NSObject {}
"""),
]
let triggeringExamples = [
Example("@objc\n ↓var x: String"),
@@ -28,11 +34,13 @@ final class AttributesRuleTests: SwiftLintTestCase {
.with(triggeringExamples: triggeringExamples)
.with(nonTriggeringExamples: nonTriggeringExamples)
verifyRule(alwaysOnSameLineDescription,
ruleConfiguration: ["always_on_same_line": ["@objc"]])
verifyRule(
alwaysOnSameLineDescription,
ruleConfiguration: ["always_on_same_line": ["@objc"]])
}
func testAttributesWithAlwaysOnLineAbove() {
@Test
func attributesWithAlwaysOnLineAbove() {
// Test with custom `always_on_line_above`
let nonTriggeringExamples = [
Example("@objc\n var x: String"),
@@ -49,43 +57,49 @@ final class AttributesRuleTests: SwiftLintTestCase {
.with(triggeringExamples: triggeringExamples)
.with(nonTriggeringExamples: nonTriggeringExamples)
verifyRule(alwaysOnNewLineDescription,
ruleConfiguration: ["always_on_line_above": ["@objc"]])
verifyRule(
alwaysOnNewLineDescription,
ruleConfiguration: ["always_on_line_above": ["@objc"]])
}
func testAttributesWithAttributesOnLineAboveButOnOtherDeclaration() {
@Test
func attributesWithAttributesOnLineAboveButOnOtherDeclaration() {
let nonTriggeringExamples = [
Example("""
@IBDesignable open class TagListView: UIView {
@IBInspectable open dynamic var textColor: UIColor = UIColor.white {
didSet {}
Example(
"""
@IBDesignable open class TagListView: UIView {
@IBInspectable open dynamic var textColor: UIColor = UIColor.white {
didSet {}
}
}
}
"""),
Example("""
@objc public protocol TagListViewDelegate {
@objc optional func tagDidSelect(_ title: String, sender: TagListView)
@objc optional func tagDidDeselect(_ title: String, sender: TagListView)
}
"""),
"""),
Example(
"""
@objc public protocol TagListViewDelegate {
@objc optional func tagDidSelect(_ title: String, sender: TagListView)
@objc optional func tagDidDeselect(_ title: String, sender: TagListView)
}
"""),
]
let triggeringExamples = [
Example("""
@IBDesignable open class TagListView: UIView {
@IBInspectable
open dynamic ↓var textColor: UIColor = UIColor.white {
didSet {}
Example(
"""
@IBDesignable open class TagListView: UIView {
@IBInspectable
open dynamic ↓var textColor: UIColor = UIColor.white {
didSet {}
}
}
}
"""),
Example("""
@objc public protocol TagListViewDelegate {
@objc
optional ↓func tagDidSelect(_ title: String, sender: TagListView)
@objc optional func tagDidDeselect(_ title: String, sender: TagListView)
}
"""),
"""),
Example(
"""
@objc public protocol TagListViewDelegate {
@objc
optional ↓func tagDidSelect(_ title: String, sender: TagListView)
@objc optional func tagDidDeselect(_ title: String, sender: TagListView)
}
"""),
]
let alwaysOnNewLineDescription = AttributesRule.description
@@ -102,26 +116,29 @@ final class AttributesRuleTests: SwiftLintTestCase {
)
}
func testAttributesWithArgumentsAlwaysOnLineAboveFalse() {
@Test
func attributesWithArgumentsAlwaysOnLineAboveFalse() {
let nonTriggeringExamples = [
Example("@Environment(\\.presentationMode) private var presentationMode")
]
let triggeringExamples = [
Example("""
@Environment(\\.presentationMode)
private ↓var presentationMode
"""),
@Environment(\\.presentationMode)
private ↓var presentationMode
"""),
]
let argumentsAlwaysOnLineDescription = AttributesRule.description
.with(triggeringExamples: triggeringExamples)
.with(nonTriggeringExamples: nonTriggeringExamples)
verifyRule(argumentsAlwaysOnLineDescription,
ruleConfiguration: ["attributes_with_arguments_always_on_line_above": false])
verifyRule(
argumentsAlwaysOnLineDescription,
ruleConfiguration: ["attributes_with_arguments_always_on_line_above": false])
}
func testAttributesWithArgumentsAlwaysOnLineAboveTrue() {
@Test
func attributesWithArgumentsAlwaysOnLineAboveTrue() {
let nonTriggeringExamples = [
Example("@Environment(\\.presentationMode)\nprivate var presentationMode")
]
@@ -133,7 +150,8 @@ final class AttributesRuleTests: SwiftLintTestCase {
.with(triggeringExamples: triggeringExamples)
.with(nonTriggeringExamples: nonTriggeringExamples)
verifyRule(argumentsAlwaysOnLineDescription,
ruleConfiguration: ["attributes_with_arguments_always_on_line_above": true])
verifyRule(
argumentsAlwaysOnLineDescription,
ruleConfiguration: ["attributes_with_arguments_always_on_line_above": true])
}
}
@@ -1,15 +1,18 @@
@testable import SwiftLintBuiltInRules
import TestHelpers
import XCTest
import Testing
final class BlanketDisableCommandRuleTests: SwiftLintTestCase {
private lazy var emptyDescription = BlanketDisableCommandRule.description
@testable import SwiftLintBuiltInRules
@Suite(.rulesRegistered)
struct BlanketDisableCommandRuleTests {
private static let emptyDescription = BlanketDisableCommandRule.description
.with(triggeringExamples: [])
.with(nonTriggeringExamples: [])
func testAlwaysBlanketDisable() {
@Test
func alwaysBlanketDisable() {
let nonTriggeringExamples = [Example("// swiftlint:disable file_length\n// swiftlint:enable file_length")]
verifyRule(emptyDescription.with(nonTriggeringExamples: nonTriggeringExamples))
verifyRule(Self.emptyDescription.with(nonTriggeringExamples: nonTriggeringExamples))
let triggeringExamples = [
Example("// swiftlint:disable file_length\n// swiftlint:enable ↓file_length"),
@@ -17,23 +20,27 @@ final class BlanketDisableCommandRuleTests: SwiftLintTestCase {
Example("// swiftlint:disable:this ↓file_length"),
Example("// swiftlint:disable:next ↓file_length"),
]
verifyRule(emptyDescription.with(triggeringExamples: triggeringExamples),
ruleConfiguration: ["always_blanket_disable": ["file_length"]],
skipCommentTests: true, skipDisableCommandTests: true)
verifyRule(
Self.emptyDescription.with(triggeringExamples: triggeringExamples),
ruleConfiguration: ["always_blanket_disable": ["file_length"]],
skipCommentTests: true, skipDisableCommandTests: true)
}
func testAlwaysBlanketDisabledAreAllowed() {
@Test
func alwaysBlanketDisabledAreAllowed() {
let nonTriggeringExamples = [Example("// swiftlint:disable identifier_name\n")]
verifyRule(emptyDescription.with(nonTriggeringExamples: nonTriggeringExamples),
ruleConfiguration: ["always_blanket_disable": ["identifier_name"], "allowed_rules": []],
skipDisableCommandTests: true)
verifyRule(
Self.emptyDescription.with(nonTriggeringExamples: nonTriggeringExamples),
ruleConfiguration: ["always_blanket_disable": ["identifier_name"], "allowed_rules": []],
skipDisableCommandTests: true)
}
func testAllowedRules() {
@Test
func allowedRules() {
let nonTriggeringExamples = [
Example("// swiftlint:disable file_length"),
Example("// swiftlint:disable single_test_class"),
]
verifyRule(emptyDescription.with(nonTriggeringExamples: nonTriggeringExamples))
verifyRule(Self.emptyDescription.with(nonTriggeringExamples: nonTriggeringExamples))
}
}
@@ -1,33 +1,42 @@
@testable import SwiftLintBuiltInRules
import TestHelpers
import XCTest
import Testing
final class ChildOptionSeverityConfigurationTests: SwiftLintTestCase {
@testable import SwiftLintBuiltInRules
@Suite(.rulesRegistered)
struct ChildOptionSeverityConfigurationTests {
typealias TesteeType = ChildOptionSeverityConfiguration<RuleMock>
func testSeverity() {
XCTAssertNil(TesteeType.off.severity)
XCTAssertEqual(TesteeType.warning.severity, .warning)
XCTAssertEqual(TesteeType.error.severity, .error)
@Test
func severity() {
#expect(TesteeType.off.severity == nil)
#expect(TesteeType.warning.severity == .warning)
#expect(TesteeType.error.severity == .error)
}
func testFromConfig() throws {
@Test
func fromConfig() throws {
var testee = TesteeType.off
try testee.apply(configuration: "warning")
XCTAssertEqual(testee, .warning)
#expect(testee == .warning)
try testee.apply(configuration: "error")
XCTAssertEqual(testee, .error)
#expect(testee == .error)
try testee.apply(configuration: "off")
XCTAssertEqual(testee, .off)
#expect(testee == .off)
}
func testInvalidConfig() {
@Test
func invalidConfig() {
var testee = TesteeType.off
XCTAssertThrowsError(try testee.apply(configuration: "no"))
XCTAssertThrowsError(try testee.apply(configuration: 1))
#expect(throws: (any Error).self) {
try testee.apply(configuration: "no")
}
#expect(throws: (any Error).self) {
try testee.apply(configuration: 1)
}
}
}
@@ -1,8 +1,12 @@
@testable import SwiftLintBuiltInRules
import TestHelpers
import Testing
final class CollectionAlignmentRuleTests: SwiftLintTestCase {
func testCollectionAlignmentWithAlignLeft() {
@testable import SwiftLintBuiltInRules
@Suite(.rulesRegistered)
struct CollectionAlignmentRuleTests {
@Test
func collectionAlignmentWithAlignLeft() {
let baseDescription = CollectionAlignmentRule.description
let examples = CollectionAlignmentRule.Examples(alignColons: false)
@@ -12,7 +16,8 @@ final class CollectionAlignmentRuleTests: SwiftLintTestCase {
verifyRule(description)
}
func testCollectionAlignmentWithAlignColons() {
@Test
func collectionAlignmentWithAlignColons() {
let baseDescription = CollectionAlignmentRule.description
let examples = CollectionAlignmentRule.Examples(alignColons: true)
+9 -4
View File
@@ -1,8 +1,12 @@
@testable import SwiftLintBuiltInRules
import TestHelpers
import Testing
final class ColonRuleTests: SwiftLintTestCase {
func testColonWithFlexibleRightSpace() {
@testable import SwiftLintBuiltInRules
@Suite(.rulesRegistered)
struct ColonRuleTests {
@Test
func colonWithFlexibleRightSpace() {
// Verify Colon rule with test values for when flexible_right_spacing
// is true.
let nonTriggeringExamples = ColonRule.description.nonTriggeringExamples + [
@@ -68,7 +72,8 @@ final class ColonRuleTests: SwiftLintTestCase {
verifyRule(description, ruleConfiguration: ["flexible_right_spacing": true])
}
func testColonWithoutApplyToDictionaries() {
@Test
func colonWithoutApplyToDictionaries() {
let nonTriggeringExamples = ColonRule.description.nonTriggeringExamples + [
Example("let abc = [Void:Void]()\n"),
Example("let abc = [Void : Void]()\n"),
@@ -1,22 +1,20 @@
@testable import SwiftLintBuiltInRules
import TestHelpers
import XCTest
import Testing
final class CompilerProtocolInitRuleTests: SwiftLintTestCase {
@testable import SwiftLintBuiltInRules
@Suite(.rulesRegistered)
struct CompilerProtocolInitRuleTests {
private let ruleID = CompilerProtocolInitRule.identifier
func testViolationMessageForExpressibleByIntegerLiteral() throws {
let config = try XCTUnwrap(makeConfig(nil, ruleID))
@Test
func violationMessageForExpressibleByIntegerLiteral() throws {
let config = try #require(makeConfig(nil, ruleID))
let allViolations = violations(Example("let a = NSNumber(integerLiteral: 1)"), config: config)
let compilerProtocolInitViolation = allViolations.first { $0.ruleIdentifier == ruleID }
let violation = try XCTUnwrap(
compilerProtocolInitViolation,
"A compiler protocol init violation should have been triggered!"
)
XCTAssertEqual(
violation.reason,
"Initializers declared in compiler protocol ExpressibleByIntegerLiteral shouldn't be called directly"
let violation = try #require(allViolations.first { $0.ruleIdentifier == ruleID })
#expect(
violation.reason
== "Initializers declared in compiler protocol ExpressibleByIntegerLiteral shouldn't be called directly"
)
}
}
@@ -1,9 +1,12 @@
@testable import SwiftLintBuiltInRules
import TestHelpers
import XCTest
import Testing
final class ComputedAccessorsOrderRuleTests: SwiftLintTestCase {
func testSetGetConfiguration() {
@testable import SwiftLintBuiltInRules
@Suite(.rulesRegistered)
struct ComputedAccessorsOrderRuleTests {
@Test
func setGetConfiguration() {
let nonTriggeringExamples = [
Example("""
class Foo {
@@ -40,7 +43,8 @@ final class ComputedAccessorsOrderRuleTests: SwiftLintTestCase {
verifyRule(description, ruleConfiguration: ["order": "set_get"])
}
func testGetSetPropertyReason() {
@Test
func getSetPropertyReason() {
let example = Example("""
class Foo {
var foo: Int {
@@ -54,13 +58,14 @@ final class ComputedAccessorsOrderRuleTests: SwiftLintTestCase {
}
""")
XCTAssertEqual(
ruleViolations(example).first?.reason,
"Computed properties should first declare the getter and then the setter"
#expect(
ruleViolations(example).first?.reason
== "Computed properties should first declare the getter and then the setter"
)
}
func testGetSetSubscriptReason() {
@Test
func getSetSubscriptReason() {
let example = Example("""
class Foo {
subscript(i: Int) -> Int {
@@ -74,13 +79,14 @@ final class ComputedAccessorsOrderRuleTests: SwiftLintTestCase {
}
""")
XCTAssertEqual(
ruleViolations(example).first?.reason,
"Computed subscripts should first declare the getter and then the setter"
#expect(
ruleViolations(example).first?.reason
== "Computed subscripts should first declare the getter and then the setter"
)
}
func testSetGetPropertyReason() {
@Test
func setGetPropertyReason() {
let example = Example("""
class Foo {
var foo: Int {
@@ -94,13 +100,14 @@ final class ComputedAccessorsOrderRuleTests: SwiftLintTestCase {
}
""")
XCTAssertEqual(
ruleViolations(example, ruleConfiguration: ["order": "set_get"]).first?.reason,
"Computed properties should first declare the setter and then the getter"
#expect(
ruleViolations(example, ruleConfiguration: ["order": "set_get"]).first?.reason
== "Computed properties should first declare the setter and then the getter"
)
}
func testSetGetSubscriptReason() {
@Test
func setGetSubscriptReason() {
let example = Example("""
class Foo {
subscript(i: Int) -> Int {
@@ -114,9 +121,9 @@ final class ComputedAccessorsOrderRuleTests: SwiftLintTestCase {
}
""")
XCTAssertEqual(
ruleViolations(example, ruleConfiguration: ["order": "set_get"]).first?.reason,
"Computed subscripts should first declare the setter and then the getter"
#expect(
ruleViolations(example, ruleConfiguration: ["order": "set_get"]).first?.reason
== "Computed subscripts should first declare the setter and then the getter"
)
}
@@ -124,7 +131,6 @@ final class ComputedAccessorsOrderRuleTests: SwiftLintTestCase {
guard let config = makeConfig(ruleConfiguration, ComputedAccessorsOrderRule.identifier) else {
return []
}
return violations(example, config: config)
}
}
@@ -1,8 +1,12 @@
@testable import SwiftLintBuiltInRules
import TestHelpers
import Testing
final class ConditionalReturnsOnNewlineRuleTests: SwiftLintTestCase {
func testConditionalReturnsOnNewlineWithIfOnly() {
@testable import SwiftLintBuiltInRules
@Suite(.rulesRegistered)
struct ConditionalReturnsOnNewlineRuleTests {
@Test
func conditionalReturnsOnNewlineWithIfOnly() {
// Test with `if_only` set to true
let nonTriggeringExamples = [
Example("guard true else {\n return true\n}"),
@@ -1,22 +1,26 @@
@testable import SwiftLintBuiltInRules
import TestHelpers
import XCTest
import Testing
final class ContainsOverFirstNotNilRuleTests: SwiftLintTestCase {
func testFirstReason() {
@testable import SwiftLintBuiltInRules
@Suite(.rulesRegistered)
struct ContainsOverFirstNotNilRuleTests {
@Test
func firstReason() {
let example = Example("↓myList.first { $0 % 2 == 0 } != nil")
let violations = self.violations(example)
XCTAssertEqual(violations.count, 1)
XCTAssertEqual(violations.first?.reason, "Prefer `contains` over `first(where:) != nil`")
#expect(violations.count == 1)
#expect(violations.first?.reason == "Prefer `contains` over `first(where:) != nil`")
}
func testFirstIndexReason() {
@Test
func firstIndexReason() {
let example = Example("↓myList.firstIndex { $0 % 2 == 0 } != nil")
let violations = self.violations(example)
XCTAssertEqual(violations.count, 1)
XCTAssertEqual(violations.first?.reason, "Prefer `contains` over `firstIndex(where:) != nil`")
#expect(violations.count == 1)
#expect(violations.first?.reason == "Prefer `contains` over `firstIndex(where:) != nil`")
}
// MARK: - Private
@@ -25,7 +29,6 @@ final class ContainsOverFirstNotNilRuleTests: SwiftLintTestCase {
guard let config = makeConfig(config, ContainsOverFirstNotNilRule.identifier) else {
return []
}
return TestHelpers.violations(example, config: config)
}
}
@@ -1,34 +1,39 @@
@testable import SwiftLintBuiltInRules
import TestHelpers
import XCTest
import Testing
final class CyclomaticComplexityConfigurationTests: SwiftLintTestCase {
func testCyclomaticComplexityConfigurationInitializerSetsLevels() {
@testable import SwiftLintBuiltInRules
@Suite(.rulesRegistered)
struct CyclomaticComplexityConfigurationTests {
@Test
func cyclomaticComplexityConfigurationInitializerSetsLevels() {
let warning = 10
let error = 30
let level = SeverityLevelsConfiguration<CyclomaticComplexityRule>(warning: warning, error: error)
let configuration1 = CyclomaticComplexityConfiguration(length: level)
XCTAssertEqual(configuration1.length, level)
#expect(configuration1.length == level)
let length2 = SeverityLevelsConfiguration<CyclomaticComplexityRule>(warning: warning, error: nil)
let configuration2 = CyclomaticComplexityConfiguration(length: length2)
XCTAssertEqual(configuration2.length, length2)
#expect(configuration2.length == length2)
}
func testCyclomaticComplexityConfigurationInitializerSetsIgnoresCaseStatements() {
@Test
func cyclomaticComplexityConfigurationInitializerSetsIgnoresCaseStatements() {
let configuration1 = CyclomaticComplexityConfiguration(
length: SeverityLevelsConfiguration(warning: 10, error: 30),
ignoresCaseStatements: true
)
XCTAssertTrue(configuration1.ignoresCaseStatements)
#expect(configuration1.ignoresCaseStatements)
let configuration2 = CyclomaticComplexityConfiguration(
length: SeverityLevelsConfiguration(warning: 10, error: 30)
)
XCTAssertFalse(configuration2.ignoresCaseStatements)
#expect(!configuration2.ignoresCaseStatements)
}
func testCyclomaticComplexityConfigurationApplyConfigurationWithDictionary() throws {
@Test
func cyclomaticComplexityConfigurationApplyConfigurationWithDictionary() throws {
var configuration = CyclomaticComplexityConfiguration(
length: SeverityLevelsConfiguration(warning: 0, error: 0)
)
@@ -49,19 +54,20 @@ final class CyclomaticComplexityConfigurationTests: SwiftLintTestCase {
let config3: [String: Bool] = ["ignores_case_statements": false]
try configuration.apply(configuration: config1)
XCTAssertEqual(configuration.length, length1)
XCTAssertTrue(configuration.ignoresCaseStatements)
#expect(configuration.length == length1)
#expect(configuration.ignoresCaseStatements)
try configuration.apply(configuration: config2)
XCTAssertEqual(configuration.length, length2)
XCTAssertTrue(configuration.ignoresCaseStatements)
#expect(configuration.length == length2)
#expect(configuration.ignoresCaseStatements)
try configuration.apply(configuration: config3)
XCTAssertEqual(configuration.length, length2)
XCTAssertFalse(configuration.ignoresCaseStatements)
#expect(configuration.length == length2)
#expect(!configuration.ignoresCaseStatements)
}
func testCyclomaticComplexityConfigurationThrowsOnBadConfigValues() {
@Test
func cyclomaticComplexityConfigurationThrowsOnBadConfigValues() {
let badConfigs: [[String: Any]] = [
["warning": true],
["ignores_case_statements": 300],
@@ -77,7 +83,8 @@ final class CyclomaticComplexityConfigurationTests: SwiftLintTestCase {
}
}
func testCyclomaticComplexityConfigurationCompares() {
@Test
func cyclomaticComplexityConfigurationCompares() {
let config1 = CyclomaticComplexityConfiguration(
length: SeverityLevelsConfiguration(warning: 10, error: 30)
)
@@ -95,9 +102,9 @@ final class CyclomaticComplexityConfigurationTests: SwiftLintTestCase {
let config5 = CyclomaticComplexityConfiguration(
length: SeverityLevelsConfiguration(warning: 20, error: 30)
)
XCTAssertNotEqual(config1, config2)
XCTAssertEqual(config1, config3)
XCTAssertNotEqual(config1, config4)
XCTAssertNotEqual(config1, config5)
#expect(config1 != config2)
#expect(config1 == config3)
#expect(config1 != config4)
#expect(config1 != config5)
}
}
@@ -1,8 +1,11 @@
@testable import SwiftLintBuiltInRules
import TestHelpers
import Testing
final class CyclomaticComplexityRuleTests: SwiftLintTestCase {
private lazy var complexSwitchExample: Example = {
@testable import SwiftLintBuiltInRules
@Suite(.rulesRegistered)
struct CyclomaticComplexityRuleTests {
private static let complexSwitchExample: Example = {
var example = "func switcheroo() {\n"
example += " switch foo {\n"
for index in (0...30) {
@@ -13,7 +16,7 @@ final class CyclomaticComplexityRuleTests: SwiftLintTestCase {
return Example(example)
}()
private lazy var complexSwitchInitExample: Example = {
private static let complexSwitchInitExample: Example = {
var example = "init() {\n"
example += " switch foo {\n"
for index in (0...30) {
@@ -24,7 +27,7 @@ final class CyclomaticComplexityRuleTests: SwiftLintTestCase {
return Example(example)
}()
private lazy var complexIfExample: Example = {
private static let complexIfExample: Example = {
let nest = 22
var example = "func nestThoseIfs() {\n"
for index in (0...nest) {
@@ -41,14 +44,16 @@ final class CyclomaticComplexityRuleTests: SwiftLintTestCase {
return Example(example)
}()
func testCyclomaticComplexity() {
@Test
func cyclomaticComplexity() {
verifyRule(CyclomaticComplexityRule.description, commentDoesntViolate: true, stringDoesntViolate: true)
}
func testIgnoresCaseStatementsConfigurationEnabled() {
@Test
func ignoresCaseStatementsConfigurationEnabled() {
let baseDescription = CyclomaticComplexityRule.description
let triggeringExamples = [complexIfExample]
let nonTriggeringExamples = baseDescription.nonTriggeringExamples + [complexSwitchExample]
let triggeringExamples = [Self.complexIfExample]
let nonTriggeringExamples = baseDescription.nonTriggeringExamples + [Self.complexSwitchExample]
let description = baseDescription.with(nonTriggeringExamples: nonTriggeringExamples)
.with(triggeringExamples: triggeringExamples)
@@ -57,9 +62,13 @@ final class CyclomaticComplexityRuleTests: SwiftLintTestCase {
commentDoesntViolate: true, stringDoesntViolate: true)
}
func testIgnoresCaseStatementsConfigurationDisabled() {
@Test
func ignoresCaseStatementsConfigurationDisabled() {
let baseDescription = CyclomaticComplexityRule.description
let triggeringExamples = baseDescription.triggeringExamples + [complexSwitchExample, complexSwitchInitExample]
let triggeringExamples = baseDescription.triggeringExamples + [
Self.complexSwitchExample,
Self.complexSwitchInitExample,
]
let nonTriggeringExamples = baseDescription.nonTriggeringExamples
let description = baseDescription.with(nonTriggeringExamples: nonTriggeringExamples)
@@ -1,92 +1,70 @@
@testable import SwiftLintBuiltInRules
import TestHelpers
import XCTest
import Testing
final class DeploymentTargetConfigurationTests: SwiftLintTestCase {
@testable import SwiftLintBuiltInRules
@Suite(.rulesRegistered)
struct DeploymentTargetConfigurationTests {
private typealias Version = DeploymentTargetConfiguration.Version
// swiftlint:disable:next function_body_length
func testAppliesConfigurationFromDictionary() throws {
@Test
func appliesConfigurationFromDictionary() throws { // swiftlint:disable:this function_body_length
var configuration = DeploymentTargetConfiguration()
try configuration.apply(configuration: ["iOS_deployment_target": "10.1", "severity": "error"])
XCTAssertEqual(
configuration.iOSDeploymentTarget,
Version(platform: .iOS, major: 10, minor: 1)
#expect(configuration.iOSDeploymentTarget == Version(platform: .iOS, major: 10, minor: 1))
#expect(
configuration.iOSAppExtensionDeploymentTarget
== Version(platform: .iOSApplicationExtension, major: 10, minor: 1)
)
XCTAssertEqual(
configuration.iOSAppExtensionDeploymentTarget,
Version(platform: .iOSApplicationExtension, major: 10, minor: 1)
)
XCTAssertEqual(configuration.severityConfiguration.severity, .error)
#expect(configuration.severityConfiguration.severity == .error)
try configuration.apply(configuration: ["iOSApplicationExtension_deployment_target": "13.0"])
XCTAssertEqual(
configuration.iOSDeploymentTarget,
Version(platform: .iOS, major: 10, minor: 1)
#expect(configuration.iOSDeploymentTarget == Version(platform: .iOS, major: 10, minor: 1))
#expect(
configuration.iOSAppExtensionDeploymentTarget
== Version(platform: .iOSApplicationExtension, major: 13, minor: 0)
)
XCTAssertEqual(
configuration.iOSAppExtensionDeploymentTarget,
Version(platform: .iOSApplicationExtension, major: 13, minor: 0)
)
XCTAssertEqual(configuration.severityConfiguration.severity, .error)
#expect(configuration.severityConfiguration.severity == .error)
try configuration.apply(configuration: ["macOS_deployment_target": "10.11.3"])
XCTAssertEqual(
configuration.iOSDeploymentTarget,
Version(platform: .iOS, major: 10, minor: 1)
#expect(configuration.iOSDeploymentTarget == Version(platform: .iOS, major: 10, minor: 1))
#expect(
configuration.iOSAppExtensionDeploymentTarget
== Version(platform: .iOSApplicationExtension, major: 13, minor: 0)
)
XCTAssertEqual(
configuration.iOSAppExtensionDeploymentTarget,
Version(platform: .iOSApplicationExtension, major: 13, minor: 0)
#expect(configuration.macOSDeploymentTarget == Version(platform: .macOS, major: 10, minor: 11, patch: 3))
#expect(
configuration.macOSAppExtensionDeploymentTarget
== Version(platform: .macOSApplicationExtension, major: 10, minor: 11, patch: 3)
)
XCTAssertEqual(
configuration.macOSDeploymentTarget,
Version(platform: .macOS, major: 10, minor: 11, patch: 3)
)
XCTAssertEqual(
configuration.macOSAppExtensionDeploymentTarget,
Version(platform: .macOSApplicationExtension, major: 10, minor: 11, patch: 3)
)
XCTAssertEqual(configuration.severityConfiguration.severity, .error)
#expect(configuration.severityConfiguration.severity == .error)
try configuration.apply(configuration: ["macOSApplicationExtension_deployment_target": "12.4"])
XCTAssertEqual(
configuration.iOSDeploymentTarget,
Version(platform: .iOS, major: 10, minor: 1)
#expect(configuration.iOSDeploymentTarget == Version(platform: .iOS, major: 10, minor: 1))
#expect(
configuration.iOSAppExtensionDeploymentTarget
== Version(platform: .iOSApplicationExtension, major: 13, minor: 0)
)
XCTAssertEqual(
configuration.iOSAppExtensionDeploymentTarget,
Version(platform: .iOSApplicationExtension, major: 13, minor: 0)
#expect(configuration.macOSDeploymentTarget == Version(platform: .macOS, major: 10, minor: 11, patch: 3))
#expect(
configuration.macOSAppExtensionDeploymentTarget
== Version(platform: .macOSApplicationExtension, major: 12, minor: 4)
)
XCTAssertEqual(
configuration.macOSDeploymentTarget,
Version(platform: .macOS, major: 10, minor: 11, patch: 3)
)
XCTAssertEqual(
configuration.macOSAppExtensionDeploymentTarget,
Version(platform: .macOSApplicationExtension, major: 12, minor: 4)
)
XCTAssertEqual(configuration.severityConfiguration.severity, .error)
#expect(configuration.severityConfiguration.severity == .error)
try configuration.apply(configuration: ["severity": "warning"])
XCTAssertEqual(
configuration.iOSDeploymentTarget,
Version(platform: .iOS, major: 10, minor: 1)
#expect(configuration.iOSDeploymentTarget == Version(platform: .iOS, major: 10, minor: 1))
#expect(
configuration.iOSAppExtensionDeploymentTarget
== Version(platform: .iOSApplicationExtension, major: 13, minor: 0)
)
XCTAssertEqual(
configuration.iOSAppExtensionDeploymentTarget,
Version(platform: .iOSApplicationExtension, major: 13, minor: 0)
#expect(configuration.macOSDeploymentTarget == Version(platform: .macOS, major: 10, minor: 11, patch: 3))
#expect(
configuration.macOSAppExtensionDeploymentTarget
== Version(platform: .macOSApplicationExtension, major: 12, minor: 4)
)
XCTAssertEqual(
configuration.macOSDeploymentTarget,
Version(platform: .macOS, major: 10, minor: 11, patch: 3)
)
XCTAssertEqual(
configuration.macOSAppExtensionDeploymentTarget,
Version(platform: .macOSApplicationExtension, major: 12, minor: 4)
)
XCTAssertEqual(configuration.severityConfiguration.severity, .warning)
#expect(configuration.severityConfiguration.severity == .warning)
try configuration.apply(configuration: [
"tvOS_deployment_target": 10.2,
@@ -94,42 +72,31 @@ final class DeploymentTargetConfigurationTests: SwiftLintTestCase {
"watchOS_deployment_target": 5,
"watchOSApplicationExtension_deployment_target": 2.2,
])
XCTAssertEqual(
configuration.iOSDeploymentTarget,
Version(platform: .iOS, major: 10, minor: 1)
#expect(configuration.iOSDeploymentTarget == Version(platform: .iOS, major: 10, minor: 1))
#expect(
configuration.iOSAppExtensionDeploymentTarget
== Version(platform: .iOSApplicationExtension, major: 13, minor: 0)
)
XCTAssertEqual(
configuration.iOSAppExtensionDeploymentTarget,
Version(platform: .iOSApplicationExtension, major: 13, minor: 0)
#expect(configuration.macOSDeploymentTarget == Version(platform: .macOS, major: 10, minor: 11, patch: 3))
#expect(
configuration.macOSAppExtensionDeploymentTarget
== Version(platform: .macOSApplicationExtension, major: 12, minor: 4)
)
XCTAssertEqual(
configuration.macOSDeploymentTarget,
Version(platform: .macOS, major: 10, minor: 11, patch: 3)
#expect(configuration.tvOSDeploymentTarget == Version(platform: .tvOS, major: 10, minor: 2))
#expect(
configuration.tvOSAppExtensionDeploymentTarget
== Version(platform: .tvOSApplicationExtension, major: 9, minor: 1)
)
XCTAssertEqual(
configuration.macOSAppExtensionDeploymentTarget,
Version(platform: .macOSApplicationExtension, major: 12, minor: 4)
#expect(configuration.watchOSDeploymentTarget == Version(platform: .watchOS, major: 5))
#expect(
configuration.watchOSAppExtensionDeploymentTarget
== Version(platform: .watchOSApplicationExtension, major: 2, minor: 2)
)
XCTAssertEqual(
configuration.tvOSDeploymentTarget,
Version(platform: .tvOS, major: 10, minor: 2)
)
XCTAssertEqual(
configuration.tvOSAppExtensionDeploymentTarget,
Version(platform: .tvOSApplicationExtension, major: 9, minor: 1)
)
XCTAssertEqual(
configuration.watchOSDeploymentTarget,
Version(platform: .watchOS, major: 5)
)
XCTAssertEqual(
configuration.watchOSAppExtensionDeploymentTarget,
Version(platform: .watchOSApplicationExtension, major: 2, minor: 2)
)
XCTAssertEqual(configuration.severityConfiguration.severity, .warning)
#expect(configuration.severityConfiguration.severity == .warning)
}
func testThrowsOnBadConfig() {
@Test
func throwsOnBadConfig() {
let badConfigs: [[String: Any]] = [
["iOS_deployment_target": "foo"],
["iOS_deployment_target": ""],
@@ -1,45 +1,53 @@
@testable import SwiftLintBuiltInRules
import TestHelpers
import XCTest
import Testing
final class DeploymentTargetRuleTests: SwiftLintTestCase {
func testMacOSAttributeReason() {
@testable import SwiftLintBuiltInRules
@Suite(.rulesRegistered)
struct DeploymentTargetRuleTests {
@Test
func macOSAttributeReason() {
let example = Example("@available(macOS 10.11, *)\nclass A {}")
let violations = self.violations(example, config: ["macOS_deployment_target": "10.14.0"])
let expectedMessage = "Availability attribute is using a version (10.11) that is satisfied by " +
"the deployment target (10.14) for platform macOS"
XCTAssertEqual(violations.count, 1)
XCTAssertEqual(violations.first?.reason, expectedMessage)
let expectedMessage = """
Availability attribute is using a version (10.11) that is satisfied by \
the deployment target (10.14) for platform macOS
"""
#expect(violations.count == 1)
#expect(violations.first?.reason == expectedMessage)
}
func testWatchOSConditionReason() {
@Test
func watchOSConditionReason() {
let example = Example("if #available(watchOS 4, *) {}")
let violations = self.violations(example, config: ["watchOS_deployment_target": "5.0.1"])
let expectedMessage = "Availability condition is using a version (4) that is satisfied by " +
"the deployment target (5.0.1) for platform watchOS"
XCTAssertEqual(violations.count, 1)
XCTAssertEqual(violations.first?.reason, expectedMessage)
let expectedMessage = """
Availability condition is using a version (4) that is satisfied by \
the deployment target (5.0.1) for platform watchOS
"""
#expect(violations.count == 1)
#expect(violations.first?.reason == expectedMessage)
}
func testiOSNegativeAttributeReason() throws {
try XCTSkipUnless(SwiftVersion.current >= .fiveDotSix)
@Test(.enabled(if: SwiftVersion.current >= .fiveDotSix))
func iOSNegativeAttributeReason() throws {
let example = Example("if #unavailable(iOS 14) { legacyImplementation() }")
let violations = self.violations(example, config: ["iOS_deployment_target": "15.0"])
let expectedMessage = "Availability negative condition is using a version (14) that is satisfied by " +
"the deployment target (15.0) for platform iOS"
XCTAssertEqual(violations.count, 1)
XCTAssertEqual(violations.first?.reason, expectedMessage)
let expectedMessage = """
Availability negative condition is using a version (14) that is satisfied by \
the deployment target (15.0) for platform iOS
"""
#expect(violations.count == 1)
#expect(violations.first?.reason == expectedMessage)
}
private func violations(_ example: Example, config: Any?) -> [StyleViolation] {
guard let config = makeConfig(config, DeploymentTargetRule.identifier) else {
return []
}
return TestHelpers.violations(example, config: config)
}
}
@@ -1,14 +1,19 @@
@testable import SwiftLintBuiltInRules
import TestHelpers
import Testing
final class DiscouragedDirectInitRuleTests: SwiftLintTestCase {
@testable import SwiftLintBuiltInRules
@Suite(.rulesRegistered)
struct DiscouragedDirectInitRuleTests {
private let baseDescription = DiscouragedDirectInitRule.description
func testDiscouragedDirectInitWithConfiguredSeverity() {
@Test
func discouragedDirectInitWithConfiguredSeverity() {
verifyRule(baseDescription, ruleConfiguration: ["severity": "error"])
}
func testDiscouragedDirectInitWithNewIncludedTypes() {
@Test
func discouragedDirectInitWithNewIncludedTypes() {
let triggeringExamples = [
Example("let foo = ↓Foo()"),
Example("let bar = ↓Bar()"),
@@ -26,7 +31,8 @@ final class DiscouragedDirectInitRuleTests: SwiftLintTestCase {
verifyRule(description, ruleConfiguration: ["types": ["Foo", "Bar"]])
}
func testDiscouragedDirectInitWithReplacedTypes() {
@Test
func discouragedDirectInitWithReplacedTypes() {
let triggeringExamples = [
Example("let bundle = ↓Bundle()")
]
@@ -1,33 +1,44 @@
@testable import SwiftLintBuiltInRules
import TestHelpers
import Testing
final class DiscouragedObjectLiteralRuleTests: SwiftLintTestCase {
func testWithImageLiteral() {
@testable import SwiftLintBuiltInRules
@Suite(.rulesRegistered)
struct DiscouragedObjectLiteralRuleTests {
@Test
func withImageLiteral() {
let baseDescription = DiscouragedObjectLiteralRule.description
let nonTriggeringExamples = baseDescription.nonTriggeringExamples + [
Example("let color = #colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)")
]
let nonTriggeringExamples =
baseDescription.nonTriggeringExamples + [
Example("""
let color = #colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)
"""),
]
let triggeringExamples = [
Example("let image = ↓#imageLiteral(resourceName: \"image.jpg\")")
]
let description = baseDescription.with(nonTriggeringExamples: nonTriggeringExamples,
triggeringExamples: triggeringExamples)
let description = baseDescription.with(
nonTriggeringExamples: nonTriggeringExamples,
triggeringExamples: triggeringExamples)
verifyRule(description, ruleConfiguration: ["image_literal": true, "color_literal": false])
}
func testWithColorLiteral() {
@Test
func withColorLiteral() {
let baseDescription = DiscouragedObjectLiteralRule.description
let nonTriggeringExamples = baseDescription.nonTriggeringExamples + [
Example("let image = #imageLiteral(resourceName: \"image.jpg\")")
]
let nonTriggeringExamples =
baseDescription.nonTriggeringExamples + [
Example("let image = #imageLiteral(resourceName: \"image.jpg\")")
]
let triggeringExamples = [
Example("let color = ↓#colorLiteral(red: 0.9607843161, green: 0.7058823705, blue: 0.200000003, alpha: 1)")
]
let description = baseDescription.with(nonTriggeringExamples: nonTriggeringExamples,
triggeringExamples: triggeringExamples)
let description = baseDescription.with(
nonTriggeringExamples: nonTriggeringExamples,
triggeringExamples: triggeringExamples)
verifyRule(description, ruleConfiguration: ["image_literal": false, "color_literal": true])
}
@@ -1,8 +1,11 @@
@testable import SwiftLintBuiltInRules
import XCTest
import Testing
final class DuplicateImportsRuleTests: XCTestCase {
func testDisableCommand() {
@testable import SwiftLintBuiltInRules
@Suite(.rulesRegistered)
struct DuplicateImportsRuleTests {
@Test
func disableCommand() {
let content = """
import InspireAPI
// swiftlint:disable:next duplicate_imports
@@ -12,6 +15,6 @@ final class DuplicateImportsRuleTests: XCTestCase {
_ = DuplicateImportsRule().correct(file: file)
XCTAssertEqual(file.contents, content)
#expect(file.contents == content)
}
}
@@ -1,8 +1,12 @@
@testable import SwiftLintBuiltInRules
import TestHelpers
import Testing
final class EmptyCountRuleTests: SwiftLintTestCase {
func testEmptyCountWithOnlyAfterDot() {
@testable import SwiftLintBuiltInRules
@Suite(.rulesRegistered)
struct EmptyCountRuleTests {
@Test
func emptyCountWithOnlyAfterDot() {
// Test with `only_after_dot` set to true
let nonTriggeringExamples = [
Example("var count = 0\n"),
@@ -1,49 +1,59 @@
@testable import SwiftLintBuiltInRules
import Foundation
import TestHelpers
import XCTest
import Testing
final class ExpiringTodoRuleTests: SwiftLintTestCase {
func testExpiringTodo() {
@testable import SwiftLintBuiltInRules
@Suite(.rulesRegistered)
struct ExpiringTodoRuleTests {
@Test
func expiringTodo() {
verifyRule(ExpiringTodoRule.description, commentDoesntViolate: false)
}
func testExpiredTodo() {
@Test
func expiredTodo() {
let example = Example("fatalError() // TODO: [\(dateString(for: .expired))] Implement")
let violations = self.violations(example)
XCTAssertEqual(violations.count, 1)
XCTAssertEqual(violations.first!.reason, "TODO/FIXME has expired and must be resolved")
#expect(violations.count == 1)
#expect(violations.first?.reason == "TODO/FIXME has expired and must be resolved")
}
func testExpiredFixMe() {
@Test
func expiredFixMe() {
let example = Example("fatalError() // FIXME: [\(dateString(for: .expired))] Implement")
let violations = self.violations(example)
XCTAssertEqual(violations.count, 1)
XCTAssertEqual(violations.first!.reason, "TODO/FIXME has expired and must be resolved")
#expect(violations.count == 1)
#expect(violations.first?.reason == "TODO/FIXME has expired and must be resolved")
}
func testApproachingExpiryTodo() {
@Test
func approachingExpiryTodo() {
let example = Example("fatalError() // TODO: [\(dateString(for: .approachingExpiry))] Implement")
let violations = self.violations(example)
XCTAssertEqual(violations.count, 1)
XCTAssertEqual(violations.first!.reason, "TODO/FIXME is approaching its expiry and should be resolved soon")
#expect(violations.count == 1)
#expect(violations.first?.reason == "TODO/FIXME is approaching its expiry and should be resolved soon")
}
func testNonExpiredTodo() {
@Test
func nonExpiredTodo() {
let example = Example("fatalError() // TODO: [\(dateString(for: .badFormatting))] Implement")
XCTAssertEqual(violations(example).count, 0)
#expect(violations(example).isEmpty)
}
func testExpiredCustomDelimiters() {
@Test
func expiredCustomDelimiters() {
let ruleConfig = ExpiringTodoConfiguration(
dateDelimiters: .init(opening: "<", closing: ">")
)
let example = Example("fatalError() // TODO: <\(dateString(for: .expired))> Implement")
let violations = self.violations(example, ruleConfig)
XCTAssertEqual(violations.count, 1)
XCTAssertEqual(violations.first!.reason, "TODO/FIXME has expired and must be resolved")
#expect(violations.count == 1)
#expect(violations.first?.reason == "TODO/FIXME has expired and must be resolved")
}
func testExpiredCustomSeparator() {
@Test
func expiredCustomSeparator() {
let ruleConfig = ExpiringTodoConfiguration(
dateFormat: "MM-dd-yyyy",
dateSeparator: "-"
@@ -52,21 +62,23 @@ final class ExpiringTodoRuleTests: SwiftLintTestCase {
"fatalError() // TODO: [\(dateString(for: .expired, format: ruleConfig.dateFormat))] Implement"
)
let violations = self.violations(example, ruleConfig)
XCTAssertEqual(violations.count, 1)
XCTAssertEqual(violations.first!.reason, "TODO/FIXME has expired and must be resolved")
#expect(violations.count == 1)
#expect(violations.first?.reason == "TODO/FIXME has expired and must be resolved")
}
func testExpiredCustomFormat() {
@Test
func expiredCustomFormat() {
let ruleConfig = ExpiringTodoConfiguration(dateFormat: "yyyy/MM/dd")
let example = Example(
"fatalError() // TODO: [\(dateString(for: .expired, format: ruleConfig.dateFormat))] Implement"
)
let violations = self.violations(example, ruleConfig)
XCTAssertEqual(violations.count, 1)
XCTAssertEqual(violations.first!.reason, "TODO/FIXME has expired and must be resolved")
#expect(violations.count == 1)
#expect(violations.first?.reason == "TODO/FIXME has expired and must be resolved")
}
func testMultipleExpiredTodos() {
@Test
func multipleExpiredTodos() throws {
let example = Example(
"""
fatalError() // TODO: [\(dateString(for: .expired))] Implement one
@@ -74,14 +86,15 @@ final class ExpiringTodoRuleTests: SwiftLintTestCase {
"""
)
let violations = self.violations(example)
XCTAssertEqual(violations.count, 2)
XCTAssertEqual(violations[0].reason, "TODO/FIXME has expired and must be resolved")
XCTAssertEqual(violations[0].location.line, 1)
XCTAssertEqual(violations[1].reason, "TODO/FIXME has expired and must be resolved")
XCTAssertEqual(violations[1].location.line, 2)
try #require(violations.count == 2)
#expect(violations[0].reason == "TODO/FIXME has expired and must be resolved")
#expect(violations[0].location.line == 1)
#expect(violations[1].reason == "TODO/FIXME has expired and must be resolved")
#expect(violations[1].location.line == 2)
}
func testTodoAndExpiredTodo() {
@Test
func todoAndExpiredTodo() {
let example = Example(
"""
// TODO: Implement one - without deadline
@@ -90,12 +103,13 @@ final class ExpiringTodoRuleTests: SwiftLintTestCase {
"""
)
let violations = self.violations(example)
XCTAssertEqual(violations.count, 1)
XCTAssertEqual(violations[0].reason, "TODO/FIXME has expired and must be resolved")
XCTAssertEqual(violations[0].location.line, 3)
#expect(violations.count == 1)
#expect(violations.first?.reason == "TODO/FIXME has expired and must be resolved")
#expect(violations.first?.location.line == 3)
}
func testMultilineExpiredTodo() {
@Test
func multilineExpiredTodo() {
let example = Example(
"""
// TODO: Multi-line task
@@ -105,12 +119,13 @@ final class ExpiringTodoRuleTests: SwiftLintTestCase {
"""
)
let violations = self.violations(example)
XCTAssertEqual(violations.count, 1)
XCTAssertEqual(violations[0].reason, "TODO/FIXME has expired and must be resolved")
XCTAssertEqual(violations[0].location.line, 3)
#expect(violations.count == 1)
#expect(violations.first?.reason == "TODO/FIXME has expired and must be resolved")
#expect(violations.first?.location.line == 3)
}
func testTodoFunctionAndExpiredTodo() {
@Test
func todoFunctionAndExpiredTodo() {
let example = Example(
"""
TODO()
@@ -118,19 +133,20 @@ final class ExpiringTodoRuleTests: SwiftLintTestCase {
"""
)
let violations = self.violations(example)
XCTAssertEqual(violations.count, 1)
XCTAssertEqual(violations[0].reason, "TODO/FIXME has expired and must be resolved")
XCTAssertEqual(violations[0].location.line, 2)
#expect(violations.count == 1)
#expect(violations.first?.reason == "TODO/FIXME has expired and must be resolved")
#expect(violations.first?.location.line == 2)
}
func testBadExpiryTodoFormat() throws {
@Test
func badExpiryTodoFormat() throws {
let ruleConfig = ExpiringTodoConfiguration(
dateFormat: "dd/yyyy/MM"
)
let example = Example("fatalError() // TODO: [31/01/2020] Implement")
let violations = self.violations(example, ruleConfig)
XCTAssertEqual(violations.count, 1)
XCTAssertEqual(violations.first?.reason, "Expiring TODO/FIXME is incorrectly formatted")
#expect(violations.count == 1)
#expect(violations.first?.reason == "Expiring TODO/FIXME is incorrectly formatted")
}
private func violations(_ example: Example, _ config: ExpiringTodoConfiguration? = nil) -> [StyleViolation] {
@@ -1,8 +1,12 @@
@testable import SwiftLintBuiltInRules
import TestHelpers
import Testing
final class ExplicitInitRuleTests: SwiftLintTestCase {
func testIncludeBareInit() {
@testable import SwiftLintBuiltInRules
@Suite(.rulesRegistered)
struct ExplicitInitRuleTests {
@Test
func includeBareInit() {
let nonTriggeringExamples = [
Example("let foo = Foo()"),
Example("let foo = init()"),
@@ -1,16 +1,20 @@
import TestHelpers
import Testing
@testable import SwiftLintBuiltInRules
@testable import SwiftLintCore
import TestHelpers
import XCTest
final class ExplicitTypeInterfaceConfigurationTests: SwiftLintTestCase {
func testDefaultConfiguration() {
@Suite(.rulesRegistered)
struct ExplicitTypeInterfaceConfigurationTests {
@Test
func defaultConfiguration() {
let config = ExplicitTypeInterfaceConfiguration()
XCTAssertEqual(config.severityConfiguration.severity, .warning)
XCTAssertEqual(config.allowedKinds, Set([.instance, .class, .static, .local]))
#expect(config.severityConfiguration.severity == .warning)
#expect(config.allowedKinds == Set([.instance, .class, .static, .local]))
}
func testApplyingCustomConfiguration() throws {
@Test
func applyingCustomConfiguration() throws {
var config = ExplicitTypeInterfaceConfiguration()
try config.apply(
configuration: [
@@ -19,42 +23,46 @@ final class ExplicitTypeInterfaceConfigurationTests: SwiftLintTestCase {
"allow_redundancy": true,
] as [String: any Sendable]
)
XCTAssertEqual(config.severityConfiguration.severity, .error)
XCTAssertEqual(config.allowedKinds, Set([.instance, .class, .static]))
XCTAssertTrue(config.allowRedundancy)
#expect(config.severityConfiguration.severity == .error)
#expect(config.allowedKinds == Set([.instance, .class, .static]))
#expect(config.allowRedundancy)
}
func testInvalidKeyInCustomConfiguration() async throws {
@Test
func invalidKeyInCustomConfiguration() async throws {
let console = try await Issue.captureConsole {
var config = ExplicitTypeInterfaceConfiguration()
try config.apply(configuration: ["invalidKey": "error"])
}
XCTAssertEqual(
console,
"warning: Configuration for 'explicit_type_interface' rule contains the invalid key(s) 'invalidKey'."
#expect(
console
== "warning: Configuration for 'explicit_type_interface' rule contains the invalid key(s) 'invalidKey'."
)
}
func testInvalidTypeOfCustomConfiguration() {
@Test
func invalidTypeOfCustomConfiguration() {
var config = ExplicitTypeInterfaceConfiguration()
checkError(Issue.invalidConfiguration(ruleID: ExplicitTypeInterfaceRule.identifier)) {
try config.apply(configuration: "invalidKey")
}
}
func testInvalidTypeOfValueInCustomConfiguration() {
@Test
func invalidTypeOfValueInCustomConfiguration() {
var config = ExplicitTypeInterfaceConfiguration()
checkError(Issue.invalidConfiguration(ruleID: ExplicitTypeInterfaceRule.identifier)) {
try config.apply(configuration: ["severity": "foo"])
}
}
func testConsoleDescription() throws {
@Test
func consoleDescription() throws {
var config = ExplicitTypeInterfaceConfiguration()
try config.apply(configuration: ["excluded": ["class", "instance"]])
XCTAssertEqual(
RuleConfigurationDescription.from(configuration: config).oneLiner(),
"severity: warning; excluded: [class, instance]; allow_redundancy: false"
#expect(
RuleConfigurationDescription.from(configuration: config).oneLiner()
== "severity: warning; excluded: [class, instance]; allow_redundancy: false"
)
}
}
@@ -1,8 +1,12 @@
@testable import SwiftLintBuiltInRules
import TestHelpers
import Testing
final class ExplicitTypeInterfaceRuleTests: SwiftLintTestCase {
func testLocalVars() {
@testable import SwiftLintBuiltInRules
@Suite(.rulesRegistered)
struct ExplicitTypeInterfaceRuleTests {
@Test
func localVars() {
let nonTriggeringExamples = [
Example("func foo() {\nlet intVal: Int = 1\n}"),
Example("""
@@ -30,7 +34,8 @@ final class ExplicitTypeInterfaceRuleTests: SwiftLintTestCase {
verifyRule(description)
}
func testExcludeLocalVars() {
@Test
func excludeLocalVars() {
let nonTriggeringExamples = ExplicitTypeInterfaceRule.description.nonTriggeringExamples + [
Example("func foo() {\nlet intVal = 1\n}")
]
@@ -42,7 +47,8 @@ final class ExplicitTypeInterfaceRuleTests: SwiftLintTestCase {
verifyRule(description, ruleConfiguration: ["excluded": ["local"]])
}
func testExcludeClassVars() {
@Test
func excludeClassVars() {
let nonTriggeringExamples = ExplicitTypeInterfaceRule.description.nonTriggeringExamples + [
Example("class Foo {\n static var myStaticVar = 0\n}\n"),
Example("class Foo {\n static let myStaticLet = 0\n}\n"),
@@ -59,7 +65,8 @@ final class ExplicitTypeInterfaceRuleTests: SwiftLintTestCase {
verifyRule(description, ruleConfiguration: ["excluded": ["static"]])
}
func testAllowRedundancy() {
@Test
func allowRedundancy() {
let nonTriggeringExamples: [Example] = [
Example("class Foo {\n var myVar: Int? = 0\n}\n"),
Example("class Foo {\n let myVar: Int? = 0\n}\n"),
@@ -90,7 +97,8 @@ final class ExplicitTypeInterfaceRuleTests: SwiftLintTestCase {
verifyRule(description, ruleConfiguration: ["allow_redundancy": true])
}
func testEmbeddedInStatements() {
@Test
func embeddedInStatements() {
let nonTriggeringExamples = [
Example("""
func foo() {
@@ -117,7 +125,8 @@ final class ExplicitTypeInterfaceRuleTests: SwiftLintTestCase {
verifyRule(description)
}
func testCaptureGroup() {
@Test
func captureGroup() {
let nonTriggeringExamples = [
Example("""
var k: Int = 0
@@ -150,7 +159,8 @@ final class ExplicitTypeInterfaceRuleTests: SwiftLintTestCase {
verifyRule(description)
}
func testFastEnumerationDeclaration() {
@Test
func fastEnumerationDeclaration() {
let nonTriggeringExamples = [
Example("""
func foo() {
@@ -173,7 +183,8 @@ final class ExplicitTypeInterfaceRuleTests: SwiftLintTestCase {
verifyRule(description)
}
func testSwitchCaseDeclarations() {
@Test
func switchCaseDeclarations() {
let nonTriggeringExamples = [
Example("""
enum Foo {
@@ -1,21 +1,25 @@
@testable import SwiftLintBuiltInRules
import TestHelpers
import XCTest
import Testing
@testable import SwiftLintBuiltInRules
private let fixturesDirectory = "\(TestResources.path())/FileHeaderRuleFixtures"
final class FileHeaderRuleTests: SwiftLintTestCase {
@Suite(.rulesRegistered)
struct FileHeaderRuleTests {
private func validate(fileName: String, using configuration: Any) throws -> [StyleViolation] {
let file = SwiftLintFile(path: fixturesDirectory.stringByAppendingPathComponent(fileName))!
let rule = try FileHeaderRule(configuration: configuration)
return rule.validate(file: file)
}
func testFileHeaderWithDefaultConfiguration() {
@Test
func fileHeaderWithDefaultConfiguration() {
verifyRule(FileHeaderRule.description, skipCommentTests: true)
}
func testFileHeaderWithRequiredString() {
@Test
func fileHeaderWithRequiredString() {
let nonTriggeringExamples = [
Example("// **Header"),
Example("//\n// **Header"),
@@ -37,7 +41,8 @@ final class FileHeaderRuleTests: SwiftLintTestCase {
testShebang: false)
}
func testFileHeaderWithRequiredPattern() {
@Test
func fileHeaderWithRequiredPattern() {
let nonTriggeringExamples = [
Example("// Copyright © 2016 Realm"),
Example("//\n// Copyright © 2016 Realm)"),
@@ -56,7 +61,8 @@ final class FileHeaderRuleTests: SwiftLintTestCase {
testMultiByteOffsets: false)
}
func testFileHeaderWithRequiredStringAndURLComment() {
@Test
func fileHeaderWithRequiredStringAndURLComment() {
let nonTriggeringExamples = [
Example("/* Check this url: https://github.com/realm/SwiftLint */")
]
@@ -73,7 +79,8 @@ final class FileHeaderRuleTests: SwiftLintTestCase {
testMultiByteOffsets: false)
}
func testFileHeaderWithForbiddenString() {
@Test
func fileHeaderWithForbiddenString() {
let nonTriggeringExamples = [
Example("// Copyright\n"),
Example("let foo = \"**All rights reserved.\""),
@@ -93,7 +100,8 @@ final class FileHeaderRuleTests: SwiftLintTestCase {
skipCommentTests: true)
}
func testFileHeaderWithForbiddenPattern() {
@Test
func fileHeaderWithForbiddenPattern() {
let nonTriggeringExamples = [
Example("// Copyright\n"),
Example("// FileHeaderRuleTests.m\n"),
@@ -113,7 +121,8 @@ final class FileHeaderRuleTests: SwiftLintTestCase {
skipCommentTests: true)
}
func testFileHeaderWithForbiddenPatternAndDocComment() {
@Test
func fileHeaderWithForbiddenPatternAndDocComment() {
let nonTriggeringExamples = [
Example("/// This is great tool with tests.\nclass GreatTool {}"),
Example("class GreatTool {}"),
@@ -130,78 +139,84 @@ final class FileHeaderRuleTests: SwiftLintTestCase {
skipCommentTests: true, testMultiByteOffsets: false)
}
func testFileHeaderWithRequiredStringUsingFilenamePlaceholder() {
@Test
func fileHeaderWithRequiredStringUsingFilenamePlaceholder() throws {
let configuration = ["required_string": "// SWIFTLINT_CURRENT_FILENAME"]
// Non triggering tests
XCTAssert(try validate(fileName: "FileNameMatchingSimple.swift", using: configuration).isEmpty)
try #expect(validate(fileName: "FileNameMatchingSimple.swift", using: configuration).isEmpty)
// Triggering tests
XCTAssertEqual(try validate(fileName: "FileNameCaseMismatch.swift", using: configuration).count, 1)
XCTAssertEqual(try validate(fileName: "FileNameMismatch.swift", using: configuration).count, 1)
XCTAssertEqual(try validate(fileName: "FileNameMissing.swift", using: configuration).count, 1)
try #expect(validate(fileName: "FileNameCaseMismatch.swift", using: configuration).count == 1)
try #expect(validate(fileName: "FileNameMismatch.swift", using: configuration).count == 1)
try #expect(validate(fileName: "FileNameMissing.swift", using: configuration).count == 1)
}
func testFileHeaderWithForbiddenStringUsingFilenamePlaceholder() {
@Test
func fileHeaderWithForbiddenStringUsingFilenamePlaceholder() throws {
let configuration = ["forbidden_string": "// SWIFTLINT_CURRENT_FILENAME"]
// Non triggering tests
XCTAssert(try validate(fileName: "FileNameCaseMismatch.swift", using: configuration).isEmpty)
XCTAssert(try validate(fileName: "FileNameMismatch.swift", using: configuration).isEmpty)
XCTAssert(try validate(fileName: "FileNameMissing.swift", using: configuration).isEmpty)
try #expect(validate(fileName: "FileNameCaseMismatch.swift", using: configuration).isEmpty)
try #expect(validate(fileName: "FileNameMismatch.swift", using: configuration).isEmpty)
try #expect(validate(fileName: "FileNameMissing.swift", using: configuration).isEmpty)
// Triggering tests
XCTAssertEqual(try validate(fileName: "FileNameMatchingSimple.swift", using: configuration).count, 1)
#expect(try validate(fileName: "FileNameMatchingSimple.swift", using: configuration).count == 1)
}
func testFileHeaderWithRequiredPatternUsingFilenamePlaceholder() {
@Test
func fileHeaderWithRequiredPatternUsingFilenamePlaceholder() throws {
let configuration1 = ["required_pattern": "// SWIFTLINT_CURRENT_FILENAME\n.*\\d{4}"]
let configuration2 = [
"required_pattern": "// Copyright © \\d{4}\n// File: \"SWIFTLINT_CURRENT_FILENAME\"",
"required_pattern": "// Copyright © \\d{4}\n// File: \"SWIFTLINT_CURRENT_FILENAME\""
]
// Non triggering tests
XCTAssert(try validate(fileName: "FileNameMatchingSimple.swift", using: configuration1).isEmpty)
XCTAssert(try validate(fileName: "FileNameMatchingComplex.swift", using: configuration2).isEmpty)
try #expect(validate(fileName: "FileNameMatchingSimple.swift", using: configuration1).isEmpty)
try #expect(validate(fileName: "FileNameMatchingComplex.swift", using: configuration2).isEmpty)
// Triggering tests
XCTAssertEqual(try validate(fileName: "FileNameCaseMismatch.swift", using: configuration1).count, 1)
XCTAssertEqual(try validate(fileName: "FileNameMismatch.swift", using: configuration1).count, 1)
XCTAssertEqual(try validate(fileName: "FileNameMissing.swift", using: configuration1).count, 1)
try #expect(validate(fileName: "FileNameCaseMismatch.swift", using: configuration1).count == 1)
try #expect(validate(fileName: "FileNameMismatch.swift", using: configuration1).count == 1)
try #expect(validate(fileName: "FileNameMissing.swift", using: configuration1).count == 1)
}
func testFileHeaderWithForbiddenPatternUsingFilenamePlaceholder() {
@Test
func fileHeaderWithForbiddenPatternUsingFilenamePlaceholder() throws {
let configuration1 = ["forbidden_pattern": "// SWIFTLINT_CURRENT_FILENAME\n.*\\d{4}"]
let configuration2 = ["forbidden_pattern": "//.*(\\s|\")SWIFTLINT_CURRENT_FILENAME(\\s|\").*"]
// Non triggering tests
XCTAssert(try validate(fileName: "FileNameCaseMismatch.swift", using: configuration1).isEmpty)
XCTAssert(try validate(fileName: "FileNameMismatch.swift", using: configuration1).isEmpty)
XCTAssert(try validate(fileName: "FileNameMissing.swift", using: configuration1).isEmpty)
try #expect(validate(fileName: "FileNameCaseMismatch.swift", using: configuration1).isEmpty)
try #expect(validate(fileName: "FileNameMismatch.swift", using: configuration1).isEmpty)
try #expect(validate(fileName: "FileNameMissing.swift", using: configuration1).isEmpty)
XCTAssert(try validate(fileName: "FileNameCaseMismatch.swift", using: configuration2).isEmpty)
XCTAssert(try validate(fileName: "FileNameMismatch.swift", using: configuration2).isEmpty)
XCTAssert(try validate(fileName: "FileNameMissing.swift", using: configuration2).isEmpty)
try #expect(validate(fileName: "FileNameCaseMismatch.swift", using: configuration2).isEmpty)
try #expect(validate(fileName: "FileNameMismatch.swift", using: configuration2).isEmpty)
try #expect(validate(fileName: "FileNameMissing.swift", using: configuration2).isEmpty)
// Triggering tests
XCTAssertEqual(try validate(fileName: "FileNameMatchingSimple.swift", using: configuration1).count, 1)
XCTAssertEqual(try validate(fileName: "FileNameMatchingComplex.swift", using: configuration2).count, 1)
try #expect(validate(fileName: "FileNameMatchingSimple.swift", using: configuration1).count == 1)
try #expect(validate(fileName: "FileNameMatchingComplex.swift", using: configuration2).count == 1)
}
func testFileHeaderShouldBeEmpty() {
@Test
func fileHeaderShouldBeEmpty() throws {
let configuration = ["forbidden_pattern": "."]
// Non triggering tests
XCTAssert(try validate(fileName: "FileHeaderEmpty.swift", using: configuration).isEmpty)
XCTAssert(try validate(fileName: "DocumentedType.swift", using: configuration).isEmpty)
try #expect(validate(fileName: "FileHeaderEmpty.swift", using: configuration).isEmpty)
try #expect(validate(fileName: "DocumentedType.swift", using: configuration).isEmpty)
// Triggering tests
XCTAssertEqual(try validate(fileName: "FileNameCaseMismatch.swift", using: configuration).count, 1)
XCTAssertEqual(try validate(fileName: "FileNameMismatch.swift", using: configuration).count, 1)
XCTAssertEqual(try validate(fileName: "FileNameMissing.swift", using: configuration).count, 1)
try #expect(validate(fileName: "FileNameCaseMismatch.swift", using: configuration).count == 1)
try #expect(validate(fileName: "FileNameMismatch.swift", using: configuration).count == 1)
try #expect(validate(fileName: "FileNameMissing.swift", using: configuration).count == 1)
}
func testSimplePattern() {
@Test
func simplePattern() {
let description = FileHeaderRule.description
.with(nonTriggeringExamples: [
Example("""
@@ -232,7 +247,8 @@ final class FileHeaderRuleTests: SwiftLintTestCase {
)
}
func testPattern() {
@Test
func pattern() {
let description = FileHeaderRule.description
.with(nonTriggeringExamples: [
Example("""
@@ -1,13 +1,18 @@
@testable import SwiftLintBuiltInRules
import TestHelpers
import Testing
final class FileLengthRuleTests: SwiftLintTestCase {
func testFileLengthWithDefaultConfiguration() {
@testable import SwiftLintBuiltInRules
@Suite(.rulesRegistered)
struct FileLengthRuleTests {
@Test
func fileLengthWithDefaultConfiguration() {
verifyRule(FileLengthRule.description, commentDoesntViolate: false,
testMultiByteOffsets: false, testShebang: false)
}
func testFileLengthIgnoringLinesWithOnlyComments() {
@Test
func fileLengthIgnoringLinesWithOnlyComments() {
let triggeringExamples = [
Example(repeatElement("print(\"swiftlint\")\n", count: 401).joined())
]
@@ -1,11 +1,13 @@
import SourceKittenFramework
@testable import SwiftLintBuiltInRules
import TestHelpers
import XCTest
import Testing
@testable import SwiftLintBuiltInRules
private let fixturesDirectory = "\(TestResources.path())/FileNameNoSpaceRuleFixtures"
final class FileNameNoSpaceRuleTests: SwiftLintTestCase {
@Suite(.rulesRegistered)
struct FileNameNoSpaceRuleTests {
private func validate(fileName: String, excludedOverride: [String]? = nil) throws -> [StyleViolation] {
let file = SwiftLintFile(path: fixturesDirectory.stringByAppendingPathComponent(fileName))!
let rule: FileNameNoSpaceRule
@@ -18,24 +20,33 @@ final class FileNameNoSpaceRuleTests: SwiftLintTestCase {
return rule.validate(file: file)
}
func testFileNameDoesntTrigger() {
XCTAssert(try validate(fileName: "File.swift").isEmpty)
@Test
func fileNameDoesntTrigger() throws {
try #expect(validate(fileName: "File.swift").isEmpty)
}
func testFileWithSpaceDoesTrigger() {
XCTAssertEqual(try validate(fileName: "File Name.swift").count, 1)
@Test
func fileWithSpaceDoesTrigger() throws {
try #expect(validate(fileName: "File Name.swift").count == 1)
}
func testExtensionNameDoesntTrigger() {
XCTAssert(try validate(fileName: "File+Extension.swift").isEmpty)
@Test
func extensionNameDoesntTrigger() throws {
try #expect(validate(fileName: "File+Extension.swift").isEmpty)
}
func testExtensionWithSpaceDoesTrigger() {
XCTAssertEqual(try validate(fileName: "File+Test Extension.swift").count, 1)
@Test
func extensionWithSpaceDoesTrigger() throws {
try #expect(validate(fileName: "File+Test Extension.swift").count == 1)
}
func testCustomExcludedList() {
XCTAssert(try validate(fileName: "File+Test Extension.swift",
excludedOverride: ["File+Test Extension.swift"]).isEmpty)
@Test
func customExcludedList() throws {
try #expect(
validate(
fileName: "File+Test Extension.swift",
excludedOverride: ["File+Test Extension.swift"]
).isEmpty
)
}
}
+96 -71
View File
@@ -1,10 +1,12 @@
@testable import SwiftLintBuiltInRules
import TestHelpers
import XCTest
import Testing
@testable import SwiftLintBuiltInRules
private let fixturesDirectory = "\(TestResources.path())/FileNameRuleFixtures"
final class FileNameRuleTests: SwiftLintTestCase {
@Suite(.rulesRegistered)
struct FileNameRuleTests {
private func validate(fileName: String,
excluded: [String]? = nil,
excludedPaths: [String]? = nil,
@@ -40,94 +42,113 @@ final class FileNameRuleTests: SwiftLintTestCase {
return rule.validate(file: file)
}
func testMainDoesntTrigger() {
XCTAssert(try validate(fileName: "main.swift").isEmpty)
@Test
func mainDoesntTrigger() throws {
try #expect(validate(fileName: "main.swift").isEmpty)
}
func testLinuxMainDoesntTrigger() {
XCTAssert(try validate(fileName: "LinuxMain.swift").isEmpty)
@Test
func linuxMainDoesntTrigger() throws {
try #expect(validate(fileName: "LinuxMain.swift").isEmpty)
}
func testClassNameDoesntTrigger() {
XCTAssert(try validate(fileName: "MyClass.swift").isEmpty)
@Test
func classNameDoesntTrigger() throws {
try #expect(validate(fileName: "MyClass.swift").isEmpty)
}
func testStructNameDoesntTrigger() {
XCTAssert(try validate(fileName: "MyStruct.swift").isEmpty)
@Test
func structNameDoesntTrigger() throws {
try #expect(validate(fileName: "MyStruct.swift").isEmpty)
}
func testMacroNameDoesntTrigger() {
XCTAssert(try validate(fileName: "MyMacro.swift").isEmpty)
@Test
func macroNameDoesntTrigger() throws {
try #expect(validate(fileName: "MyMacro.swift").isEmpty)
}
func testExtensionNameDoesntTrigger() {
XCTAssert(try validate(fileName: "NSString+Extension.swift").isEmpty)
@Test
func extensionNameDoesntTrigger() throws {
try #expect(validate(fileName: "NSString+Extension.swift").isEmpty)
}
func testNestedExtensionDoesntTrigger() {
XCTAssert(try validate(fileName: "Notification.Name+Extension.swift").isEmpty)
@Test
func nestedExtensionDoesntTrigger() throws {
try #expect(validate(fileName: "Notification.Name+Extension.swift").isEmpty)
}
func testNestedTypeDoesntTrigger() {
XCTAssert(try validate(fileName: "Nested.MyType.swift").isEmpty)
@Test
func nestedTypeDoesntTrigger() throws {
try #expect(validate(fileName: "Nested.MyType.swift").isEmpty)
}
func testMultipleLevelsDeeplyNestedTypeDoesntTrigger() {
XCTAssert(try validate(fileName: "Multiple.Levels.Deeply.Nested.MyType.swift").isEmpty)
@Test
func multipleLevelsDeeplyNestedTypeDoesntTrigger() throws {
try #expect(validate(fileName: "Multiple.Levels.Deeply.Nested.MyType.swift").isEmpty)
}
func testNestedTypeNotFullyQualifiedDoesntTrigger() {
XCTAssert(try validate(fileName: "MyType.swift").isEmpty)
@Test
func nestedTypeNotFullyQualifiedDoesntTrigger() throws {
try #expect(validate(fileName: "MyType.swift").isEmpty)
}
func testNestedTypeNotFullyQualifiedDoesTriggerWithOverride() {
XCTAssert(try validate(fileName: "MyType.swift", requireFullyQualifiedNames: true).isNotEmpty)
@Test
func nestedTypeNotFullyQualifiedDoesTriggerWithOverride() throws {
try #expect(validate(fileName: "MyType.swift", requireFullyQualifiedNames: true).isNotEmpty)
}
func testNestedTypeSeparatorDoesntTrigger() {
XCTAssert(try validate(fileName: "NotificationName+Extension.swift", nestedTypeSeparator: "").isEmpty)
XCTAssert(try validate(fileName: "Notification__Name+Extension.swift", nestedTypeSeparator: "__").isEmpty)
@Test
func nestedTypeSeparatorDoesntTrigger() throws {
try #expect(validate(fileName: "NotificationName+Extension.swift", nestedTypeSeparator: "").isEmpty)
try #expect(validate(fileName: "Notification__Name+Extension.swift", nestedTypeSeparator: "__").isEmpty)
}
func testWrongNestedTypeSeparatorDoesTrigger() {
XCTAssert(try validate(fileName: "Notification__Name+Extension.swift", nestedTypeSeparator: ".").isNotEmpty)
XCTAssert(try validate(fileName: "NotificationName+Extension.swift", nestedTypeSeparator: "__").isNotEmpty)
@Test
func wrongNestedTypeSeparatorDoesTrigger() throws {
try #expect(validate(fileName: "Notification__Name+Extension.swift", nestedTypeSeparator: ".").isNotEmpty)
try #expect(validate(fileName: "NotificationName+Extension.swift", nestedTypeSeparator: "__").isNotEmpty)
}
func testMisspelledNameDoesTrigger() {
XCTAssertEqual(try validate(fileName: "MyStructf.swift").count, 1)
@Test
func misspelledNameDoesTrigger() throws {
try #expect(validate(fileName: "MyStructf.swift").count == 1)
}
func testMisspelledNameDoesntTriggerWithOverride() {
XCTAssert(try validate(fileName: "MyStructf.swift", excluded: ["MyStructf.swift"]).isEmpty)
@Test
func misspelledNameDoesntTriggerWithOverride() throws {
try #expect(validate(fileName: "MyStructf.swift", excluded: ["MyStructf.swift"]).isEmpty)
}
func testMainDoesTriggerWithoutOverride() {
XCTAssertEqual(try validate(fileName: "main.swift", excluded: []).count, 1)
@Test
func mainDoesTriggerWithoutOverride() throws {
try #expect(validate(fileName: "main.swift", excluded: []).count == 1)
}
func testCustomSuffixPattern() {
XCTAssert(try validate(fileName: "BoolExtension.swift", suffixPattern: "Extensions?").isEmpty)
XCTAssert(try validate(fileName: "BoolExtensions.swift", suffixPattern: "Extensions?").isEmpty)
XCTAssert(try validate(fileName: "BoolExtensionTests.swift", suffixPattern: "Extensions?|\\+.*").isEmpty)
@Test
func customSuffixPattern() throws {
try #expect(validate(fileName: "BoolExtension.swift", suffixPattern: "Extensions?").isEmpty)
try #expect(validate(fileName: "BoolExtensions.swift", suffixPattern: "Extensions?").isEmpty)
try #expect(validate(fileName: "BoolExtensionTests.swift", suffixPattern: "Extensions?|\\+.*").isEmpty)
}
func testCustomPrefixPattern() {
XCTAssert(try validate(fileName: "ExtensionBool.swift", prefixPattern: "Extensions?").isEmpty)
XCTAssert(try validate(fileName: "ExtensionsBool.swift", prefixPattern: "Extensions?").isEmpty)
@Test
func customPrefixPattern() throws {
try #expect(validate(fileName: "ExtensionBool.swift", prefixPattern: "Extensions?").isEmpty)
try #expect(validate(fileName: "ExtensionsBool.swift", prefixPattern: "Extensions?").isEmpty)
}
func testCustomPrefixAndSuffixPatterns() {
XCTAssert(
try validate(
@Test
func customPrefixAndSuffixPatterns() throws {
try #expect(
validate(
fileName: "SLBoolExtension.swift",
prefixPattern: "SL",
suffixPattern: "Extensions?|\\+.*"
).isEmpty
)
XCTAssert(
try validate(
try #expect(
validate(
fileName: "ExtensionBool+SwiftLint.swift",
prefixPattern: "Extensions?",
suffixPattern: "Extensions?|\\+.*"
@@ -135,34 +156,36 @@ final class FileNameRuleTests: SwiftLintTestCase {
)
}
func testExcludedDoesntSupportRegex() {
XCTAssert(
try validate(
@Test
func excludedDoesntSupportRegex() throws {
try #expect(
validate(
fileName: "main.swift",
excluded: [".*"]
).isNotEmpty
)
}
func testExcludedPathPatternsSupportRegex() {
XCTAssert(
try validate(
@Test
func excludedPathPatternsSupportRegex() throws {
try #expect(
validate(
fileName: "main.swift",
excluded: [],
excludedPaths: [".*"]
).isEmpty
)
XCTAssert(
try validate(
try #expect(
validate(
fileName: "main.swift",
excluded: [],
excludedPaths: [".*.swift"]
).isEmpty
)
XCTAssert(
try validate(
try #expect(
validate(
fileName: "main.swift",
excluded: [],
excludedPaths: [".*/FileNameRuleFixtures/.*"]
@@ -170,9 +193,10 @@ final class FileNameRuleTests: SwiftLintTestCase {
)
}
func testExcludedPathPatternsWithRegexDoesntMatch() {
XCTAssert(
try validate(
@Test
func excludedPathPatternsWithRegexDoesntMatch() throws {
try #expect(
validate(
fileName: "main.swift",
excluded: [],
excludedPaths: [".*/OtherFolder/.*", "MAIN\\.swift"]
@@ -180,8 +204,9 @@ final class FileNameRuleTests: SwiftLintTestCase {
)
}
func testInvalidRegex() {
XCTAssertThrowsError(
@Test
func invalidRegex() throws {
#expect(throws: (any Error).self) {
try validate(
fileName: "NSString+Extension.swift",
excluded: [],
@@ -189,24 +214,24 @@ final class FileNameRuleTests: SwiftLintTestCase {
prefixPattern: "",
suffixPattern: ""
)
)
}
}
func testExcludedPathPatternsWithMultipleRegexs() {
XCTAssertThrowsError(
@Test
func excludedPathPatternsWithMultipleRegexs() throws {
#expect(throws: (any Error).self) {
try validate(
fileName: "main.swift",
excluded: [],
excludedPaths: ["/FileNameRuleFixtures/.*", "("]
)
)
XCTAssertThrowsError(
}
#expect(throws: (any Error).self) {
try validate(
fileName: "main.swift",
excluded: [],
excludedPaths: ["/FileNameRuleFixtures/.*", "(", ".*.swift"]
)
)
}
}
}
@@ -1,9 +1,12 @@
@testable import SwiftLintBuiltInRules
import TestHelpers
import Testing
final class FileTypesOrderRuleTests: SwiftLintTestCase {
// swiftlint:disable:next function_body_length
func testFileTypesOrderReversedOrder() {
@testable import SwiftLintBuiltInRules
@Suite(.rulesRegistered)
struct FileTypesOrderRuleTests {
@Test
func fileTypesOrderReversedOrder() { // swiftlint:disable:this function_body_length
// Test with reversed `order` entries
let nonTriggeringExamples = [
Example(FileTypesOrderRuleExamples.defaultOrderParts.reversed().joined(separator: "\n\n"))
@@ -82,7 +85,8 @@ final class FileTypesOrderRuleTests: SwiftLintTestCase {
)
}
func testFileTypesOrderGroupedOrder() {
@Test
func fileTypesOrderGroupedOrder() {
// Test with grouped `order` entries
let nonTriggeringExamples = [
Example("""
@@ -1,10 +1,14 @@
@testable import SwiftLintBuiltInRules
import TestHelpers
import XCTest
import Testing
final class FunctionBodyLengthRuleTests: SwiftLintTestCase {
func testWarning() {
let example = Example("""
@testable import SwiftLintBuiltInRules
@Suite(.rulesRegistered)
struct FunctionBodyLengthRuleTests {
@Test
func warning() {
let example = Example(
"""
func f() {
let x = 0
let y = 1
@@ -12,9 +16,8 @@ final class FunctionBodyLengthRuleTests: SwiftLintTestCase {
}
""")
XCTAssertEqual(
self.violations(example, configuration: ["warning": 2, "error": 4]),
[
#expect(
self.violations(example, configuration: ["warning": 2, "error": 4]) == [
StyleViolation(
ruleDescription: FunctionBodyLengthRule.description,
severity: .warning,
@@ -28,7 +31,8 @@ final class FunctionBodyLengthRuleTests: SwiftLintTestCase {
)
}
func testError() {
@Test
func error() {
let example = Example("""
func f() {
let x = 0
@@ -37,9 +41,8 @@ final class FunctionBodyLengthRuleTests: SwiftLintTestCase {
}
""")
XCTAssertEqual(
self.violations(example, configuration: ["warning": 1, "error": 2]),
[
#expect(
self.violations(example, configuration: ["warning": 1, "error": 2]) == [
StyleViolation(
ruleDescription: FunctionBodyLengthRule.description,
severity: .error,
@@ -53,16 +56,16 @@ final class FunctionBodyLengthRuleTests: SwiftLintTestCase {
)
}
func testViolationMessages() {
@Test
func violationMessages() {
let types = FunctionBodyLengthRule.description.triggeringExamples.flatMap {
self.violations($0, configuration: ["warning": 2])
violations($0, configuration: ["warning": 2])
}.compactMap {
$0.reason.split(separator: " ", maxSplits: 1).first
}
XCTAssertEqual(
types,
["Function", "Deinitializer", "Initializer", "Subscript", "Accessor", "Accessor", "Accessor"]
#expect(
types == ["Function", "Deinitializer", "Initializer", "Subscript", "Accessor", "Accessor", "Accessor"]
)
}
@@ -1,8 +1,10 @@
@testable import SwiftLintBuiltInRules
import TestHelpers
import XCTest
import Testing
final class FunctionNameWhitespaceRuleTests: SwiftLintTestCase {
@testable import SwiftLintBuiltInRules
@Suite(.rulesRegistered)
struct FunctionNameWhitespaceRuleTests {
private typealias GenericSpacingType = FunctionNameWhitespaceConfiguration.GenericSpacingType
private static let operatorWhitespaceViolationReason =
@@ -16,7 +18,7 @@ final class FunctionNameWhitespaceRuleTests: SwiftLintTestCase {
_ source: String,
configuration: [String: String]? = nil,
expected: String,
file: StaticString = #filePath,
file: String = #filePath,
line: UInt = #line
) {
let example = configuration == nil
@@ -24,7 +26,10 @@ final class FunctionNameWhitespaceRuleTests: SwiftLintTestCase {
: Example(source, configuration: configuration!)
let violations = ruleViolations(example)
XCTAssertEqual(violations.first?.reason, expected, file: file, line: line)
#expect(
violations.first?.reason == expected,
sourceLocation: SourceLocation(fileID: #fileID, filePath: file, line: Int(line), column: 1)
)
}
private func ruleViolations(
@@ -39,7 +44,8 @@ final class FunctionNameWhitespaceRuleTests: SwiftLintTestCase {
// MARK: - func keyword spacing
func testSpaceBetweenFuncKeywordAndName_ShouldReportReason() {
@Test
func spaceBetweenFuncKeywordAndName_ShouldReportReason() {
assertReason(
"func abc(lhs: Int, rhs: Int) -> Int {}",
expected: Self.funcKeywordSpacingViolationReason
@@ -48,35 +54,40 @@ final class FunctionNameWhitespaceRuleTests: SwiftLintTestCase {
// MARK: - operator functions
func testOperatorFunctionSpacing_WhenNoSpaceAfterOperator_ShouldReportOperatorMessage() {
@Test
func operatorFunctionSpacing_WhenNoSpaceAfterOperator_ShouldReportOperatorMessage() {
assertReason(
"func <|(lhs: Int, rhs: Int) -> Int {}",
expected: Self.operatorWhitespaceViolationReason
)
}
func testOperatorFunctionSpacing_WhenTooManySpacesAfterOperator_ShouldReportOperatorMessage() {
@Test
func operatorFunctionSpacing_WhenTooManySpacesAfterOperator_ShouldReportOperatorMessage() {
assertReason(
"func <| (lhs: Int, rhs: Int) -> Int {}",
expected: Self.operatorWhitespaceViolationReason
)
}
func testOperatorFunctionWithGenerics_WhenNoSpaceAfterOperator_ShouldReportOperatorMessage() {
@Test
func operatorFunctionWithGenerics_WhenNoSpaceAfterOperator_ShouldReportOperatorMessage() {
assertReason(
"func <|<<A>(lhs: A, rhs: A) -> A {}",
expected: Self.operatorWhitespaceViolationReason
)
}
func testOperatorFunctionSpacing_WhenMultipleViolations_ShouldReportOperatorMessage() {
@Test
func operatorFunctionSpacing_WhenMultipleViolations_ShouldReportOperatorMessage() {
assertReason(
"func <| (lhs: Int, rhs: Int) -> Int {}",
expected: Self.operatorWhitespaceViolationReason
)
}
func testOperatorFunctionSpacing_WhenTooManySpacesBeforeAndAfter_ShouldReportOperatorMessage() {
@Test
func operatorFunctionSpacing_WhenTooManySpacesBeforeAndAfter_ShouldReportOperatorMessage() {
assertReason(
"func <| (lhs: Int, rhs: Int) -> Int {}",
expected: Self.operatorWhitespaceViolationReason
@@ -85,7 +96,8 @@ final class FunctionNameWhitespaceRuleTests: SwiftLintTestCase {
// MARK: - generic_spacing = no_space
func testSpaceAfterFuncName_WhenNoSpaceConfigured_ShouldReport() {
@Test
func spaceAfterFuncName_WhenNoSpaceConfigured_ShouldReport() {
assertReason(
"func abc (lhs: Int) {}",
configuration: ["generic_spacing": "no_space"],
@@ -93,7 +105,8 @@ final class FunctionNameWhitespaceRuleTests: SwiftLintTestCase {
)
}
func testSpaceAfterGeneric_WhenNoSpaceConfigured_ShouldReport() {
@Test
func spaceAfterGeneric_WhenNoSpaceConfigured_ShouldReport() {
assertReason(
"func abc<T> (lhs: Int) {}",
configuration: ["generic_spacing": "no_space"],
@@ -103,7 +116,8 @@ final class FunctionNameWhitespaceRuleTests: SwiftLintTestCase {
// MARK: - generic_spacing = leading_space
func testSpaceAfterFuncName_WhenLeadingSpaceConfigured_ShouldReport() {
@Test
func spaceAfterFuncName_WhenLeadingSpaceConfigured_ShouldReport() {
assertReason(
"func abc(lhs: Int) {}",
configuration: ["generic_spacing": "leading_space"],
@@ -111,7 +125,8 @@ final class FunctionNameWhitespaceRuleTests: SwiftLintTestCase {
)
}
func testSpaceBeforeGeneric_WhenLeadingSpaceConfigured_ShouldReport() {
@Test
func spaceBeforeGeneric_WhenLeadingSpaceConfigured_ShouldReport() {
assertReason(
"func abc<T>(lhs: Int) {}",
configuration: ["generic_spacing": "leading_space"],
@@ -121,7 +136,8 @@ final class FunctionNameWhitespaceRuleTests: SwiftLintTestCase {
// MARK: - generic_spacing = trailing_space
func testSpaceAfterFuncName_WhenTrailingSpaceConfigured_ShouldReport() {
@Test
func spaceAfterFuncName_WhenTrailingSpaceConfigured_ShouldReport() {
assertReason(
"func abc (lhs: Int) {}",
configuration: ["generic_spacing": "trailing_space"],
@@ -129,7 +145,8 @@ final class FunctionNameWhitespaceRuleTests: SwiftLintTestCase {
)
}
func testSpaceAfterGeneric_WhenTrailingSpaceConfigured_ShouldReport() {
@Test
func spaceAfterGeneric_WhenTrailingSpaceConfigured_ShouldReport() {
assertReason(
"func abc<T>(lhs: Int) {}",
configuration: ["generic_spacing": "trailing_space"],
@@ -139,7 +156,8 @@ final class FunctionNameWhitespaceRuleTests: SwiftLintTestCase {
// MARK: - generic_spacing = leading_trailing_space
func testSpaceAfterFuncName_WhenLeadingTrailingSpaceConfigured_ShouldReport() {
@Test
func spaceAfterFuncName_WhenLeadingTrailingSpaceConfigured_ShouldReport() {
assertReason(
"func abc(lhs: Int) {}",
configuration: ["generic_spacing": "leading_trailing_space"],
@@ -147,7 +165,8 @@ final class FunctionNameWhitespaceRuleTests: SwiftLintTestCase {
)
}
func testSpaceBeforeGeneric_WhenLeadingTrailingSpaceConfigured_ShouldReport() {
@Test
func spaceBeforeGeneric_WhenLeadingTrailingSpaceConfigured_ShouldReport() {
assertReason(
"func abc<T>(lhs: Int) {}",
configuration: ["generic_spacing": "leading_trailing_space"],
@@ -155,7 +174,8 @@ final class FunctionNameWhitespaceRuleTests: SwiftLintTestCase {
)
}
func testSpaceAfterGeneric_WhenLeadingTrailingSpaceConfigured_ShouldReport() {
@Test
func spaceAfterGeneric_WhenLeadingTrailingSpaceConfigured_ShouldReport() {
assertReason(
"func abc <T>(lhs: Int) {}",
configuration: ["generic_spacing": "leading_trailing_space"],
@@ -1,5 +1,7 @@
@testable import SwiftLintBuiltInRules
import TestHelpers
import Testing
@testable import SwiftLintBuiltInRules
private func funcWithParameters(_ parameters: String,
violates: Bool = false,
@@ -10,8 +12,10 @@ private func funcWithParameters(_ parameters: String,
return Example("func \(marker)abc(\(parameters)) {}\n", file: file, line: line)
}
final class FunctionParameterCountRuleTests: SwiftLintTestCase {
func testFunctionParameterCount() {
@Suite(.rulesRegistered)
struct FunctionParameterCountRuleTests {
@Test
func functionParameterCount() {
let baseDescription = FunctionParameterCountRule.description
let nonTriggeringExamples = [
funcWithParameters(repeatElement("x: Int, ", count: 3).joined() + "x: Int")
@@ -27,7 +31,8 @@ final class FunctionParameterCountRuleTests: SwiftLintTestCase {
verifyRule(description)
}
func testDefaultFunctionParameterCount() {
@Test
func defaultFunctionParameterCount() {
let baseDescription = FunctionParameterCountRule.description
let nonTriggeringExamples = [
funcWithParameters(repeatElement("x: Int, ", count: 3).joined() + "x: Int")
@@ -1,8 +1,12 @@
@testable import SwiftLintBuiltInRules
import TestHelpers
import Testing
final class GenericTypeNameRuleTests: SwiftLintTestCase {
func testGenericTypeNameWithExcluded() {
@testable import SwiftLintBuiltInRules
@Suite(.rulesRegistered)
struct GenericTypeNameRuleTests {
@Test
func genericTypeNameWithExcluded() {
let baseDescription = GenericTypeNameRule.description
let nonTriggeringExamples = baseDescription.nonTriggeringExamples + [
Example("func foo<apple> {}"),
@@ -18,7 +22,8 @@ final class GenericTypeNameRuleTests: SwiftLintTestCase {
verifyRule(description, ruleConfiguration: ["excluded": ["apple", "some.*", ".*st\\d+.*"]])
}
func testGenericTypeNameWithAllowedSymbols() {
@Test
func genericTypeNameWithAllowedSymbols() {
let baseDescription = GenericTypeNameRule.description
let nonTriggeringExamples = baseDescription.nonTriggeringExamples + [
Example("func foo<T$>() {}"),
@@ -33,7 +38,8 @@ final class GenericTypeNameRuleTests: SwiftLintTestCase {
verifyRule(description, ruleConfiguration: ["allowed_symbols": ["$", "%"]])
}
func testGenericTypeNameWithAllowedSymbolsAndViolation() {
@Test
func genericTypeNameWithAllowedSymbolsAndViolation() {
let baseDescription = GenericTypeNameRule.description
let triggeringExamples = [
Example("func foo<↓T_$>() {}")
@@ -43,7 +49,8 @@ final class GenericTypeNameRuleTests: SwiftLintTestCase {
verifyRule(description, ruleConfiguration: ["allowed_symbols": ["$", "%"]])
}
func testGenericTypeNameWithIgnoreStartWithLowercase() {
@Test
func genericTypeNameWithIgnoreStartWithLowercase() {
let baseDescription = GenericTypeNameRule.description
let triggeringExamplesToRemove = [
Example("func foo<↓type>() {}"),
@@ -1,9 +1,12 @@
@testable import SwiftLintBuiltInRules
import TestHelpers
import XCTest
import Testing
final class IdentifierNameRuleTests: SwiftLintTestCase {
func testIdentifierNameWithExcluded() {
@testable import SwiftLintBuiltInRules
@Suite(.rulesRegistered)
struct IdentifierNameRuleTests {
@Test
func identifierNameWithExcluded() {
let baseDescription = IdentifierNameRule.description
let nonTriggeringExamples = baseDescription.nonTriggeringExamples + [
Example("let Apple = 0"),
@@ -19,7 +22,8 @@ final class IdentifierNameRuleTests: SwiftLintTestCase {
verifyRule(description, ruleConfiguration: ["excluded": ["Apple", "some.*", ".*\\d+.*"]])
}
func testIdentifierNameWithAllowedSymbols() {
@Test
func identifierNameWithAllowedSymbols() {
let baseDescription = IdentifierNameRule.description
let nonTriggeringExamples = baseDescription.nonTriggeringExamples + [
Example("let myLet$ = 0"),
@@ -33,7 +37,8 @@ final class IdentifierNameRuleTests: SwiftLintTestCase {
verifyRule(description, ruleConfiguration: ["allowed_symbols": ["$", "%", "_"]])
}
func testIdentifierNameWithAllowedSymbolsAndViolation() {
@Test
func identifierNameWithAllowedSymbolsAndViolation() {
let baseDescription = IdentifierNameRule.description
let triggeringExamples = [
Example("let ↓my_Let$ = 0")
@@ -43,7 +48,8 @@ final class IdentifierNameRuleTests: SwiftLintTestCase {
verifyRule(description, ruleConfiguration: ["allowed_symbols": ["$", "%"]])
}
func testIdentifierNameWithIgnoreStartWithLowercase() {
@Test
func identifierNameWithIgnoreStartWithLowercase() {
let baseDescription = IdentifierNameRule.description
let triggeringExamplesToRemove = [
Example("let ↓MyLet = 0"),
@@ -65,7 +71,8 @@ final class IdentifierNameRuleTests: SwiftLintTestCase {
verifyRule(description, ruleConfiguration: ["validates_start_with_lowercase": "off"])
}
func testStartsWithLowercaseCheck() {
@Test
func startsWithLowercaseCheck() {
let triggeringExamples = [
Example("let ↓MyLet = 0"),
Example("enum Foo { case ↓MyCase }"),
@@ -92,7 +99,8 @@ final class IdentifierNameRuleTests: SwiftLintTestCase {
)
}
func testStartsWithLowercaseCheckInCombinationWithAllowedSymbols() {
@Test
func startsWithLowercaseCheckInCombinationWithAllowedSymbols() {
verifyRule(
IdentifierNameRule.description
.with(triggeringExamples: [
@@ -109,7 +117,8 @@ final class IdentifierNameRuleTests: SwiftLintTestCase {
)
}
func testLinuxCrashOnEmojiNames() {
@Test
func linuxCrashOnEmojiNames() {
let baseDescription = IdentifierNameRule.description
let triggeringExamples = [
Example("let 👦🏼 = \"👦🏼\"")
@@ -119,12 +128,13 @@ final class IdentifierNameRuleTests: SwiftLintTestCase {
verifyRule(description, ruleConfiguration: ["allowed_symbols": ["$", "%"]])
}
func testFunctionNameInViolationMessage() {
@Test
func functionNameInViolationMessage() {
let example = SwiftLintFile(contents: "func _abc(arg: String) {}")
let violations = IdentifierNameRule().validate(file: example)
XCTAssertEqual(
violations.map(\.reason),
["Function name \'_abc(arg:)\' should start with a lowercase character"]
#expect(
violations.map(\.reason)
== ["Function name \'_abc(arg:)\' should start with a lowercase character"]
)
}
}
@@ -1,39 +1,43 @@
@testable import SwiftLintBuiltInRules
import TestHelpers
import XCTest
import Testing
final class ImplicitGetterRuleTests: SwiftLintTestCase {
func testPropertyReason() throws {
let config = try XCTUnwrap(makeConfig(nil, ImplicitGetterRule.identifier))
@testable import SwiftLintBuiltInRules
@Suite(.rulesRegistered)
struct ImplicitGetterRuleTests {
@Test
func propertyReason() throws {
let config = try #require(makeConfig(nil, ImplicitGetterRule.identifier))
let example = Example("""
class Foo {
var foo: Int {
↓get {
return 20
class Foo {
var foo: Int {
↓get {
return 20
}
}
}
}
""")
""")
let violations = violations(example, config: config)
XCTAssertEqual(violations.count, 1)
XCTAssertEqual(violations.first?.reason, "Computed read-only properties should avoid using the get keyword")
#expect(violations.count == 1)
#expect(violations.first?.reason == "Computed read-only properties should avoid using the get keyword")
}
func testSubscriptReason() throws {
let config = try XCTUnwrap(makeConfig(nil, ImplicitGetterRule.identifier))
@Test
func subscriptReason() throws {
let config = try #require(makeConfig(nil, ImplicitGetterRule.identifier))
let example = Example("""
class Foo {
subscript(i: Int) -> Int {
↓get {
return 20
class Foo {
subscript(i: Int) -> Int {
↓get {
return 20
}
}
}
}
""")
""")
let violations = violations(example, config: config)
XCTAssertEqual(violations.count, 1)
XCTAssertEqual(violations.first?.reason, "Computed read-only subscripts should avoid using the get keyword")
#expect(violations.count == 1)
#expect(violations.first?.reason == "Computed read-only subscripts should avoid using the get keyword")
}
}
@@ -1,9 +1,11 @@
@testable import SwiftLintBuiltInRules
import TestHelpers
import XCTest
import Testing
final class ImplicitReturnConfigurationTests: SwiftLintTestCase {
func testImplicitReturnConfigurationFromDictionary() throws {
@Suite(.rulesRegistered)
struct ImplicitReturnConfigurationTests {
@Test
func implicitReturnConfigurationFromDictionary() throws {
var configuration = ImplicitReturnConfiguration(includedKinds: Set<ImplicitReturnConfiguration.ReturnKind>())
let config: [String: Any] = [
"severity": "error",
@@ -24,11 +26,12 @@ final class ImplicitReturnConfigurationTests: SwiftLintTestCase {
.initializer,
.subscript,
])
XCTAssertEqual(configuration.severityConfiguration.severity, .error)
XCTAssertEqual(configuration.includedKinds, expectedKinds)
#expect(configuration.severityConfiguration.severity == .error)
#expect(configuration.includedKinds == expectedKinds)
}
func testImplicitReturnConfigurationThrowsOnUnrecognizedModifierGroup() {
@Test
func implicitReturnConfigurationThrowsOnUnrecognizedModifierGroup() {
var configuration = ImplicitReturnConfiguration()
let config = ["included": ["foreach"]] as [String: any Sendable]
@@ -1,8 +1,12 @@
@testable import SwiftLintBuiltInRules
import TestHelpers
import Testing
final class ImplicitReturnRuleTests: SwiftLintTestCase {
func testOnlyClosureKindIncluded() {
@testable import SwiftLintBuiltInRules
@Suite(.rulesRegistered)
struct ImplicitReturnRuleTests {
@Test
func onlyClosureKindIncluded() {
var nonTriggeringExamples = ImplicitReturnRuleExamples.nonTriggeringExamples +
ImplicitReturnRuleExamples.triggeringExamples
nonTriggeringExamples.removeAll(
@@ -17,7 +21,8 @@ final class ImplicitReturnRuleTests: SwiftLintTestCase {
)
}
func testOnlyFunctionKindIncluded() {
@Test
func onlyFunctionKindIncluded() {
var nonTriggeringExamples = ImplicitReturnRuleExamples.nonTriggeringExamples +
ImplicitReturnRuleExamples.triggeringExamples
nonTriggeringExamples.removeAll(
@@ -32,7 +37,8 @@ final class ImplicitReturnRuleTests: SwiftLintTestCase {
)
}
func testOnlyGetterKindIncluded() {
@Test
func onlyGetterKindIncluded() {
var nonTriggeringExamples = ImplicitReturnRuleExamples.nonTriggeringExamples +
ImplicitReturnRuleExamples.triggeringExamples
nonTriggeringExamples.removeAll(
@@ -47,7 +53,8 @@ final class ImplicitReturnRuleTests: SwiftLintTestCase {
)
}
func testOnlyInitializerKindIncluded() {
@Test
func onlyInitializerKindIncluded() {
var nonTriggeringExamples = ImplicitReturnRuleExamples.nonTriggeringExamples +
ImplicitReturnRuleExamples.triggeringExamples
nonTriggeringExamples.removeAll(
@@ -62,7 +69,8 @@ final class ImplicitReturnRuleTests: SwiftLintTestCase {
)
}
func testOnlySubscriptKindIncluded() {
@Test
func onlySubscriptKindIncluded() {
var nonTriggeringExamples = ImplicitReturnRuleExamples.nonTriggeringExamples +
ImplicitReturnRuleExamples.triggeringExamples
nonTriggeringExamples.removeAll(
@@ -88,6 +96,6 @@ final class ImplicitReturnRuleTests: SwiftLintTestCase {
.with(triggeringExamples: triggeringExamples)
.with(corrections: corrections)
self.verifyRule(description, ruleConfiguration: ["included": [kind.rawValue]])
verifyRule(description, ruleConfiguration: ["included": [kind.rawValue]])
}
}
@@ -1,33 +1,37 @@
@testable import SwiftLintBuiltInRules
import TestHelpers
import XCTest
import Testing
// swiftlint:disable:next type_name
final class ImplicitlyUnwrappedOptionalConfigurationTests: SwiftLintTestCase {
func testImplicitlyUnwrappedOptionalConfigurationProperlyAppliesConfigurationFromDictionary() throws {
@testable import SwiftLintBuiltInRules
@Suite(.rulesRegistered)
struct ImplicitlyUnwrappedOptionalConfigurationTests { // swiftlint:disable:this type_name
@Test
func implicitlyUnwrappedOptionalConfigurationProperlyAppliesConfigurationFromDictionary() throws {
var configuration = ImplicitlyUnwrappedOptionalConfiguration(
severityConfiguration: SeverityConfiguration(.warning),
mode: .allExceptIBOutlets
)
try configuration.apply(configuration: ["mode": "all", "severity": "error"])
XCTAssertEqual(configuration.mode, .all)
XCTAssertEqual(configuration.severity, .error)
#expect(configuration.mode == .all)
#expect(configuration.severity == .error)
try configuration.apply(configuration: ["mode": "all_except_iboutlets"])
XCTAssertEqual(configuration.mode, .allExceptIBOutlets)
XCTAssertEqual(configuration.severity, .error)
#expect(configuration.mode == .allExceptIBOutlets)
#expect(configuration.severity == .error)
try configuration.apply(configuration: ["severity": "warning"])
XCTAssertEqual(configuration.mode, .allExceptIBOutlets)
XCTAssertEqual(configuration.severity, .warning)
#expect(configuration.mode == .allExceptIBOutlets)
#expect(configuration.severity == .warning)
try configuration.apply(configuration: ["mode": "all", "severity": "warning"])
XCTAssertEqual(configuration.mode, .all)
XCTAssertEqual(configuration.severity, .warning)
#expect(configuration.mode == .all)
#expect(configuration.severity == .warning)
}
func testImplicitlyUnwrappedOptionalConfigurationThrowsOnBadConfig() {
@Test
func implicitlyUnwrappedOptionalConfigurationThrowsOnBadConfig() {
let badConfigs: [[String: Any]] = [
["mode": "everything"],
["mode": false],
@@ -40,7 +44,7 @@ final class ImplicitlyUnwrappedOptionalConfigurationTests: SwiftLintTestCase {
mode: .allExceptIBOutlets
)
checkError(Issue.invalidConfiguration(ruleID: ImplicitlyUnwrappedOptionalRule.identifier)) {
#expect(throws: Issue.invalidConfiguration(ruleID: ImplicitlyUnwrappedOptionalRule.identifier)) {
try configuration.apply(configuration: badConfig)
}
}
@@ -1,15 +1,19 @@
@testable import SwiftLintBuiltInRules
import TestHelpers
import XCTest
import Testing
final class ImplicitlyUnwrappedOptionalRuleTests: SwiftLintTestCase {
func testImplicitlyUnwrappedOptionalRuleDefaultConfiguration() {
@testable import SwiftLintBuiltInRules
@Suite(.rulesRegistered)
struct ImplicitlyUnwrappedOptionalRuleTests {
@Test
func implicitlyUnwrappedOptionalRuleDefaultConfiguration() {
let rule = ImplicitlyUnwrappedOptionalRule()
XCTAssertEqual(rule.configuration.mode, .allExceptIBOutlets)
XCTAssertEqual(rule.configuration.severity, .warning)
#expect(rule.configuration.mode == .allExceptIBOutlets)
#expect(rule.configuration.severity == .warning)
}
func testImplicitlyUnwrappedOptionalRuleWarnsOnOutletsInAllMode() {
@Test
func implicitlyUnwrappedOptionalRuleWarnsOnOutletsInAllMode() {
let baseDescription = ImplicitlyUnwrappedOptionalRule.description
let triggeringExamples = [
Example("@IBOutlet private var label: UILabel!"),
@@ -25,7 +29,8 @@ final class ImplicitlyUnwrappedOptionalRuleTests: SwiftLintTestCase {
commentDoesntViolate: true, stringDoesntViolate: true)
}
func testImplicitlyUnwrappedOptionalRuleWarnsOnOutletsInWeakMode() {
@Test
func implicitlyUnwrappedOptionalRuleWarnsOnOutletsInWeakMode() {
let baseDescription = ImplicitlyUnwrappedOptionalRule.description
let triggeringExamples = [
Example("private weak var label: ↓UILabel!"),
@@ -1,8 +1,12 @@
@testable import SwiftLintBuiltInRules
import TestHelpers
import Testing
final class InclusiveLanguageRuleTests: SwiftLintTestCase {
func testNonTriggeringExamplesWithNonDefaultConfig() {
@testable import SwiftLintBuiltInRules
@Suite(.rulesRegistered)
struct InclusiveLanguageRuleTests {
@Test
func nonTriggeringExamplesWithNonDefaultConfig() {
InclusiveLanguageRuleExamples.nonTriggeringExamplesWithConfig.forEach { example in
let description = InclusiveLanguageRule.description
.with(nonTriggeringExamples: [example])
@@ -11,7 +15,8 @@ final class InclusiveLanguageRuleTests: SwiftLintTestCase {
}
}
func testTriggeringExamplesWithNonDefaultConfig() {
@Test
func triggeringExamplesWithNonDefaultConfig() {
InclusiveLanguageRuleExamples.triggeringExamplesWithConfig.forEach { example in
let description = InclusiveLanguageRule.description
.with(nonTriggeringExamples: [])
@@ -1,10 +1,13 @@
import TestHelpers
import Testing
@testable import SwiftLintBuiltInRules
@testable import SwiftLintCore
import TestHelpers
import XCTest
final class IndentationWidthRuleTests: SwiftLintTestCase {
func testInvalidIndentation() async throws {
@Suite(.rulesRegistered)
struct IndentationWidthRuleTests {
@Test
func invalidIndentation() async throws {
let defaultValue = IndentationWidthConfiguration().indentationWidth
for indentation in [0, -1, -5] {
@@ -13,17 +16,17 @@ final class IndentationWidthRuleTests: SwiftLintTestCase {
try testee.apply(configuration: ["indentation_width": indentation])
// Value remains the default.
XCTAssertEqual(testee.indentationWidth, defaultValue)
#expect(testee.indentationWidth == defaultValue)
}
XCTAssertEqual(
console,
"warning: Invalid configuration for 'indentation_width' rule. Falling back to default."
#expect(
console == "warning: Invalid configuration for 'indentation_width' rule. Falling back to default."
)
}
}
/// It's not okay to have the first line indented.
func testFirstLineIndentation() {
@Test
func firstLineIndentation() {
assert1Violation(in: " firstLine")
assert1Violation(in: " firstLine")
assert1Violation(in: " firstLine")
@@ -33,28 +36,32 @@ final class IndentationWidthRuleTests: SwiftLintTestCase {
}
/// It's not okay to indent using both tabs and spaces in one line.
func testMixedTabSpaceIndentation() {
@Test
func mixedTabSpaceIndentation() {
// Expect 2 violations as secondLine is also indented by 8 spaces (which isn't valid)
assertViolations(in: "firstLine\n\t secondLine", equals: 2)
assertViolations(in: "firstLine\n \tsecondLine", equals: 2)
}
/// It's okay to indent using either tabs or spaces in different lines.
func testMixedTabsAndSpacesIndentation() {
@Test
func mixedTabsAndSpacesIndentation() {
assertNoViolation(in: "firstLine\n\tsecondLine\n thirdLine")
assertNoViolation(in: "firstLine\n secondLine\n\t\tthirdLine")
assertNoViolation(in: "firstLine\n\tsecondLine\n thirdLine\n\t\t\tfourthLine")
}
/// It's okay to keep the same indentation.
func testKeepingIndentation() {
@Test
func keepingIndentation() {
assertNoViolation(in: "firstLine\nsecondLine")
assertNoViolation(in: "firstLine \nsecondLine\n thirdLine")
assertNoViolation(in: "firstLine\t\nsecondLine\n\tthirdLine")
}
/// It's only okay to indent using one tab or indentationWidth spaces.
func testIndentationLength() {
@Test
func indentationLength() {
assert1Violation(in: "firstLine\n secondLine", indentationWidth: 1)
assert1Violation(in: "firstLine\n secondLine", indentationWidth: 2)
assert1Violation(in: "firstLine\n secondLine", indentationWidth: 3)
@@ -78,7 +85,8 @@ final class IndentationWidthRuleTests: SwiftLintTestCase {
}
/// It's okay to unindent indentationWidth * (1, 2, 3, ...) - x iff x == 0.
func testUnindentation() {
@Test
func unindentation() {
assert1Violation(in: "firstLine\n secondLine\n thirdLine\n fourthLine")
assert1Violation(in: "firstLine\n secondLine\n thirdLine\n fourthLine")
assert1Violation(in: "firstLine\n secondLine\n thirdLine\n fourthLine")
@@ -90,7 +98,8 @@ final class IndentationWidthRuleTests: SwiftLintTestCase {
}
/// It's okay to have empty lines between iff the following indentations obey the rules.
func testEmptyLinesBetween() {
@Test
func emptyLinesBetween() {
assertNoViolation(in: "firstLine\n\tsecondLine\n\n\tfourthLine")
assertNoViolation(in: "firstLine\n\tsecondLine\n \n\tfourthLine")
assertNoViolation(in: "firstLine\n\tsecondLine\n \n\tfourthLine")
@@ -106,7 +115,8 @@ final class IndentationWidthRuleTests: SwiftLintTestCase {
assert1Violation(in: "firstLine\n\tsecondLine\n \n fourthLine")
}
func testsBrackets() {
@Test
func sBrackets() {
assertNoViolation(
in: "firstLine\n [\n .thirdLine\n ]\nfifthLine",
includeComments: true
@@ -129,7 +139,8 @@ final class IndentationWidthRuleTests: SwiftLintTestCase {
}
/// It's okay to have comments not following the indentation pattern iff the configuration allows this.
func testCommentLines() {
@Test
func commentLines() {
assert1Violation(
in: "firstLine\n\tsecondLine\n\t\tthirdLine\n//test\n\t\tfourthLine",
includeComments: true
@@ -160,7 +171,8 @@ final class IndentationWidthRuleTests: SwiftLintTestCase {
}
/// Duplicate warnings for one actual indentation issue should be avoided.
func testDuplicateWarningAvoidanceMechanism() {
@Test
func duplicateWarningAvoidanceMechanism() {
// thirdLine is indented correctly, yet not in-line with the badly indented secondLine. This should be allowed.
assert1Violation(in: "firstLine\n secondLine\nthirdLine")
@@ -181,7 +193,8 @@ final class IndentationWidthRuleTests: SwiftLintTestCase {
assertViolations(in: "firstLine\n secondLine\n thirdLine\n fourthLine\n fifthLine", equals: 2)
}
func testIgnoredCompilerDirectives() {
@Test
func ignoredCompilerDirectives() {
assertNoViolation(in: """
struct S {
#if os(iOS)
@@ -215,7 +228,8 @@ final class IndentationWidthRuleTests: SwiftLintTestCase {
""", includeCompilerDirectives: true)
}
func testIncludeMultilineStrings() {
@Test
func includeMultilineStrings() {
let example0 = #"""
let x = """
string1
@@ -274,9 +288,7 @@ final class IndentationWidthRuleTests: SwiftLintTestCase {
indentationWidth: Int? = nil,
includeComments: Bool = true,
includeCompilerDirectives: Bool = true,
includeMultilineStrings: Bool = true,
file: StaticString = #filePath,
line: UInt = #line
includeMultilineStrings: Bool = true
) -> Int {
var configDict: [String: Any] = [:]
if let indentationWidth {
@@ -287,7 +299,7 @@ final class IndentationWidthRuleTests: SwiftLintTestCase {
configDict["include_multiline_strings"] = includeMultilineStrings
guard let config = makeConfig(configDict, IndentationWidthRule.identifier) else {
XCTFail("Unable to create rule configuration.", file: (file), line: line)
Testing.Issue.record("Unable to create rule configuration.")
return 0
}
@@ -304,19 +316,20 @@ final class IndentationWidthRuleTests: SwiftLintTestCase {
file: StaticString = #filePath,
line: UInt = #line
) {
XCTAssertEqual(
#expect(
countViolations(
in: Example(string, file: (file), line: line),
indentationWidth: indentationWidth,
includeComments: includeComments,
includeCompilerDirectives: includeCompilerDirectives,
includeMultilineStrings: includeMultilineStrings,
file: file,
line: line
),
expectedCount,
file: (file),
line: line
includeMultilineStrings: includeMultilineStrings
) == expectedCount,
sourceLocation: SourceLocation(
fileID: #fileID,
filePath: String(describing: file),
line: Int(line),
column: 1
)
)
}
@@ -1,83 +1,95 @@
@testable import SwiftLintBuiltInRules
import TestHelpers
import XCTest
import Testing
final class LineLengthConfigurationTests: SwiftLintTestCase {
@testable import SwiftLintBuiltInRules
@Suite(.rulesRegistered)
struct LineLengthConfigurationTests {
private let severityLevels = SeverityLevelsConfiguration<LineLengthRule>(warning: 100, error: 150)
func testLineLengthConfigurationInitializerSetsLength() {
@Test
func lineLengthConfigurationInitializerSetsLength() {
let configuration1 = LineLengthConfiguration(length: severityLevels)
XCTAssertEqual(configuration1.length, severityLevels)
#expect(configuration1.length == severityLevels)
let length2 = SeverityLevelsConfiguration<LineLengthRule>(warning: 100, error: nil)
let configuration2 = LineLengthConfiguration(length: length2)
XCTAssertEqual(configuration2.length, length2)
#expect(configuration2.length == length2)
}
func testLineLengthConfigurationInitialiserSetsIgnoresURLs() {
@Test
func lineLengthConfigurationInitialiserSetsIgnoresURLs() {
let configuration1 = LineLengthConfiguration(length: severityLevels, ignoresURLs: true)
XCTAssertTrue(configuration1.ignoresURLs)
#expect(configuration1.ignoresURLs)
let configuration2 = LineLengthConfiguration(length: severityLevels)
XCTAssertFalse(configuration2.ignoresURLs)
#expect(!configuration2.ignoresURLs)
}
func testLineLengthConfigurationInitialiserSetsIgnoresFunctionDeclarations() {
@Test
func lineLengthConfigurationInitialiserSetsIgnoresFunctionDeclarations() {
let configuration1 = LineLengthConfiguration(length: severityLevels, ignoresFunctionDeclarations: true)
XCTAssertTrue(configuration1.ignoresFunctionDeclarations)
#expect(configuration1.ignoresFunctionDeclarations)
let configuration2 = LineLengthConfiguration(length: severityLevels)
XCTAssertFalse(configuration2.ignoresFunctionDeclarations)
#expect(!configuration2.ignoresFunctionDeclarations)
}
func testLineLengthConfigurationInitialiserSetsIgnoresComments() {
@Test
func lineLengthConfigurationInitialiserSetsIgnoresComments() {
let configuration1 = LineLengthConfiguration(length: severityLevels, ignoresComments: true)
XCTAssertTrue(configuration1.ignoresComments)
#expect(configuration1.ignoresComments)
let configuration2 = LineLengthConfiguration(length: severityLevels)
XCTAssertFalse(configuration2.ignoresComments)
#expect(!configuration2.ignoresComments)
}
func testLineLengthConfigurationInitialiserSetsIgnoresInterpolatedStrings() {
@Test
func lineLengthConfigurationInitialiserSetsIgnoresInterpolatedStrings() {
let configuration1 = LineLengthConfiguration(length: severityLevels, ignoresInterpolatedStrings: true)
XCTAssertTrue(configuration1.ignoresInterpolatedStrings)
#expect(configuration1.ignoresInterpolatedStrings)
let configuration2 = LineLengthConfiguration(length: severityLevels)
XCTAssertFalse(configuration2.ignoresInterpolatedStrings)
#expect(!configuration2.ignoresInterpolatedStrings)
}
func testLineLengthConfigurationInitialiserSetsIgnoresMultilineStrings() {
@Test
func lineLengthConfigurationInitialiserSetsIgnoresMultilineStrings() {
let configuration1 = LineLengthConfiguration(length: severityLevels, ignoresMultilineStrings: true)
XCTAssertTrue(configuration1.ignoresMultilineStrings)
#expect(configuration1.ignoresMultilineStrings)
let configuration2 = LineLengthConfiguration(length: severityLevels)
XCTAssertFalse(configuration2.ignoresMultilineStrings)
#expect(!configuration2.ignoresMultilineStrings)
}
func testLineLengthConfigurationInitialiserSetsExcludedLinesPatterns() {
@Test
func lineLengthConfigurationInitialiserSetsExcludedLinesPatterns() {
let patterns: Set = ["foo", "bar"]
let configuration1 = LineLengthConfiguration(length: severityLevels, excludedLinesPatterns: patterns)
XCTAssertEqual(configuration1.excludedLinesPatterns, patterns)
#expect(configuration1.excludedLinesPatterns == patterns)
let configuration2 = LineLengthConfiguration(length: severityLevels)
XCTAssertTrue(configuration2.excludedLinesPatterns.isEmpty)
#expect(configuration2.excludedLinesPatterns.isEmpty)
}
func testLineLengthConfigurationParams() {
@Test
func lineLengthConfigurationParams() {
let warning = 13
let error = 10
let configuration = LineLengthConfiguration(length: SeverityLevelsConfiguration(warning: warning, error: error))
let params = [RuleParameter(severity: .error, value: error), RuleParameter(severity: .warning, value: warning)]
XCTAssertEqual(configuration.params, params)
#expect(configuration.params == params)
}
func testLineLengthConfigurationPartialParams() {
@Test
func lineLengthConfigurationPartialParams() {
let configuration = LineLengthConfiguration(length: SeverityLevelsConfiguration(warning: 13))
XCTAssertEqual(configuration.params, [RuleParameter(severity: .warning, value: 13)])
#expect(configuration.params == [RuleParameter(severity: .warning, value: 13)])
}
func testLineLengthConfigurationThrowsOnBadConfig() {
@Test
func lineLengthConfigurationThrowsOnBadConfig() {
let config = ["warning": "unknown"]
var configuration = LineLengthConfiguration(length: severityLevels)
checkError(Issue.invalidConfiguration(ruleID: LineLengthRule.identifier)) {
@@ -85,7 +97,8 @@ final class LineLengthConfigurationTests: SwiftLintTestCase {
}
}
func testLineLengthConfigurationThrowsOnBadConfigValues() {
@Test
func lineLengthConfigurationThrowsOnBadConfigValues() {
let badConfigs: [[String: Any]] = [
["warning": true],
["ignores_function_declarations": 300],
@@ -99,7 +112,8 @@ final class LineLengthConfigurationTests: SwiftLintTestCase {
}
}
func testLineLengthConfigurationApplyConfigurationWithArray() throws {
@Test
func lineLengthConfigurationApplyConfigurationWithArray() throws {
var configuration = LineLengthConfiguration(length: SeverityLevelsConfiguration(warning: 0, error: 0))
let warning1 = 100
@@ -112,13 +126,14 @@ final class LineLengthConfigurationTests: SwiftLintTestCase {
let config2 = [warning2]
try configuration.apply(configuration: config1)
XCTAssertEqual(configuration.length, length1)
#expect(configuration.length == length1)
try configuration.apply(configuration: config2)
XCTAssertEqual(configuration.length, length2)
#expect(configuration.length == length2)
}
func testLineLengthConfigurationApplyConfigurationWithDictionary() throws {
@Test
func lineLengthConfigurationApplyConfigurationWithDictionary() throws {
var configuration = LineLengthConfiguration(length: SeverityLevelsConfiguration(warning: 0, error: 0))
let warning1 = 100
@@ -144,47 +159,48 @@ final class LineLengthConfigurationTests: SwiftLintTestCase {
]
try configuration.apply(configuration: config1)
XCTAssertEqual(configuration.length, length1)
XCTAssertTrue(configuration.ignoresURLs)
XCTAssertTrue(configuration.ignoresFunctionDeclarations)
XCTAssertTrue(configuration.ignoresComments)
#expect(configuration.length == length1)
#expect(configuration.ignoresURLs)
#expect(configuration.ignoresFunctionDeclarations)
#expect(configuration.ignoresComments)
try configuration.apply(configuration: config2)
XCTAssertEqual(configuration.length, length2)
XCTAssertTrue(configuration.ignoresURLs)
XCTAssertTrue(configuration.ignoresFunctionDeclarations)
XCTAssertTrue(configuration.ignoresComments)
#expect(configuration.length == length2)
#expect(configuration.ignoresURLs)
#expect(configuration.ignoresFunctionDeclarations)
#expect(configuration.ignoresComments)
try configuration.apply(configuration: config3)
XCTAssertEqual(configuration.length, length2)
XCTAssertFalse(configuration.ignoresURLs)
XCTAssertFalse(configuration.ignoresFunctionDeclarations)
XCTAssertFalse(configuration.ignoresComments)
#expect(configuration.length == length2)
#expect(!configuration.ignoresURLs)
#expect(!configuration.ignoresFunctionDeclarations)
#expect(!configuration.ignoresComments)
}
func testLineLengthConfigurationCompares() {
@Test
func lineLengthConfigurationCompares() {
let configuration1 = LineLengthConfiguration(length: SeverityLevelsConfiguration(warning: 100, error: 100))
let configuration2 = LineLengthConfiguration(
length: SeverityLevelsConfiguration(warning: 100, error: 100),
ignoresFunctionDeclarations: true,
ignoresComments: true
)
XCTAssertNotEqual(configuration1, configuration2)
#expect(configuration1 != configuration2)
let configuration3 = LineLengthConfiguration(length: SeverityLevelsConfiguration(warning: 100, error: 200))
XCTAssertNotEqual(configuration1, configuration3)
#expect(configuration1 != configuration3)
let configuration4 = LineLengthConfiguration(length: SeverityLevelsConfiguration(warning: 200, error: 200))
XCTAssertNotEqual(configuration1, configuration4)
#expect(configuration1 != configuration4)
let configuration5 = LineLengthConfiguration(length: SeverityLevelsConfiguration(warning: 100, error: 100))
XCTAssertEqual(configuration1, configuration5)
#expect(configuration1 == configuration5)
let configuration6 = LineLengthConfiguration(
length: SeverityLevelsConfiguration(warning: 100, error: 100),
ignoresFunctionDeclarations: true,
ignoresComments: true
)
XCTAssertEqual(configuration2, configuration6)
#expect(configuration2 == configuration6)
}
}
@@ -1,7 +1,10 @@
@testable import SwiftLintBuiltInRules
import TestHelpers
import Testing
final class LineLengthRuleTests: SwiftLintTestCase {
@testable import SwiftLintBuiltInRules
@Suite(.rulesRegistered)
struct LineLengthRuleTests {
private static let longString = String(repeating: "a", count: 121)
private let longFunctionDeclarations = [
@@ -50,53 +53,55 @@ final class LineLengthRuleTests: SwiftLintTestCase {
private let longBlockComment = Example("/*" + String(repeating: " ", count: 121) + "*/\n")
private let longRealBlockComment = Example("""
/*
\(LineLengthRuleTests.longString)
\(Self.longString)
*/
""")
private let declarationWithTrailingLongComment = Example("let foo = 1 " + String(repeating: "/", count: 121) + "\n")
private let interpolatedString = Example("print(\"\\(value)" + String(repeating: "A", count: 113) + "\" )\n")
private let plainString = Example("print(\"" + LineLengthRuleTests.longString + ")\"\n")
private let plainString = Example("print(\"" + Self.longString + ")\"\n")
private let multilineString = Example("""
let multilineString = \"\"\"
\(LineLengthRuleTests.longString)
\(Self.longString)
\"\"\"
""")
private let tripleStringSingleLine = Example(
"let tripleString = \"\"\"\(LineLengthRuleTests.longString)\"\"\"\n"
"let tripleString = \"\"\"\(Self.longString)\"\"\"\n"
)
private let poundStringSingleLine = Example("let poundString = #\"\(LineLengthRuleTests.longString)\"#\n")
private let poundStringSingleLine = Example("let poundString = #\"\(Self.longString)\"#\n")
private let multilineStringWithExpression = Example("""
let multilineString = \"\"\"
\(LineLengthRuleTests.longString)
\(Self.longString)
\"\"\"; let a = 1
""")
private let multilineStringWithNewlineExpression = Example("""
let multilineString = \"\"\"
\(LineLengthRuleTests.longString)
\(Self.longString)
\"\"\"
; let a = 1
""")
private let multilineStringFail = Example("""
let multilineString = "A" +
"\(LineLengthRuleTests.longString)"
"\(Self.longString)"
""")
private let multilineStringWithFunction = Example("""
let multilineString = \"\"\"
\(LineLengthRuleTests.longString)
\(Self.longString)
\"\"\".functionCall()
""")
func testLineLength() {
@Test
func lineLength() {
verifyRule(LineLengthRule.description, commentDoesntViolate: false, stringDoesntViolate: false)
}
func testLineLengthWithIgnoreFunctionDeclarationsEnabled() {
@Test
func lineLengthWithIgnoreFunctionDeclarationsEnabled() {
let baseDescription = LineLengthRule.description
let nonTriggeringExamples = baseDescription.nonTriggeringExamples + longFunctionDeclarations
let description = baseDescription.with(nonTriggeringExamples: nonTriggeringExamples)
@@ -109,7 +114,8 @@ final class LineLengthRuleTests: SwiftLintTestCase {
)
}
func testLineLengthWithIgnoreCommentsEnabled() {
@Test
func lineLengthWithIgnoreCommentsEnabled() {
let baseDescription = LineLengthRule.description
let triggeringExamples = longFunctionDeclarations + [declarationWithTrailingLongComment]
let nonTriggeringExamples = [longComment, longBlockComment, longRealBlockComment]
@@ -121,7 +127,8 @@ final class LineLengthRuleTests: SwiftLintTestCase {
commentDoesntViolate: false, stringDoesntViolate: false, skipCommentTests: true)
}
func testLineLengthWithIgnoreURLsEnabled() {
@Test
func lineLengthWithIgnoreURLsEnabled() {
let url = "https://github.com/realm/SwiftLint"
let triggeringLines = [Example(String(repeating: "/", count: 121) + "\(url)\n")]
let nonTriggeringLines = [
@@ -140,7 +147,8 @@ final class LineLengthRuleTests: SwiftLintTestCase {
commentDoesntViolate: false, stringDoesntViolate: false)
}
func testLineLengthWithIgnoreInterpolatedStringsTrue() {
@Test
func lineLengthWithIgnoreInterpolatedStringsTrue() {
let triggeringLines = [plainString]
let nonTriggeringLines = [interpolatedString]
@@ -155,7 +163,8 @@ final class LineLengthRuleTests: SwiftLintTestCase {
commentDoesntViolate: false, stringDoesntViolate: false)
}
func testLineLengthWithIgnoreMultilineStringsTrue() {
@Test
func lineLengthWithIgnoreMultilineStringsTrue() {
let triggeringLines = [
multilineStringFail,
tripleStringSingleLine,
@@ -179,7 +188,8 @@ final class LineLengthRuleTests: SwiftLintTestCase {
commentDoesntViolate: false, stringDoesntViolate: false)
}
func testLineLengthWithIgnoreInterpolatedStringsFalse() {
@Test
func lineLengthWithIgnoreInterpolatedStringsFalse() {
let triggeringLines = [plainString, interpolatedString]
let baseDescription = LineLengthRule.description
@@ -193,7 +203,8 @@ final class LineLengthRuleTests: SwiftLintTestCase {
commentDoesntViolate: false, stringDoesntViolate: false)
}
func testLineLengthWithExcludedLinesPatterns() {
@Test
func lineLengthWithExcludedLinesPatterns() {
let nonTriggeringLines = [plainString, interpolatedString]
let baseDescription = LineLengthRule.description
@@ -212,7 +223,8 @@ final class LineLengthRuleTests: SwiftLintTestCase {
)
}
func testLineLengthWithEmptyExcludedLinesPatterns() {
@Test
func lineLengthWithEmptyExcludedLinesPatterns() {
let triggeringLines = [plainString, interpolatedString]
let baseDescription = LineLengthRule.description
+123 -100
View File
@@ -1,207 +1,230 @@
@testable import SwiftLintBuiltInRules
import TestHelpers
import XCTest
import Testing
final class MissingDocsRuleTests: SwiftLintTestCase {
func testDescriptionEmpty() {
@testable import SwiftLintBuiltInRules
@Suite(.rulesRegistered)
struct MissingDocsRuleTests {
@Test
func descriptionEmpty() {
let configuration = MissingDocsConfiguration()
XCTAssertEqual(
configuration.parameterDescription?.oneLiner(),
"warning: [open, public]; excludes_extensions: true; " +
"excludes_inherited_types: true; excludes_trivial_init: false; " +
"evaluate_effective_access_control_level: false"
#expect(
configuration.parameterDescription?.oneLiner() == """
warning: [open, public]; excludes_extensions: true; \
excludes_inherited_types: true; excludes_trivial_init: false; \
evaluate_effective_access_control_level: false
"""
)
}
func testDescriptionExcludesFalse() {
@Test
func descriptionExcludesFalse() {
let configuration = MissingDocsConfiguration(excludesExtensions: false, excludesInheritedTypes: false)
XCTAssertEqual(
configuration.parameterDescription?.oneLiner(),
"warning: [open, public]; excludes_extensions: false; " +
"excludes_inherited_types: false; excludes_trivial_init: false; " +
"evaluate_effective_access_control_level: false"
#expect(
configuration.parameterDescription?.oneLiner() == """
warning: [open, public]; excludes_extensions: false; \
excludes_inherited_types: false; excludes_trivial_init: false; \
evaluate_effective_access_control_level: false
"""
)
}
func testDescriptionExcludesExtensionsFalseExcludesInheritedTypesTrue() {
@Test
func descriptionExcludesExtensionsFalseExcludesInheritedTypesTrue() {
let configuration = MissingDocsConfiguration(excludesExtensions: false, excludesInheritedTypes: true)
XCTAssertEqual(
configuration.parameterDescription?.oneLiner(),
"warning: [open, public]; excludes_extensions: false; " +
"excludes_inherited_types: true; excludes_trivial_init: false; " +
"evaluate_effective_access_control_level: false"
#expect(
configuration.parameterDescription?.oneLiner() == """
warning: [open, public]; excludes_extensions: false; \
excludes_inherited_types: true; excludes_trivial_init: false; \
evaluate_effective_access_control_level: false
"""
)
}
func testDescriptionExcludesExtensionsTrueExcludesInheritedTypesFalse() {
@Test
func descriptionExcludesExtensionsTrueExcludesInheritedTypesFalse() {
let configuration = MissingDocsConfiguration(
excludesExtensions: true,
excludesInheritedTypes: false,
evaluateEffectiveAccessControlLevel: true
)
XCTAssertEqual(
configuration.parameterDescription?.oneLiner(),
"warning: [open, public]; excludes_extensions: true; " +
"excludes_inherited_types: false; excludes_trivial_init: false; " +
"evaluate_effective_access_control_level: true"
#expect(
configuration.parameterDescription?.oneLiner() == """
warning: [open, public]; excludes_extensions: true; \
excludes_inherited_types: false; excludes_trivial_init: false; \
evaluate_effective_access_control_level: true
"""
)
}
func testDescriptionSingleServety() {
@Test
func descriptionSingleServety() {
let configuration = MissingDocsConfiguration(
parameters: [RuleParameter<AccessControlLevel>(severity: .error, value: .open)])
XCTAssertEqual(
configuration.parameterDescription?.oneLiner(),
"error: [open]; excludes_extensions: true; " +
"excludes_inherited_types: true; excludes_trivial_init: false; " +
"evaluate_effective_access_control_level: false"
#expect(
configuration.parameterDescription?.oneLiner() == """
error: [open]; excludes_extensions: true; \
excludes_inherited_types: true; excludes_trivial_init: false; \
evaluate_effective_access_control_level: false
"""
)
}
func testDescriptionMultipleSeverities() {
@Test
func descriptionMultipleSeverities() {
let configuration = MissingDocsConfiguration(
parameters: [
RuleParameter<AccessControlLevel>(severity: .error, value: .open),
RuleParameter<AccessControlLevel>(severity: .warning, value: .public),
]
)
XCTAssertEqual(
configuration.parameterDescription?.oneLiner(),
"error: [open]; warning: [public]; excludes_extensions: true; " +
"excludes_inherited_types: true; excludes_trivial_init: false; " +
"evaluate_effective_access_control_level: false"
#expect(
configuration.parameterDescription?.oneLiner() == """
error: [open]; warning: [public]; excludes_extensions: true; \
excludes_inherited_types: true; excludes_trivial_init: false; \
evaluate_effective_access_control_level: false
"""
)
}
func testDescriptionMultipleAcls() {
@Test
func descriptionMultipleAcls() {
let configuration = MissingDocsConfiguration(
parameters: [
RuleParameter<AccessControlLevel>(severity: .warning, value: .open),
RuleParameter<AccessControlLevel>(severity: .warning, value: .public),
]
)
XCTAssertEqual(
configuration.parameterDescription?.oneLiner(),
"warning: [open, public]; excludes_extensions: true; " +
"excludes_inherited_types: true; excludes_trivial_init: false; " +
"evaluate_effective_access_control_level: false"
#expect(
configuration.parameterDescription?.oneLiner() == """
warning: [open, public]; excludes_extensions: true; \
excludes_inherited_types: true; excludes_trivial_init: false; \
evaluate_effective_access_control_level: false
"""
)
}
func testDescriptionExcludesTrivialInitTrue() {
@Test
func descriptionExcludesTrivialInitTrue() {
let configuration = MissingDocsConfiguration(excludesTrivialInit: true)
XCTAssertEqual(
configuration.parameterDescription?.oneLiner(),
"warning: [open, public]; excludes_extensions: true; " +
"excludes_inherited_types: true; excludes_trivial_init: true; " +
"evaluate_effective_access_control_level: false"
#expect(
configuration.parameterDescription?.oneLiner() == """
warning: [open, public]; excludes_extensions: true; \
excludes_inherited_types: true; excludes_trivial_init: true; \
evaluate_effective_access_control_level: false
"""
)
}
func testParsingSingleServety() {
@Test
func parsingSingleServety() {
var configuration = MissingDocsConfiguration()
try? configuration.apply(configuration: ["warning": "open"])
XCTAssertEqual(
configuration.parameters,
[RuleParameter<AccessControlLevel>(severity: .warning, value: .open)]
#expect(
configuration.parameters == [RuleParameter<AccessControlLevel>(severity: .warning, value: .open)]
)
}
func testParsingMultipleSeverities() {
@Test
func parsingMultipleSeverities() {
var configuration = MissingDocsConfiguration()
try? configuration.apply(configuration: ["warning": "public", "error": "open"])
XCTAssertEqual(
configuration.parameters.sorted { $0.value.rawValue > $1.value.rawValue },
[
#expect(
configuration.parameters.sorted { $0.value.rawValue > $1.value.rawValue } == [
RuleParameter<AccessControlLevel>(severity: .warning, value: .public),
RuleParameter<AccessControlLevel>(severity: .error, value: .open),
]
)
}
func testParsingMultipleAcls() {
@Test
func parsingMultipleAcls() {
var configuration = MissingDocsConfiguration()
try? configuration.apply(configuration: ["warning": ["public", "open"]])
XCTAssertEqual(
configuration.parameters.sorted { $0.value.rawValue > $1.value.rawValue },
[
#expect(
configuration.parameters.sorted { $0.value.rawValue > $1.value.rawValue } == [
RuleParameter<AccessControlLevel>(severity: .warning, value: .public),
RuleParameter<AccessControlLevel>(severity: .warning, value: .open),
]
)
XCTAssertTrue(configuration.excludesExtensions)
XCTAssertTrue(configuration.excludesInheritedTypes)
#expect(configuration.excludesExtensions)
#expect(configuration.excludesInheritedTypes)
}
func testInvalidServety() {
@Test
func invalidServety() {
var configuration = MissingDocsConfiguration()
XCTAssertThrowsError(try configuration.apply(configuration: ["warning": ["public", "closed"]]))
#expect(throws: (any Error).self) {
try configuration.apply(configuration: ["warning": ["public", "closed"]])
}
}
func testInvalidAcl() {
@Test
func invalidAcl() {
var configuration = MissingDocsConfiguration()
try? configuration.apply(configuration: ["debug": ["public", "open"]])
XCTAssertTrue(configuration.excludesExtensions)
XCTAssertTrue(configuration.excludesInheritedTypes)
XCTAssertEqual(
configuration.parameters.sorted { $0.value.rawValue > $1.value.rawValue },
[
#expect(configuration.excludesExtensions)
#expect(configuration.excludesInheritedTypes)
#expect(
configuration.parameters.sorted { $0.value.rawValue > $1.value.rawValue } == [
RuleParameter<AccessControlLevel>(severity: .warning, value: .public),
RuleParameter<AccessControlLevel>(severity: .warning, value: .open),
]
)
}
func testInvalidDuplicateAcl() {
@Test
func invalidDuplicateAcl() {
var configuration = MissingDocsConfiguration()
XCTAssertThrowsError(
#expect(throws: (any Error).self) {
try configuration.apply(configuration: ["warning": ["public", "open"] as Any, "error": "public"])
)
}
}
func testExcludesFalse() {
@Test
func excludesFalse() {
var configuration = MissingDocsConfiguration()
try? configuration.apply(configuration: ["excludes_extensions": false, "excludes_inherited_types": false])
XCTAssertFalse(configuration.excludesExtensions)
XCTAssertFalse(configuration.excludesInheritedTypes)
XCTAssertEqual(
configuration.parameters.sorted { $0.value.rawValue > $1.value.rawValue },
[
#expect(!configuration.excludesExtensions)
#expect(!configuration.excludesInheritedTypes)
#expect(
configuration.parameters.sorted { $0.value.rawValue > $1.value.rawValue } == [
RuleParameter<AccessControlLevel>(severity: .warning, value: .public),
RuleParameter<AccessControlLevel>(severity: .warning, value: .open),
]
)
}
func testExcludesExtensionsFalseExcludesInheritedTypesTrue() {
@Test
func excludesExtensionsFalseExcludesInheritedTypesTrue() {
var configuration = MissingDocsConfiguration()
try? configuration.apply(configuration: ["excludes_extensions": false, "excludes_inherited_types": true])
XCTAssertFalse(configuration.excludesExtensions)
XCTAssertTrue(configuration.excludesInheritedTypes)
XCTAssertEqual(
configuration.parameters.sorted { $0.value.rawValue > $1.value.rawValue },
[
#expect(!configuration.excludesExtensions)
#expect(configuration.excludesInheritedTypes)
#expect(
configuration.parameters.sorted { $0.value.rawValue > $1.value.rawValue } == [
RuleParameter<AccessControlLevel>(severity: .warning, value: .public),
RuleParameter<AccessControlLevel>(severity: .warning, value: .open),
]
)
}
func testExcludesExtensionsTrueExcludesInheritedTypesFalse() {
@Test
func excludesExtensionsTrueExcludesInheritedTypesFalse() {
var configuration = MissingDocsConfiguration()
try? configuration.apply(configuration: ["excludes_extensions": true, "excludes_inherited_types": false])
XCTAssertTrue(configuration.excludesExtensions)
XCTAssertFalse(configuration.excludesInheritedTypes)
XCTAssertEqual(
configuration.parameters.sorted { $0.value.rawValue > $1.value.rawValue },
[
#expect(configuration.excludesExtensions)
#expect(!configuration.excludesInheritedTypes)
#expect(
configuration.parameters.sorted { $0.value.rawValue > $1.value.rawValue } == [
RuleParameter<AccessControlLevel>(severity: .warning, value: .public),
RuleParameter<AccessControlLevel>(severity: .warning, value: .open),
]
)
}
func testExcludesExtensionsTrueExcludesInheritedTypesFalseWithParameters() {
@Test
func excludesExtensionsTrueExcludesInheritedTypesFalseWithParameters() {
var configuration = MissingDocsConfiguration()
try? configuration.apply(
configuration: [
@@ -211,11 +234,11 @@ final class MissingDocsRuleTests: SwiftLintTestCase {
] as [String: any Sendable]
)
XCTAssertTrue(configuration.excludesExtensions)
XCTAssertFalse(configuration.excludesInheritedTypes)
XCTAssertEqual(
configuration.parameters.sorted { $0.value.rawValue > $1.value.rawValue },
[RuleParameter<AccessControlLevel>(severity: .error, value: .public)]
#expect(configuration.excludesExtensions)
#expect(!configuration.excludesInheritedTypes)
#expect(
configuration.parameters.sorted { $0.value.rawValue > $1.value.rawValue }
== [RuleParameter<AccessControlLevel>(severity: .error, value: .public)]
)
}
}
@@ -1,9 +1,14 @@
@testable import SwiftLintBuiltInRules
import TestHelpers
import XCTest
import Testing
final class ModifierOrderTests: SwiftLintTestCase {
func testAttributeTypeMethod() {
@testable import SwiftLintBuiltInRules
// swiftlint:disable file_length
@Suite(.rulesRegistered)
struct ModifierOrderTests {
@Test
func attributeTypeMethod() {
let descriptionOverride = ModifierOrderRule.description
.with(nonTriggeringExamples: [
Example("""
@@ -35,7 +40,8 @@ final class ModifierOrderTests: SwiftLintTestCase {
ruleConfiguration: ["preferred_modifier_order": ["typeMethods", "acl"]])
}
func testRightOrderedModifierGroups() {
@Test
func rightOrderedModifierGroups() {
let descriptionOverride = ModifierOrderRule.description
.with(nonTriggeringExamples: [
Example("public protocol Foo: class {}\n" +
@@ -73,8 +79,8 @@ final class ModifierOrderTests: SwiftLintTestCase {
)
}
// swiftlint:disable:next function_body_length
func testAtPrefixedGroup() {
@Test
func atPrefixedGroup() { // swiftlint:disable:this function_body_length
let descriptionOverride = ModifierOrderRule.description
.with(nonTriggeringExamples: [
Example(#"""
@@ -171,7 +177,8 @@ final class ModifierOrderTests: SwiftLintTestCase {
ruleConfiguration: ["preferred_modifier_order": ["override", "acl", "owned", "final"]])
}
func testNonSpecifiedModifiersDontInterfere() {
@Test
func nonSpecifiedModifiersDontInterfere() {
let descriptionOverride = ModifierOrderRule.description
.with(nonTriggeringExamples: [
Example("""
@@ -223,8 +230,8 @@ final class ModifierOrderTests: SwiftLintTestCase {
ruleConfiguration: ["preferred_modifier_order": ["final", "override", "acl"]])
}
// swiftlint:disable:next function_body_length
func testCorrectionsAreAppliedCorrectly() {
@Test
func correctionsAreAppliedCorrectly() { // swiftlint:disable:this function_body_length
let descriptionOverride = ModifierOrderRule.description
.with(nonTriggeringExamples: [], triggeringExamples: [])
.with(corrections: [
@@ -290,8 +297,8 @@ final class ModifierOrderTests: SwiftLintTestCase {
ruleConfiguration: ["preferred_modifier_order": ["final", "override", "acl", "typeMethods"]])
}
// swiftlint:disable:next function_body_length
func testCorrectionsAreNotAppliedToIrrelevantModifier() {
@Test
func correctionsAreNotAppliedToIrrelevantModifier() { // swiftlint:disable:this function_body_length
let descriptionOverride = ModifierOrderRule.description
.with(nonTriggeringExamples: [], triggeringExamples: [])
.with(corrections: [
@@ -361,7 +368,8 @@ final class ModifierOrderTests: SwiftLintTestCase {
ruleConfiguration: ["preferred_modifier_order": ["final", "override", "acl", "typeMethods"]])
}
func testTypeMethodClassCorrection() {
@Test
func typeMethodClassCorrection() {
let descriptionOverride = ModifierOrderRule.description
.with(nonTriggeringExamples: [], triggeringExamples: [])
.with(corrections: [
@@ -383,18 +391,19 @@ final class ModifierOrderTests: SwiftLintTestCase {
ruleConfiguration: ["preferred_modifier_order": ["final", "typeMethods", "acl"]])
}
func testViolationMessage() {
@Test
func violationMessage() {
let ruleID = ModifierOrderRule.identifier
guard let config = makeConfig(["preferred_modifier_order": ["acl", "final"]], ruleID) else {
XCTFail("Failed to create configuration")
Testing.Issue.record("Failed to create configuration")
return
}
let allViolations = violations(Example("final public var foo: String"), config: config)
let modifierOrderRuleViolation = allViolations.first { $0.ruleIdentifier == ruleID }
if let violation = modifierOrderRuleViolation {
XCTAssertEqual(violation.reason, "public modifier should come before final")
#expect(violation.reason == "public modifier should come before final")
} else {
XCTFail("A modifier order violation should have been triggered!")
Testing.Issue.record("A modifier order violation should have been triggered!")
}
}
}
@@ -1,8 +1,12 @@
@testable import SwiftLintBuiltInRules
import TestHelpers
import Testing
final class MultilineArgumentsRuleTests: SwiftLintTestCase {
func testMultilineArgumentsWithWithNextLine() {
@testable import SwiftLintBuiltInRules
@Suite(.rulesRegistered)
struct MultilineArgumentsRuleTests {
@Test
func multilineArgumentsWithWithNextLine() {
let nonTriggeringExamples = [
Example("foo()"),
Example("foo(0)"),
@@ -27,7 +31,8 @@ final class MultilineArgumentsRuleTests: SwiftLintTestCase {
verifyRule(description, ruleConfiguration: ["first_argument_location": "next_line"])
}
func testMultilineArgumentsWithWithSameLine() {
@Test
func multilineArgumentsWithWithSameLine() {
let nonTriggeringExamples = [
Example("foo()"),
Example("foo(0)"),
@@ -54,7 +59,8 @@ final class MultilineArgumentsRuleTests: SwiftLintTestCase {
verifyRule(description, ruleConfiguration: ["first_argument_location": "same_line"])
}
func testMultilineArgumentsWithOnlyEnforceAfterFirstClosureOnFirstLine() {
@Test
func multilineArgumentsWithOnlyEnforceAfterFirstClosureOnFirstLine() {
let nonTriggeringExamples: [Example] = [
Example("foo()"),
Example("foo(0)"),
@@ -1,10 +1,13 @@
import TestHelpers
import Testing
@testable import SwiftLintBuiltInRules
@testable import SwiftLintCore
import TestHelpers
import XCTest
final class MultilineParametersConfigurationTests: SwiftLintTestCase {
func testInvalidMaxNumberOfSingleLineParameters() async throws {
@Suite(.rulesRegistered)
struct MultilineParametersConfigurationTests {
@Test
func invalidMaxNumberOfSingleLineParameters() async throws {
for maxNumberOfSingleLineParameters in [0, -1] {
let console = try await Issue.captureConsole {
var config = MultilineParametersConfiguration()
@@ -12,29 +15,28 @@ final class MultilineParametersConfigurationTests: SwiftLintTestCase {
configuration: ["max_number_of_single_line_parameters": maxNumberOfSingleLineParameters]
)
}
XCTAssertEqual(
console,
"""
warning: Inconsistent configuration for 'multiline_parameters' rule: Option \
'max_number_of_single_line_parameters' should be >= 1.
"""
#expect(
console == """
warning: Inconsistent configuration for 'multiline_parameters' rule: Option \
'max_number_of_single_line_parameters' should be >= 1.
"""
)
}
}
func testInvalidMaxNumberOfSingleLineParametersWithSingleLineEnabled() async throws {
@Test
func invalidMaxNumberOfSingleLineParametersWithSingleLineEnabled() async throws {
let console = try await Issue.captureConsole {
var config = MultilineParametersConfiguration()
try config.apply(
configuration: ["max_number_of_single_line_parameters": 2, "allows_single_line": false]
)
}
XCTAssertEqual(
console,
"""
warning: Inconsistent configuration for 'multiline_parameters' rule: Option \
'max_number_of_single_line_parameters' has no effect when 'allows_single_line' is false.
"""
#expect(
console == """
warning: Inconsistent configuration for 'multiline_parameters' rule: Option \
'max_number_of_single_line_parameters' has no effect when 'allows_single_line' is false.
"""
)
}
}
@@ -1,11 +1,14 @@
@testable import SwiftLintBuiltInRules
import TestHelpers
import XCTest
import Testing
final class NameConfigurationTests: SwiftLintTestCase {
@testable import SwiftLintBuiltInRules
@Suite(.rulesRegistered)
struct NameConfigurationTests {
typealias TesteeType = NameConfiguration<RuleMock>
func testNameConfigurationSetsCorrectly() {
@Test
func nameConfigurationSetsCorrectly() {
let config: [String: any Sendable] = [
"min_length": ["warning": 17, "error": 7],
"max_length": ["warning": 170, "error": 700],
@@ -26,66 +29,80 @@ final class NameConfigurationTests: SwiftLintTestCase {
validatesStartWithLowercase: .warning)
do {
try nameConfig.apply(configuration: config)
XCTAssertEqual(nameConfig, comp)
#expect(nameConfig == comp)
} catch {
XCTFail("Did not configure correctly")
Testing.Issue.record("Did not configure correctly")
}
}
func testCaseCheck() throws {
var nameConfig = TesteeType(minLengthWarning: 0,
minLengthError: 0,
maxLengthWarning: 0,
maxLengthError: 0)
@Test
func caseCheck() throws {
var nameConfig = TesteeType(
minLengthWarning: 0,
minLengthError: 0,
maxLengthWarning: 0,
maxLengthError: 0
)
XCTAssertEqual(nameConfig.validatesStartWithLowercase, .error)
#expect(nameConfig.validatesStartWithLowercase == .error)
try nameConfig.apply(configuration: ["validates_start_with_lowercase": "off"])
XCTAssertEqual(nameConfig.validatesStartWithLowercase, .off)
#expect(nameConfig.validatesStartWithLowercase == .off)
try nameConfig.apply(configuration: ["validates_start_with_lowercase": "warning"])
XCTAssertEqual(nameConfig.validatesStartWithLowercase, .warning)
#expect(nameConfig.validatesStartWithLowercase == .warning)
}
func testNameConfigurationThrowsOnBadConfig() {
@Test
func nameConfigurationThrowsOnBadConfig() {
let config = 17
var nameConfig = TesteeType(minLengthWarning: 0,
minLengthError: 0,
maxLengthWarning: 0,
maxLengthError: 0)
checkError(Issue.invalidConfiguration(ruleID: RuleMock.identifier)) {
var nameConfig = TesteeType(
minLengthWarning: 0,
minLengthError: 0,
maxLengthWarning: 0,
maxLengthError: 0
)
#expect(throws: Issue.invalidConfiguration(ruleID: RuleMock.identifier)) {
try nameConfig.apply(configuration: config)
}
}
func testNameConfigurationMinLengthThreshold() {
let nameConfig = TesteeType(minLengthWarning: 7,
minLengthError: 17,
maxLengthWarning: 0,
maxLengthError: 0,
excluded: [])
XCTAssertEqual(nameConfig.minLengthThreshold, 17)
@Test
func nameConfigurationMinLengthThreshold() {
let nameConfig = TesteeType(
minLengthWarning: 7,
minLengthError: 17,
maxLengthWarning: 0,
maxLengthError: 0,
excluded: []
)
#expect(nameConfig.minLengthThreshold == 17)
}
func testNameConfigurationMaxLengthThreshold() {
let nameConfig = TesteeType(minLengthWarning: 0,
minLengthError: 0,
maxLengthWarning: 17,
maxLengthError: 7,
excluded: [])
XCTAssertEqual(nameConfig.maxLengthThreshold, 7)
@Test
func nameConfigurationMaxLengthThreshold() {
let nameConfig = TesteeType(
minLengthWarning: 0,
minLengthError: 0,
maxLengthWarning: 17,
maxLengthError: 7,
excluded: []
)
#expect(nameConfig.maxLengthThreshold == 7)
}
func testUnallowedSymbolsSeverity() throws {
var nameConfig = TesteeType(minLengthWarning: 3,
minLengthError: 1,
maxLengthWarning: 17,
maxLengthError: 22,
unallowedSymbolsSeverity: .warning)
XCTAssertEqual(nameConfig.unallowedSymbolsSeverity, .warning)
@Test
func unallowedSymbolsSeverity() throws {
var nameConfig = TesteeType(
minLengthWarning: 3,
minLengthError: 1,
maxLengthWarning: 17,
maxLengthError: 22,
unallowedSymbolsSeverity: .warning
)
#expect(nameConfig.unallowedSymbolsSeverity == .warning)
try nameConfig.apply(configuration: ["unallowed_symbols_severity": "error"])
XCTAssertEqual(nameConfig.unallowedSymbolsSeverity, .error)
#expect(nameConfig.unallowedSymbolsSeverity == .error)
}
}
+11 -8
View File
@@ -1,14 +1,16 @@
@testable import SwiftLintBuiltInRules
import TestHelpers
import Testing
@testable import SwiftLintBuiltInRules
// swiftlint:disable file_length
private let detectingTypes = ["actor", "class", "struct", "enum"]
// swiftlint:disable:next type_body_length
final class NestingRuleTests: SwiftLintTestCase {
// swiftlint:disable:next function_body_length
func testNestingWithAlwaysAllowOneTypeInFunctions() {
@Suite(.rulesRegistered)
struct NestingRuleTests { // swiftlint:disable:this type_body_length
@Test
func nestingWithAlwaysAllowOneTypeInFunctions() { // swiftlint:disable:this function_body_length
var nonTriggeringExamples = NestingRule.description.nonTriggeringExamples
nonTriggeringExamples.append(contentsOf: detectingTypes.flatMap { type -> [Example] in
[
@@ -212,8 +214,8 @@ final class NestingRuleTests: SwiftLintTestCase {
verifyRule(description, ruleConfiguration: ["always_allow_one_type_in_functions": true])
}
// swiftlint:disable:next function_body_length
func testNestingWithoutCheckNestingInClosuresAndStatements() {
@Test
func nestingWithoutCheckNestingInClosuresAndStatements() { // swiftlint:disable:this function_body_length
var nonTriggeringExamples = NestingRule.description.nonTriggeringExamples
// swiftlint:disable:next closure_body_length
nonTriggeringExamples.append(contentsOf: detectingTypes.flatMap { type -> [Example] in
@@ -511,7 +513,8 @@ final class NestingRuleTests: SwiftLintTestCase {
verifyRule(description, ruleConfiguration: ["check_nesting_in_closures_and_statements": false])
}
func testNestingWithoutTypealiasAndAssociatedtype() {
@Test
func nestingWithoutTypealiasAndAssociatedtype() {
var nonTriggeringExamples = NestingRule.description.nonTriggeringExamples
nonTriggeringExamples.append(contentsOf: detectingTypes.flatMap { type -> [Example] in
[
@@ -1,16 +1,20 @@
import TestHelpers
import Testing
@testable import SwiftLintBuiltInRules
@testable import SwiftLintCore
import TestHelpers
import XCTest
final class NoEmptyBlockConfigurationTests: SwiftLintTestCase {
func testDefaultConfiguration() {
@Suite(.rulesRegistered)
struct NoEmptyBlockConfigurationTests {
@Test
func defaultConfiguration() {
let config = NoEmptyBlockConfiguration()
XCTAssertEqual(config.severityConfiguration.severity, .warning)
XCTAssertEqual(config.enabledBlockTypes, NoEmptyBlockConfiguration.CodeBlockType.all)
#expect(config.severityConfiguration.severity == .warning)
#expect(config.enabledBlockTypes == NoEmptyBlockConfiguration.CodeBlockType.all)
}
func testApplyingCustomConfiguration() throws {
@Test
func applyingCustomConfiguration() throws {
var config = NoEmptyBlockConfiguration()
try config.apply(
configuration: [
@@ -18,41 +22,44 @@ final class NoEmptyBlockConfigurationTests: SwiftLintTestCase {
"disabled_block_types": ["function_bodies"],
] as [String: any Sendable]
)
XCTAssertEqual(config.severityConfiguration.severity, .error)
XCTAssertEqual(config.enabledBlockTypes, Set([.initializerBodies, .statementBlocks, .closureBlocks]))
#expect(config.severityConfiguration.severity == .error)
#expect(config.enabledBlockTypes == Set([.initializerBodies, .statementBlocks, .closureBlocks]))
}
func testInvalidKeyInCustomConfiguration() async throws {
@Test
func invalidKeyInCustomConfiguration() async throws {
let console = try await Issue.captureConsole {
var config = NoEmptyBlockConfiguration()
try config.apply(configuration: ["invalidKey": "error"])
}
XCTAssertEqual(
console,
"warning: Configuration for 'no_empty_block' rule contains the invalid key(s) 'invalidKey'."
#expect(
console == "warning: Configuration for 'no_empty_block' rule contains the invalid key(s) 'invalidKey'."
)
}
func testInvalidTypeOfCustomConfiguration() {
@Test
func invalidTypeOfCustomConfiguration() {
var config = NoEmptyBlockConfiguration()
checkError(Issue.invalidConfiguration(ruleID: NoEmptyBlockRule.identifier)) {
#expect(throws: Issue.invalidConfiguration(ruleID: NoEmptyBlockRule.identifier)) {
try config.apply(configuration: "invalidKey")
}
}
func testInvalidTypeOfValueInCustomConfiguration() {
@Test
func invalidTypeOfValueInCustomConfiguration() {
var config = NoEmptyBlockConfiguration()
checkError(Issue.invalidConfiguration(ruleID: NoEmptyBlockRule.identifier)) {
#expect(throws: Issue.invalidConfiguration(ruleID: NoEmptyBlockRule.identifier)) {
try config.apply(configuration: ["severity": "foo"])
}
}
func testConsoleDescription() throws {
@Test
func consoleDescription() throws {
var config = NoEmptyBlockConfiguration()
try config.apply(configuration: ["disabled_block_types": ["initializer_bodies", "statement_blocks"]])
XCTAssertEqual(
RuleConfigurationDescription.from(configuration: config).oneLiner(),
"severity: warning; disabled_block_types: [initializer_bodies, statement_blocks]"
#expect(
RuleConfigurationDescription.from(configuration: config).oneLiner()
== "severity: warning; disabled_block_types: [initializer_bodies, statement_blocks]"
)
}
}
@@ -1,10 +1,13 @@
@testable import SwiftLintBuiltInRules
import SwiftParser
import TestHelpers
import XCTest
import Testing
final class NumberSeparatorRuleTests: SwiftLintTestCase {
func testNumberSeparatorWithMinimumLength() {
@testable import SwiftLintBuiltInRules
@Suite(.rulesRegistered)
struct NumberSeparatorRuleTests {
@Test
func numberSeparatorWithMinimumLength() {
let nonTriggeringExamples = [
Example("let foo = 10_000"),
Example("let foo = 1000"),
@@ -31,7 +34,8 @@ final class NumberSeparatorRuleTests: SwiftLintTestCase {
verifyRule(description, ruleConfiguration: ["minimum_length": 5])
}
func testNumberSeparatorWithMinimumFractionLength() {
@Test
func numberSeparatorWithMinimumFractionLength() {
let nonTriggeringExamples = [
Example("let foo = 1_000.000_000_1"),
Example("let foo = 1.000_001"),
@@ -57,7 +61,8 @@ final class NumberSeparatorRuleTests: SwiftLintTestCase {
verifyRule(description, ruleConfiguration: ["minimum_fraction_length": 5])
}
func testNumberSeparatorWithExcludeRanges() {
@Test
func numberSeparatorWithExcludeRanges() {
let nonTriggeringExamples = [
Example("let foo = 1950"),
Example("let foo = 1_950"),
@@ -100,38 +105,24 @@ final class NumberSeparatorRuleTests: SwiftLintTestCase {
)
}
func testSpecificViolationReasons() {
XCTAssertEqual(
violations(in: "1_000"),
[]
@Test
func specificViolationReasons() {
#expect(violations(in: "1_000").isEmpty)
#expect(violations(in: "1000") == [NumberSeparatorRule.missingSeparatorsReason])
#expect(
violations(in: "1.000000", config: ["minimum_fraction_length": 5])
== [NumberSeparatorRule.missingSeparatorsReason]
)
XCTAssertEqual(
violations(in: "1000"),
[NumberSeparatorRule.missingSeparatorsReason]
#expect(violations(in: "10_00") == [NumberSeparatorRule.misplacedSeparatorsReason])
#expect(violations(in: "1_000_0") == [NumberSeparatorRule.misplacedSeparatorsReason])
#expect(violations(in: "1000.0_00") == [NumberSeparatorRule.misplacedSeparatorsReason])
#expect(
violations(in: "10_00", config: ["minimum_length": 5])
== [NumberSeparatorRule.misplacedSeparatorsReason]
)
XCTAssertEqual(
violations(in: "1.000000", config: ["minimum_fraction_length": 5]),
[NumberSeparatorRule.missingSeparatorsReason]
)
XCTAssertEqual(
violations(in: "10_00"),
[NumberSeparatorRule.misplacedSeparatorsReason]
)
XCTAssertEqual(
violations(in: "1_000_0"),
[NumberSeparatorRule.misplacedSeparatorsReason]
)
XCTAssertEqual(
violations(in: "1000.0_00"),
[NumberSeparatorRule.misplacedSeparatorsReason]
)
XCTAssertEqual(
violations(in: "10_00", config: ["minimum_length": 5]),
[NumberSeparatorRule.misplacedSeparatorsReason]
)
XCTAssertEqual(
violations(in: "1000.0_00", config: ["minimum_fraction_length": 5]),
[NumberSeparatorRule.misplacedSeparatorsReason]
#expect(
violations(in: "1000.0_00", config: ["minimum_fraction_length": 5])
== [NumberSeparatorRule.misplacedSeparatorsReason]
)
}
@@ -1,7 +1,10 @@
@testable import SwiftLintBuiltInRules
import TestHelpers
import Testing
final class ObjectLiteralRuleTests: SwiftLintTestCase {
@testable import SwiftLintBuiltInRules
@Suite(.rulesRegistered)
struct ObjectLiteralRuleTests {
// MARK: - Instance Properties
private let imageLiteralTriggeringExamples = ["", ".init"].flatMap { (method: String) -> [Example] in
["UI", "NS"].flatMap { (prefix: String) -> [Example] in
@@ -26,7 +29,8 @@ final class ObjectLiteralRuleTests: SwiftLintTestCase {
}
// MARK: - Test Methods
func testObjectLiteralWithImageLiteral() {
@Test
func objectLiteralWithImageLiteral() {
// Verify ObjectLiteral rule for when image_literal is true.
let baseDescription = ObjectLiteralRule.description
let nonTriggeringColorLiteralExamples = colorLiteralTriggeringExamples.removingViolationMarkers()
@@ -38,7 +42,8 @@ final class ObjectLiteralRuleTests: SwiftLintTestCase {
verifyRule(description, ruleConfiguration: ["image_literal": true, "color_literal": false])
}
func testObjectLiteralWithColorLiteral() {
@Test
func objectLiteralWithColorLiteral() {
// Verify ObjectLiteral rule for when color_literal is true.
let baseDescription = ObjectLiteralRule.description
let nonTriggeringImageLiteralExamples = imageLiteralTriggeringExamples.removingViolationMarkers()
@@ -50,7 +55,8 @@ final class ObjectLiteralRuleTests: SwiftLintTestCase {
verifyRule(description, ruleConfiguration: ["image_literal": false, "color_literal": true])
}
func testObjectLiteralWithImageAndColorLiteral() {
@Test
func objectLiteralWithImageAndColorLiteral() {
// Verify ObjectLiteral rule for when image_literal & color_literal are true.
let description = ObjectLiteralRule.description.with(triggeringExamples: allTriggeringExamples)
verifyRule(description, ruleConfiguration: ["image_literal": true, "color_literal": true])
@@ -1,8 +1,12 @@
@testable import SwiftLintBuiltInRules
import TestHelpers
import Testing
final class OpeningBraceRuleTests: SwiftLintTestCase {
func testDefaultNonTriggeringExamplesWithMultilineOptionsTrue() {
@testable import SwiftLintBuiltInRules
@Suite(.rulesRegistered)
struct OpeningBraceRuleTests {
@Test
func defaultNonTriggeringExamplesWithMultilineOptionsTrue() {
let description = OpeningBraceRule.description
.with(triggeringExamples: [])
.with(corrections: [:])
@@ -14,7 +18,8 @@ final class OpeningBraceRuleTests: SwiftLintTestCase {
])
}
func testWithIgnoreMultilineTypeHeadersTrue() {
@Test
func withIgnoreMultilineTypeHeadersTrue() {
let nonTriggeringExamples = [
Example("""
extension A
@@ -56,7 +61,8 @@ final class OpeningBraceRuleTests: SwiftLintTestCase {
verifyRule(description, ruleConfiguration: ["ignore_multiline_type_headers": true])
}
func testWithIgnoreMultilineStatementConditionsTrue() {
@Test
func withIgnoreMultilineStatementConditionsTrue() {
let nonTriggeringExamples = [
Example("""
while
@@ -114,8 +120,8 @@ final class OpeningBraceRuleTests: SwiftLintTestCase {
verifyRule(description, ruleConfiguration: ["ignore_multiline_statement_conditions": true])
}
// swiftlint:disable:next function_body_length
func testWithIgnoreMultilineFunctionSignaturesTrue() {
@Test
func withIgnoreMultilineFunctionSignaturesTrue() { // swiftlint:disable:this function_body_length
let nonTriggeringExamples = [
Example("""
func abc(
@@ -1,8 +1,10 @@
@testable import SwiftLintBuiltInRules
import TestHelpers
import XCTest
import Testing
final class PreferKeyPathRuleTests: SwiftLintTestCase {
@testable import SwiftLintBuiltInRules
@Suite(.rulesRegistered)
struct PreferKeyPathRuleTests {
private static let extendedMode = ["restrict_to_standard_functions": false]
private static let ignoreIdentity = ["ignore_identity_closures": true]
private static let extendedModeAndIgnoreIdentity = [
@@ -10,9 +12,8 @@ final class PreferKeyPathRuleTests: SwiftLintTestCase {
"ignore_identity_closures": true,
]
func testIdentityExpressionInSwift6() throws {
try XCTSkipIf(SwiftVersion.current < .six)
@Test(.disabled(if: SwiftVersion.current < .six))
func identityExpressionInSwift6() throws {
let description = PreferKeyPathRule.description
.with(nonTriggeringExamples: [
Example("f.filter { a in b }"),
@@ -1,8 +1,12 @@
@testable import SwiftLintBuiltInRules
import TestHelpers
import Testing
final class PrefixedTopLevelConstantRuleTests: SwiftLintTestCase {
func testPrivateOnly() {
@testable import SwiftLintBuiltInRules
@Suite(.rulesRegistered)
struct PrefixedTopLevelConstantRuleTests {
@Test
func privateOnly() {
let triggeringExamples = [
Example("private let ↓Foo = 20.0"),
Example("fileprivate let ↓foo = 20.0"),
@@ -1,8 +1,12 @@
@testable import SwiftLintBuiltInRules
import TestHelpers
import Testing
final class PrivateOverFilePrivateRuleTests: SwiftLintTestCase {
func testPrivateOverFilePrivateValidatingExtensions() {
@testable import SwiftLintBuiltInRules
@Suite(.rulesRegistered)
struct PrivateOverFilePrivateRuleTests {
@Test
func privateOverFilePrivateValidatingExtensions() {
let baseDescription = PrivateOverFilePrivateRule.description
let triggeringExamples = baseDescription.triggeringExamples + [
Example("↓fileprivate extension String {}"),
@@ -20,7 +24,8 @@ final class PrivateOverFilePrivateRuleTests: SwiftLintTestCase {
verifyRule(description, ruleConfiguration: ["validate_extensions": true])
}
func testPrivateOverFilePrivateNotValidatingExtensions() {
@Test
func privateOverFilePrivateNotValidatingExtensions() {
let baseDescription = PrivateOverFilePrivateRule.description
let nonTriggeringExamples = baseDescription.nonTriggeringExamples + [
Example("fileprivate extension String {}")
@@ -1,8 +1,10 @@
@testable import SwiftLintBuiltInRules
import TestHelpers
import XCTest
import Testing
final class RequiredEnumCaseConfigurationTests: SwiftLintTestCase {
@testable import SwiftLintBuiltInRules
@Suite(.rulesRegistered)
final class RequiredEnumCaseConfigurationTests {
private typealias RuleConfiguration = RequiredEnumCaseConfiguration
private typealias RequiredCase = RuleConfiguration.RequiredCase
@@ -20,56 +22,64 @@ final class RequiredEnumCaseConfigurationTests: SwiftLintTestCase {
return config
}()
func testRequiredCaseHashValue() {
@Test
func requiredCaseHashValue() {
let requiredCase = RequiredCase(name: "success")
XCTAssertEqual(requiredCase.hashValue, RequiredCase(name: "success").hashValue)
#expect(requiredCase.hashValue == RequiredCase(name: "success").hashValue)
}
func testRequiredCaseEquatableReturnsTrue() {
@Test
func requiredCaseEquatableReturnsTrue() {
let lhs = RequiredCase(name: "success")
let rhs = RequiredCase(name: "success")
XCTAssertEqual(lhs, rhs)
#expect(lhs == rhs)
}
func testRequiredCaseEquatableReturnsFalseBecauseOfDifferentName() {
@Test
func requiredCaseEquatableReturnsFalseBecauseOfDifferentName() {
let lhs = RequiredCase(name: "success")
let rhs = RequiredCase(name: "error")
XCTAssertNotEqual(lhs, rhs)
#expect(lhs != rhs)
}
func testConsoleDescriptionReturnsAllConfiguredProtocols() {
@Test
func consoleDescriptionReturnsAllConfiguredProtocols() {
let expected = "NetworkResults: error: warning; RequiredProtocol: error: warning, success: warning"
XCTAssertEqual(config.parameterDescription?.oneLiner(), expected)
#expect(config.parameterDescription?.oneLiner() == expected)
}
func testConsoleDescriptionReturnsNoConfiguredProtocols() {
@Test
func consoleDescriptionReturnsNoConfiguredProtocols() {
let expected = "{Protocol Name}: {Case Name 1}: {warning|error}, {Case Name 2}: {warning|error}"
config.protocols.removeAll()
XCTAssertEqual(config.parameterDescription?.oneLiner(), expected)
#expect(config.parameterDescription?.oneLiner() == expected)
}
private func validateRulesExistForProtocol1() {
XCTAssertTrue(self.config.protocols[Self.protocol1]?.contains(Self.rule1) ?? false)
XCTAssertTrue(self.config.protocols[Self.protocol1]?.contains(Self.rule2) ?? false)
#expect(self.config.protocols[Self.protocol1]?.contains(Self.rule1) ?? false)
#expect(self.config.protocols[Self.protocol1]?.contains(Self.rule2) ?? false)
}
func testRegisterProtocolCasesRegistersCasesWithSpecifiedSeverity() {
@Test
func registerProtocolCasesRegistersCasesWithSpecifiedSeverity() {
config.register(protocol: Self.protocol3, cases: ["success": "error", "error": "warning"])
validateRulesExistForProtocol3()
}
private func validateRulesExistForProtocol3() {
XCTAssertTrue(self.config.protocols[Self.protocol3]?.contains(Self.rule3) ?? false)
XCTAssertTrue(self.config.protocols[Self.protocol3]?.contains(Self.rule2) ?? false)
#expect(self.config.protocols[Self.protocol3]?.contains(Self.rule3) ?? false)
#expect(self.config.protocols[Self.protocol3]?.contains(Self.rule2) ?? false)
}
func testRegisterProtocols() {
@Test
func registerProtocols() {
config.register(protocols: [Self.protocol1: ["success": "warning", "error": "warning"]])
validateRulesExistForProtocol1()
}
func testApplyThrowsErrorBecausePassedConfigurationCantBeCast() {
@Test
func applyThrowsErrorBecausePassedConfigurationCantBeCast() {
var errorThrown = false
do {
@@ -78,41 +88,45 @@ final class RequiredEnumCaseConfigurationTests: SwiftLintTestCase {
errorThrown = true
}
XCTAssertTrue(errorThrown)
#expect(errorThrown)
}
func testApplyRegistersProtocols() {
@Test
func applyRegistersProtocols() {
try? config.apply(configuration: [Self.protocol1: ["success": "warning", "error": "warning"]])
validateRulesExistForProtocol1()
}
func testEqualsReturnsTrue() {
@Test
func equalsReturnsTrue() {
var lhs = RuleConfiguration()
try? lhs.apply(configuration: [Self.protocol1: ["success", "error"]])
var rhs = RuleConfiguration()
try? rhs.apply(configuration: [Self.protocol1: ["success", "error"]])
XCTAssertEqual(lhs, rhs)
#expect(lhs == rhs)
}
func testEqualsReturnsFalseBecauseProtocolsArentEqual() {
@Test
func equalsReturnsFalseBecauseProtocolsArentEqual() {
var lhs = RuleConfiguration()
try? lhs.apply(configuration: [Self.protocol1: ["success": "error"]])
var rhs = RuleConfiguration()
try? rhs.apply(configuration: [Self.protocol2: ["success": "error", "error": "warning"]])
XCTAssertNotEqual(lhs, rhs)
#expect(lhs != rhs)
}
func testEqualsReturnsFalseBecauseSeverityIsntEqual() {
@Test
func equalsReturnsFalseBecauseSeverityIsntEqual() {
var lhs = RuleConfiguration()
try? lhs.apply(configuration: [Self.protocol1: ["success": "error", "error": "error"]])
var rhs = RuleConfiguration()
try? rhs.apply(configuration: [Self.protocol1: ["success": "warning", "error": "error"]])
XCTAssertNotEqual(lhs, rhs)
#expect(lhs != rhs)
}
}
@@ -1,8 +1,12 @@
@testable import SwiftLintBuiltInRules
import TestHelpers
import Testing
final class StatementPositionRuleTests: SwiftLintTestCase {
func testStatementPositionUncuddled() {
@testable import SwiftLintBuiltInRules
@Suite(.rulesRegistered)
struct StatementPositionRuleTests {
@Test
func statementPositionUncuddled() {
let configuration = ["statement_mode": "uncuddled_else"]
verifyRule(StatementPositionRule.uncuddledDescription, ruleConfiguration: configuration)
}
@@ -1,8 +1,12 @@
@testable import SwiftLintBuiltInRules
import TestHelpers
import Testing
final class SwitchCaseAlignmentRuleTests: SwiftLintTestCase {
func testSwitchCaseAlignmentWithoutIndentedCases() {
@testable import SwiftLintBuiltInRules
@Suite(.rulesRegistered)
struct SwitchCaseAlignmentRuleTests {
@Test
func switchCaseAlignmentWithoutIndentedCases() {
let baseDescription = SwitchCaseAlignmentRule.description
let examples = SwitchCaseAlignmentRule.Examples(indentedCases: false)
@@ -12,7 +16,8 @@ final class SwitchCaseAlignmentRuleTests: SwiftLintTestCase {
verifyRule(description)
}
func testSwitchCaseAlignmentWithIndentedCases() {
@Test
func switchCaseAlignmentWithIndentedCases() {
let baseDescription = SwitchCaseAlignmentRule.description
let examples = SwitchCaseAlignmentRule.Examples(indentedCases: true)
+25 -18
View File
@@ -1,44 +1,51 @@
@testable import SwiftLintBuiltInRules
import TestHelpers
import XCTest
import Testing
final class TodoRuleTests: SwiftLintTestCase {
func testTodo() {
@testable import SwiftLintBuiltInRules
@Suite(.rulesRegistered)
struct TodoRuleTests {
@Test
func todo() {
verifyRule(TodoRule.description, commentDoesntViolate: false)
}
func testTodoMessage() {
@Test
func todoMessage() {
let example = Example("fatalError() // TODO: Implement")
let violations = self.violations(example)
XCTAssertEqual(violations.count, 1)
XCTAssertEqual(violations.first!.reason, "TODOs should be resolved (Implement)")
#expect(violations.count == 1)
#expect(violations.first?.reason == "TODOs should be resolved (Implement)")
}
func testFixMeMessage() {
@Test
func fixMeMessage() {
let example = Example("fatalError() // FIXME: Implement")
let violations = self.violations(example)
XCTAssertEqual(violations.count, 1)
XCTAssertEqual(violations.first!.reason, "FIXMEs should be resolved (Implement)")
#expect(violations.count == 1)
#expect(violations.first?.reason == "FIXMEs should be resolved (Implement)")
}
func testOnlyFixMe() {
@Test
func onlyFixMe() {
let example = Example("""
fatalError() // TODO: Implement todo
fatalError() // FIXME: Implement fixme
""")
""")
let violations = self.violations(example, config: ["only": ["FIXME"]])
XCTAssertEqual(violations.count, 1)
XCTAssertEqual(violations.first!.reason, "FIXMEs should be resolved (Implement fixme)")
#expect(violations.count == 1)
#expect(violations.first?.reason == "FIXMEs should be resolved (Implement fixme)")
}
func testOnlyTodo() {
@Test
func onlyTodo() {
let example = Example("""
fatalError() // TODO: Implement todo
fatalError() // FIXME: Implement fixme
""")
""")
let violations = self.violations(example, config: ["only": ["TODO"]])
XCTAssertEqual(violations.count, 1)
XCTAssertEqual(violations.first!.reason, "TODOs should be resolved (Implement todo)")
#expect(violations.count == 1)
#expect(violations.first?.reason == "TODOs should be resolved (Implement todo)")
}
private func violations(_ example: Example, config: Any? = nil) -> [StyleViolation] {
@@ -1,15 +1,19 @@
@testable import SwiftLintBuiltInRules
import TestHelpers
import XCTest
import Testing
final class TrailingClosureConfigurationTests: SwiftLintTestCase {
func testDefaultConfiguration() {
@testable import SwiftLintBuiltInRules
@Suite(.rulesRegistered)
struct TrailingClosureConfigurationTests {
@Test
func defaultConfiguration() {
let config = TrailingClosureConfiguration()
XCTAssertEqual(config.severityConfiguration.severity, .warning)
XCTAssertFalse(config.onlySingleMutedParameter)
#expect(config.severityConfiguration.severity == .warning)
#expect(!config.onlySingleMutedParameter)
}
func testApplyingCustomConfiguration() throws {
@Test
func applyingCustomConfiguration() throws {
var config = TrailingClosureConfiguration()
try config.apply(
configuration: [
@@ -17,7 +21,7 @@ final class TrailingClosureConfigurationTests: SwiftLintTestCase {
"only_single_muted_parameter": true,
] as [String: any Sendable]
)
XCTAssertEqual(config.severityConfiguration.severity, .error)
XCTAssertTrue(config.onlySingleMutedParameter)
#expect(config.severityConfiguration.severity == .error)
#expect(config.onlySingleMutedParameter)
}
}
@@ -1,8 +1,12 @@
@testable import SwiftLintBuiltInRules
import TestHelpers
import Testing
final class TrailingClosureRuleTests: SwiftLintTestCase {
func testWithOnlySingleMutedParameterEnabled() {
@testable import SwiftLintBuiltInRules
@Suite(.rulesRegistered)
struct TrailingClosureRuleTests {
@Test
func withOnlySingleMutedParameterEnabled() {
let originalDescription = TrailingClosureRule.description
let description = originalDescription
.with(nonTriggeringExamples: originalDescription.nonTriggeringExamples + [
@@ -1,9 +1,12 @@
@testable import SwiftLintBuiltInRules
import TestHelpers
import XCTest
import Testing
final class TrailingCommaRuleTests: SwiftLintTestCase {
func testTrailingCommaRuleWithDefaultConfiguration() {
@testable import SwiftLintBuiltInRules
@Suite(.rulesRegistered)
struct TrailingCommaRuleTests {
@Test
func trailingCommaRuleWithDefaultConfiguration() {
// Verify TrailingCommaRule with test values for when mandatory_comma is false (default).
let triggeringExamples = TrailingCommaRule.description.triggeringExamples +
[Example("class C {\n #if true\n func f() {\n let foo = [1, 2, 3↓,]\n }\n #endif\n}")]
@@ -11,8 +14,8 @@ final class TrailingCommaRuleTests: SwiftLintTestCase {
// Ensure the rule produces the correct reason string.
let failingCase = Example("let array = [\n\t1,\n\t2,\n]\n")
XCTAssertEqual(trailingCommaViolations(failingCase).first?.reason,
"Collection literals should not have trailing commas")
#expect(
trailingCommaViolations(failingCase).first?.reason == "Collection literals should not have trailing commas")
}
private static let triggeringExamples = [
@@ -52,11 +55,12 @@ final class TrailingCommaRuleTests: SwiftLintTestCase {
}()
private let mandatoryCommaRuleDescription = TrailingCommaRule.description
.with(nonTriggeringExamples: TrailingCommaRuleTests.nonTriggeringExamples)
.with(triggeringExamples: TrailingCommaRuleTests.triggeringExamples)
.with(corrections: TrailingCommaRuleTests.corrections)
.with(nonTriggeringExamples: Self.nonTriggeringExamples)
.with(triggeringExamples: Self.triggeringExamples)
.with(corrections: Self.corrections)
func testTrailingCommaRuleWithMandatoryComma() {
@Test
func trailingCommaRuleWithMandatoryComma() {
// Verify TrailingCommaRule with test values for when mandatory_comma is true.
let ruleDescription = mandatoryCommaRuleDescription
let ruleConfiguration = ["mandatory_comma": true]
@@ -65,8 +69,9 @@ final class TrailingCommaRuleTests: SwiftLintTestCase {
// Ensure the rule produces the correct reason string.
let failingCase = Example("let array = [\n\t1,\n\t2\n]\n")
XCTAssertEqual(trailingCommaViolations(failingCase, ruleConfiguration: ruleConfiguration).first?.reason,
"Multi-line collection literals should have trailing commas")
#expect(
trailingCommaViolations(failingCase, ruleConfiguration: ruleConfiguration).first?.reason
== "Multi-line collection literals should have trailing commas")
}
private func trailingCommaViolations(_ example: Example, ruleConfiguration: Any? = nil) -> [StyleViolation] {
@@ -1,8 +1,12 @@
@testable import SwiftLintBuiltInRules
import TestHelpers
import Testing
final class TrailingWhitespaceRuleTests: SwiftLintTestCase {
func testWithIgnoresEmptyLinesEnabled() {
@testable import SwiftLintBuiltInRules
@Suite(.rulesRegistered)
struct TrailingWhitespaceRuleTests {
@Test
func withIgnoresEmptyLinesEnabled() {
// Perform additional tests with the ignores_empty_lines setting enabled.
// The set of non-triggering examples is extended by a whitespace-indented empty line
let baseDescription = TrailingWhitespaceRule.description
@@ -13,7 +17,8 @@ final class TrailingWhitespaceRuleTests: SwiftLintTestCase {
ruleConfiguration: ["ignores_empty_lines": true, "ignores_comments": true])
}
func testWithIgnoresCommentsDisabled() {
@Test
func withIgnoresCommentsDisabled() {
// Perform additional tests with the ignores_comments settings disabled.
let baseDescription = TrailingWhitespaceRule.description
let triggeringComments = [
@@ -1,16 +1,20 @@
@testable import SwiftLintBuiltInRules
import TestHelpers
import XCTest
import Testing
final class TypeBodyLengthConfigurationTests: SwiftLintTestCase {
func testDefaultConfiguration() {
@testable import SwiftLintBuiltInRules
@Suite(.rulesRegistered)
struct TypeBodyLengthConfigurationTests {
@Test
func defaultConfiguration() {
let config = TypeBodyLengthConfiguration()
XCTAssertEqual(config.severityConfiguration.warning, 250)
XCTAssertEqual(config.severityConfiguration.error, 350)
XCTAssertEqual(config.excludedTypes, [.extension, .protocol])
#expect(config.severityConfiguration.warning == 250)
#expect(config.severityConfiguration.error == 350)
#expect(config.excludedTypes == [.extension, .protocol])
}
func testApplyingCustomConfiguration() throws {
@Test
func applyingCustomConfiguration() throws {
var config = TypeBodyLengthConfiguration()
try config.apply(
configuration: [
@@ -19,58 +23,63 @@ final class TypeBodyLengthConfigurationTests: SwiftLintTestCase {
"excluded_types": ["struct", "class"],
] as [String: any Sendable]
)
XCTAssertEqual(config.severityConfiguration.warning, 150)
XCTAssertEqual(config.severityConfiguration.error, 200)
XCTAssertEqual(config.excludedTypes, Set([.struct, .class]))
#expect(config.severityConfiguration.warning == 150)
#expect(config.severityConfiguration.error == 200)
#expect(config.excludedTypes == Set([.struct, .class]))
}
func testApplyingOnlyExcludedTypesConfiguration() throws {
@Test
func applyingOnlyExcludedTypesConfiguration() throws {
var config = TypeBodyLengthConfiguration()
try config.apply(
configuration: [
"excluded_types": ["actor", "enum"]
] as [String: any Sendable]
)
configuration: [
"excluded_types": ["actor", "enum"]
] as [String: any Sendable]
)
// Severity should remain default
XCTAssertEqual(config.severityConfiguration.warning, 250)
XCTAssertEqual(config.severityConfiguration.error, 350)
#expect(config.severityConfiguration.warning == 250)
#expect(config.severityConfiguration.error == 350)
// Excluded types should be updated
XCTAssertEqual(config.excludedTypes, Set([.actor, .enum]))
#expect(config.excludedTypes == Set([.actor, .enum]))
}
func testApplyingAllTypesAsExcludedConfiguration() throws {
@Test
func applyingAllTypesAsExcludedConfiguration() throws {
var config = TypeBodyLengthConfiguration()
try config.apply(
configuration: [
"excluded_types": ["struct", "class", "actor", "enum", "extension", "protocol"]
] as [String: any Sendable]
)
XCTAssertEqual(config.excludedTypes, Set(TypeBodyLengthCheckType.allCases))
#expect(config.excludedTypes == Set(TypeBodyLengthCheckType.allCases))
}
func testApplyingEmptyExcludedTypesConfiguration() throws {
@Test
func applyingEmptyExcludedTypesConfiguration() throws {
var config = TypeBodyLengthConfiguration()
try config.apply(
configuration: [
"excluded_types": [] as [String]
] as [String: any Sendable]
)
XCTAssertTrue(config.excludedTypes.isEmpty)
#expect(config.excludedTypes.isEmpty)
}
func testApplyingSingleExcludedTypeConfiguration() throws {
@Test
func applyingSingleExcludedTypeConfiguration() throws {
var config = TypeBodyLengthConfiguration()
try config.apply(
configuration: [
"excluded_types": ["extension"]
] as [String: any Sendable]
)
XCTAssertEqual(config.excludedTypes, Set([.extension]))
#expect(config.excludedTypes == Set([.extension]))
}
func testInvalidExcludedTypeConfiguration() throws {
@Test
func invalidExcludedTypeConfiguration() throws {
var config = TypeBodyLengthConfiguration()
checkError(Issue.invalidConfiguration(ruleID: TypeBodyLengthRule.identifier)) {
try config.apply(
@@ -79,13 +88,13 @@ final class TypeBodyLengthConfigurationTests: SwiftLintTestCase {
] as [String: any Sendable]
)
}
XCTAssertEqual(config.excludedTypes, Set([.extension, .protocol]))
#expect(config.excludedTypes == Set([.extension, .protocol]))
}
func testTypeEnumComparability() {
XCTAssertEqual(
TypeBodyLengthCheckType.allCases.sorted(),
[.actor, .class, .enum, .extension, .protocol, .struct]
@Test
func typeEnumComparability() {
#expect(
TypeBodyLengthCheckType.allCases.sorted() == [.actor, .class, .enum, .extension, .protocol, .struct]
)
}
}
@@ -1,9 +1,12 @@
@testable import SwiftLintBuiltInRules
import TestHelpers
import XCTest
import Testing
final class TypeBodyLengthRuleTests: SwiftLintTestCase {
func testWarning() {
@testable import SwiftLintBuiltInRules
@Suite(.rulesRegistered)
struct TypeBodyLengthRuleTests {
@Test
func warning() {
let example = Example("""
actor A {
let x = 0
@@ -12,9 +15,8 @@ final class TypeBodyLengthRuleTests: SwiftLintTestCase {
}
""")
XCTAssertEqual(
self.violations(example, configuration: ["warning": 2, "error": 4]),
[
#expect(
self.violations(example, configuration: ["warning": 2, "error": 4]) == [
StyleViolation(
ruleDescription: TypeBodyLengthRule.description,
severity: .warning,
@@ -28,7 +30,8 @@ final class TypeBodyLengthRuleTests: SwiftLintTestCase {
)
}
func testError() {
@Test
func error() {
let example = Example("""
class C {
let x = 0
@@ -37,9 +40,8 @@ final class TypeBodyLengthRuleTests: SwiftLintTestCase {
}
""")
XCTAssertEqual(
self.violations(example, configuration: ["warning": 1, "error": 2]),
[
#expect(
self.violations(example, configuration: ["warning": 1, "error": 2]) == [
StyleViolation(
ruleDescription: TypeBodyLengthRule.description,
severity: .error,
@@ -53,16 +55,16 @@ final class TypeBodyLengthRuleTests: SwiftLintTestCase {
)
}
func testViolationMessages() {
@Test
func violationMessages() {
let types = TypeBodyLengthRule.description.triggeringExamples.flatMap {
self.violations($0, configuration: ["warning": 2])
violations($0, configuration: ["warning": 2])
}.compactMap {
$0.reason.split(separator: " ", maxSplits: 1).first
}
XCTAssertEqual(
types,
["Actor", "Class", "Enum", "Extension", "Protocol", "Struct"]
#expect(
types == ["Actor", "Class", "Enum", "Extension", "Protocol", "Struct"]
)
}
@@ -1,9 +1,12 @@
@testable import SwiftLintBuiltInRules
import TestHelpers
import Testing
final class TypeContentsOrderRuleTests: SwiftLintTestCase {
// swiftlint:disable:next function_body_length
func testTypeContentsOrderReversedOrder() {
@testable import SwiftLintBuiltInRules
@Suite(.rulesRegistered)
struct TypeContentsOrderRuleTests {
@Test
func typeContentsOrderReversedOrder() { // swiftlint:disable:this function_body_length
// Test with reversed `order` entries
let nonTriggeringExamples = [
Example([
@@ -164,8 +167,8 @@ final class TypeContentsOrderRuleTests: SwiftLintTestCase {
)
}
// swiftlint:disable:next function_body_length
func testTypeContentsOrderGroupedOrder() {
@Test
func typeContentsOrderGroupedOrder() { // swiftlint:disable:this function_body_length
// Test with grouped `order` entries
let nonTriggeringExamples = [
Example("""
@@ -1,8 +1,12 @@
@testable import SwiftLintBuiltInRules
import TestHelpers
import Testing
final class TypeNameRuleTests: SwiftLintTestCase {
func testTypeNameWithExcluded() {
@testable import SwiftLintBuiltInRules
@Suite(.rulesRegistered)
struct TypeNameRuleTests {
@Test
func typeNameWithExcluded() {
let baseDescription = TypeNameRule.description
let nonTriggeringExamples = baseDescription.nonTriggeringExamples + [
Example("class apple {}"),
@@ -18,7 +22,8 @@ final class TypeNameRuleTests: SwiftLintTestCase {
verifyRule(description, ruleConfiguration: ["excluded": ["apple", "some.*", ".*st\\d+.*"]])
}
func testTypeNameWithAllowedSymbols() {
@Test
func typeNameWithAllowedSymbols() {
let baseDescription = TypeNameRule.description
let nonTriggeringExamples = baseDescription.nonTriggeringExamples + [
Example("class MyType$ {}"),
@@ -32,7 +37,8 @@ final class TypeNameRuleTests: SwiftLintTestCase {
verifyRule(description, ruleConfiguration: ["allowed_symbols": ["$"]])
}
func testTypeNameWithAllowedSymbolsAndViolation() {
@Test
func typeNameWithAllowedSymbolsAndViolation() {
let baseDescription = TypeNameRule.description
let triggeringExamples = [
Example("class ↓My_Type$ {}")
@@ -42,7 +48,8 @@ final class TypeNameRuleTests: SwiftLintTestCase {
verifyRule(description, ruleConfiguration: ["allowed_symbols": ["$", "%"]])
}
func testTypeNameWithIgnoreStartWithLowercase() {
@Test
func typeNameWithIgnoreStartWithLowercase() {
let baseDescription = TypeNameRule.description
let triggeringExamplesToRemove = [
Example("private typealias ↓foo = Void"),
@@ -1,20 +1,16 @@
@testable import SwiftLintBuiltInRules
import TestHelpers
import XCTest
import Testing
final class TypesafeArrayInitRuleTests: SwiftLintTestCase {
func testViolationRuleIdentifier() {
@testable import SwiftLintBuiltInRules
@Suite(.rulesRegistered)
struct TypesafeArrayInitRuleTests {
@Test
func violationRuleIdentifier() throws {
let baseDescription = TypesafeArrayInitRule.description
guard let triggeringExample = baseDescription.triggeringExamples.first else {
XCTFail("No triggering examples found")
return
}
guard let config = makeConfig(nil, baseDescription.identifier) else {
XCTFail("Failed to create configuration")
return
}
let triggeringExample = try #require(baseDescription.triggeringExamples.first)
let config = try #require(makeConfig(nil, baseDescription.identifier))
let violations = violations(triggeringExample, config: config, requiresFileOnDisk: true)
XCTAssertGreaterThanOrEqual(violations.count, 1)
XCTAssertEqual(violations.first?.ruleIdentifier, baseDescription.identifier)
#expect(violations.first?.ruleIdentifier == baseDescription.identifier)
}
}
@@ -1,8 +1,12 @@
@testable import SwiftLintBuiltInRules
import TestHelpers
import Testing
final class UnneededOverrideRuleTests: SwiftLintTestCase {
func testIncludeAffectInits() {
@testable import SwiftLintBuiltInRules
@Suite(.rulesRegistered)
struct UnneededOverrideRuleTests {
@Test
func includeAffectInits() {
let nonTriggeringExamples = [
Example("""
override init() {
@@ -1,8 +1,11 @@
@testable import SwiftLintBuiltInRules
import XCTest
import Testing
final class UnusedDeclarationConfigurationTests: XCTestCase {
func testParseConfiguration() throws {
@testable import SwiftLintBuiltInRules
@Suite(.rulesRegistered)
struct UnusedDeclarationConfigurationTests {
@Test
func parseConfiguration() throws {
var testee = UnusedDeclarationConfiguration()
let config = [
"severity": "warning",
@@ -12,8 +15,8 @@ final class UnusedDeclarationConfigurationTests: XCTestCase {
try testee.apply(configuration: config)
XCTAssertEqual(testee.severityConfiguration.severity, .warning)
XCTAssertTrue(testee.includePublicAndOpen)
XCTAssertEqual(testee.relatedUSRsToSkip, ["a", "b", "s:7SwiftUI15PreviewProviderP"])
#expect(testee.severityConfiguration.severity == .warning)
#expect(testee.includePublicAndOpen)
#expect(testee.relatedUSRsToSkip == ["a", "b", "s:7SwiftUI15PreviewProviderP"])
}
}
@@ -1,8 +1,12 @@
@testable import SwiftLintBuiltInRules
import TestHelpers
import Testing
final class UnusedOptionalBindingRuleTests: SwiftLintTestCase {
func testDefaultConfiguration() {
@testable import SwiftLintBuiltInRules
@Suite(.rulesRegistered)
struct UnusedOptionalBindingRuleTests {
@Test
func defaultConfiguration() {
let baseDescription = UnusedOptionalBindingRule.description
let triggeringExamples = baseDescription.triggeringExamples + [
Example("guard let _ = try? alwaysThrows() else { return }")
@@ -12,7 +16,8 @@ final class UnusedOptionalBindingRuleTests: SwiftLintTestCase {
verifyRule(description)
}
func testIgnoreOptionalTryEnabled() {
@Test
func ignoreOptionalTryEnabled() {
// Perform additional tests with the ignore_optional_try settings enabled.
let baseDescription = UnusedOptionalBindingRule.description
let nonTriggeringExamples = baseDescription.nonTriggeringExamples + [
@@ -1,11 +1,14 @@
@testable import SwiftLintBuiltInRules
import TestHelpers
import XCTest
import Testing
final class VerticalWhitespaceRuleTests: SwiftLintTestCase {
@testable import SwiftLintBuiltInRules
@Suite(.rulesRegistered)
struct VerticalWhitespaceRuleTests {
private let ruleID = VerticalWhitespaceRule.identifier
func testAttributesWithMaxEmptyLines() {
@Test
func attributesWithMaxEmptyLines() {
// Test with custom `max_empty_lines`
let maxEmptyLinesDescription = VerticalWhitespaceRule.description
.with(nonTriggeringExamples: [Example("let aaaa = 0\n\n\n")])
@@ -15,11 +18,11 @@ final class VerticalWhitespaceRuleTests: SwiftLintTestCase {
])
.with(corrections: [:])
verifyRule(maxEmptyLinesDescription,
ruleConfiguration: ["max_empty_lines": 2])
verifyRule(maxEmptyLinesDescription, ruleConfiguration: ["max_empty_lines": 2])
}
func testAutoCorrectionWithMaxEmptyLines() {
@Test
func autoCorrectionWithMaxEmptyLines() {
let maxEmptyLinesDescription = VerticalWhitespaceRule.description
.with(nonTriggeringExamples: [])
.with(triggeringExamples: [])
@@ -29,32 +32,21 @@ final class VerticalWhitespaceRuleTests: SwiftLintTestCase {
Example("class BB {\n \n \n\n let b = 0\n}\n"): Example("class BB {\n \n \n let b = 0\n}\n"),
])
verifyRule(maxEmptyLinesDescription,
ruleConfiguration: ["max_empty_lines": 2])
verifyRule(maxEmptyLinesDescription, ruleConfiguration: ["max_empty_lines": 2])
}
func testViolationMessageWithMaxEmptyLines() {
guard let config = makeConfig(["max_empty_lines": 2], ruleID) else {
XCTFail("Failed to create configuration")
return
}
@Test
func violationMessageWithMaxEmptyLines() throws {
let config = try #require(makeConfig(["max_empty_lines": 2], ruleID))
let allViolations = violations(Example("let aaaa = 0\n\n\n\nlet bbb = 2\n"), config: config)
let verticalWhiteSpaceViolation = allViolations.first { $0.ruleIdentifier == ruleID }
if let violation = verticalWhiteSpaceViolation {
XCTAssertEqual(violation.reason, "Limit vertical whitespace to maximum 2 empty lines; currently 3")
} else {
XCTFail("A vertical whitespace violation should have been triggered!")
}
let violation = try #require(allViolations.first { $0.ruleIdentifier == ruleID })
#expect(violation.reason == "Limit vertical whitespace to maximum 2 empty lines; currently 3")
}
func testViolationMessageWithDefaultConfiguration() {
@Test
func violationMessageWithDefaultConfiguration() throws {
let allViolations = violations(Example("let aaaa = 0\n\n\n\nlet bbb = 2\n"))
let verticalWhiteSpaceViolation = allViolations.first(where: { $0.ruleIdentifier == ruleID })
if let violation = verticalWhiteSpaceViolation {
XCTAssertEqual(violation.reason, "Limit vertical whitespace to a single empty line; currently 3")
} else {
XCTFail("A vertical whitespace violation should have been triggered!")
}
let violation = try #require(allViolations.first { $0.ruleIdentifier == ruleID })
#expect(violation.reason == "Limit vertical whitespace to a single empty line; currently 3")
}
}
@@ -1,234 +1,265 @@
@testable import SwiftLintBuiltInRules
import TestHelpers
import XCTest
import Testing
final class XCTSpecificMatcherRuleTests: SwiftLintTestCase {
func testEqualTrue() {
@testable import SwiftLintBuiltInRules
@Suite(.rulesRegistered)
struct XCTSpecificMatcherRuleTests {
@Test
func equalTrue() {
let example = Example("XCTAssertEqual(a, true)")
let violations = self.violations(example)
XCTAssertEqual(violations.count, 1)
XCTAssertEqual(violations.first?.reason, "Prefer the specific matcher 'XCTAssertTrue' instead")
#expect(violations.count == 1)
#expect(violations.first?.reason == "Prefer the specific matcher 'XCTAssertTrue' instead")
}
func testEqualFalse() {
@Test
func equalFalse() {
let example = Example("XCTAssertEqual(a, false)")
let violations = self.violations(example)
XCTAssertEqual(violations.count, 1)
XCTAssertEqual(violations.first?.reason, "Prefer the specific matcher 'XCTAssertFalse' instead")
#expect(violations.count == 1)
#expect(violations.first?.reason == "Prefer the specific matcher 'XCTAssertFalse' instead")
}
func testEqualNil() {
@Test
func equalNil() {
let example = Example("XCTAssertEqual(a, nil)")
let violations = self.violations(example)
XCTAssertEqual(violations.count, 1)
XCTAssertEqual(violations.first?.reason, "Prefer the specific matcher 'XCTAssertNil' instead")
#expect(violations.count == 1)
#expect(violations.first?.reason == "Prefer the specific matcher 'XCTAssertNil' instead")
}
func testNotEqualTrue() {
@Test
func notEqualTrue() {
let example = Example("XCTAssertNotEqual(a, true)")
let violations = self.violations(example)
XCTAssertEqual(violations.count, 1)
XCTAssertEqual(violations.first?.reason, "Prefer the specific matcher 'XCTAssertFalse' instead")
#expect(violations.count == 1)
#expect(violations.first?.reason == "Prefer the specific matcher 'XCTAssertFalse' instead")
}
func testNotEqualFalse() {
@Test
func notEqualFalse() {
let example = Example("XCTAssertNotEqual(a, false)")
let violations = self.violations(example)
XCTAssertEqual(violations.count, 1)
XCTAssertEqual(violations.first?.reason, "Prefer the specific matcher 'XCTAssertTrue' instead")
#expect(violations.count == 1)
#expect(violations.first?.reason == "Prefer the specific matcher 'XCTAssertTrue' instead")
}
func testNotEqualNil() {
@Test
func notEqualNil() {
let example = Example("XCTAssertNotEqual(a, nil)")
let violations = self.violations(example)
XCTAssertEqual(violations.count, 1)
XCTAssertEqual(violations.first?.reason, "Prefer the specific matcher 'XCTAssertNotNil' instead")
#expect(violations.count == 1)
#expect(violations.first?.reason == "Prefer the specific matcher 'XCTAssertNotNil' instead")
}
// MARK: - Additional Tests
func testEqualOptionalFalse() {
@Test
func equalOptionalFalse() {
let example = Example("XCTAssertEqual(a?.b, false)")
let violations = self.violations(example)
XCTAssertEqual(violations.count, 0)
#expect(violations.isEmpty)
}
func testEqualUnwrappedOptionalFalse() {
@Test
func equalUnwrappedOptionalFalse() {
let example = Example("XCTAssertEqual(a!.b, false)")
let violations = self.violations(example)
XCTAssertEqual(violations.count, 1)
XCTAssertEqual(violations.first?.reason, "Prefer the specific matcher 'XCTAssertFalse' instead")
#expect(violations.count == 1)
#expect(violations.first?.reason == "Prefer the specific matcher 'XCTAssertFalse' instead")
}
func testEqualNilNil() {
@Test
func equalNilNil() {
let example = Example("XCTAssertEqual(nil, nil)")
let violations = self.violations(example)
XCTAssertEqual(violations.count, 1)
XCTAssertEqual(violations.first?.reason, "Prefer the specific matcher 'XCTAssertNil' instead")
#expect(violations.count == 1)
#expect(violations.first?.reason == "Prefer the specific matcher 'XCTAssertNil' instead")
}
func testEqualTrueTrue() {
@Test
func equalTrueTrue() {
let example = Example("XCTAssertEqual(true, true)")
let violations = self.violations(example)
XCTAssertEqual(violations.count, 1)
XCTAssertEqual(violations.first?.reason, "Prefer the specific matcher 'XCTAssertTrue' instead")
#expect(violations.count == 1)
#expect(violations.first?.reason == "Prefer the specific matcher 'XCTAssertTrue' instead")
}
func testEqualFalseFalse() {
@Test
func equalFalseFalse() {
let example = Example("XCTAssertEqual(false, false)")
let violations = self.violations(example)
XCTAssertEqual(violations.count, 1)
XCTAssertEqual(violations.first?.reason, "Prefer the specific matcher 'XCTAssertFalse' instead")
#expect(violations.count == 1)
#expect(violations.first?.reason == "Prefer the specific matcher 'XCTAssertFalse' instead")
}
func testNotEqualNilNil() {
@Test
func notEqualNilNil() {
let example = Example("XCTAssertNotEqual(nil, nil)")
let violations = self.violations(example)
XCTAssertEqual(violations.count, 1)
XCTAssertEqual(violations.first?.reason, "Prefer the specific matcher 'XCTAssertNotNil' instead")
#expect(violations.count == 1)
#expect(violations.first?.reason == "Prefer the specific matcher 'XCTAssertNotNil' instead")
}
func testNotEqualTrueTrue() {
@Test
func notEqualTrueTrue() {
let example = Example("XCTAssertNotEqual(true, true)")
let violations = self.violations(example)
XCTAssertEqual(violations.count, 1)
XCTAssertEqual(violations.first?.reason, "Prefer the specific matcher 'XCTAssertFalse' instead")
#expect(violations.count == 1)
#expect(violations.first?.reason == "Prefer the specific matcher 'XCTAssertFalse' instead")
}
func testNotEqualFalseFalse() {
@Test
func notEqualFalseFalse() {
let example = Example("XCTAssertNotEqual(false, false)")
let violations = self.violations(example)
XCTAssertEqual(violations.count, 1)
XCTAssertEqual(violations.first?.reason, "Prefer the specific matcher 'XCTAssertTrue' instead")
#expect(violations.count == 1)
#expect(violations.first?.reason == "Prefer the specific matcher 'XCTAssertTrue' instead")
}
func testAssertEqual() {
@Test
func assertEqual() {
let example = Example("XCTAssert(foo == bar)")
let violations = self.violations(example)
XCTAssertEqual(violations.count, 1)
XCTAssertEqual(violations.first?.reason, "Prefer the specific matcher 'XCTAssertEqual' instead")
#expect(violations.count == 1)
#expect(violations.first?.reason == "Prefer the specific matcher 'XCTAssertEqual' instead")
}
func testAssertFalseNotEqual() {
@Test
func assertFalseNotEqual() {
let example = Example("XCTAssertFalse(bar != foo)")
let violations = self.violations(example)
XCTAssertEqual(violations.count, 1)
XCTAssertEqual(violations.first?.reason, "Prefer the specific matcher 'XCTAssertEqual' instead")
#expect(violations.count == 1)
#expect(violations.first?.reason == "Prefer the specific matcher 'XCTAssertEqual' instead")
}
func testAssertTrueEqual() {
@Test
func assertTrueEqual() {
let example = Example("XCTAssertTrue(foo == 1)")
let violations = self.violations(example)
XCTAssertEqual(violations.count, 1)
XCTAssertEqual(violations.first?.reason, "Prefer the specific matcher 'XCTAssertEqual' instead")
#expect(violations.count == 1)
#expect(violations.first?.reason == "Prefer the specific matcher 'XCTAssertEqual' instead")
}
func testAssertNotEqual() {
@Test
func assertNotEqual() {
let example = Example("XCTAssert(foo != bar)")
let violations = self.violations(example)
XCTAssertEqual(violations.count, 1)
XCTAssertEqual(violations.first?.reason, "Prefer the specific matcher 'XCTAssertNotEqual' instead")
#expect(violations.count == 1)
#expect(violations.first?.reason == "Prefer the specific matcher 'XCTAssertNotEqual' instead")
}
func testAssertFalseEqual() {
@Test
func assertFalseEqual() {
let example = Example("XCTAssertFalse(bar == foo)")
let violations = self.violations(example)
XCTAssertEqual(violations.count, 1)
XCTAssertEqual(violations.first?.reason, "Prefer the specific matcher 'XCTAssertNotEqual' instead")
#expect(violations.count == 1)
#expect(violations.first?.reason == "Prefer the specific matcher 'XCTAssertNotEqual' instead")
}
func testAssertTrueNotEqual() {
@Test
func assertTrueNotEqual() {
let example = Example("XCTAssertTrue(foo != 1)")
let violations = self.violations(example)
XCTAssertEqual(violations.count, 1)
XCTAssertEqual(violations.first?.reason, "Prefer the specific matcher 'XCTAssertNotEqual' instead")
#expect(violations.count == 1)
#expect(violations.first?.reason == "Prefer the specific matcher 'XCTAssertNotEqual' instead")
}
func testMultipleComparisons() {
@Test
func multipleComparisons() {
let example = Example("XCTAssert(foo == (bar == baz))")
let violations = self.violations(example)
XCTAssertEqual(violations.count, 1)
XCTAssertEqual(violations.first?.reason, "Prefer the specific matcher 'XCTAssertEqual' instead")
#expect(violations.count == 1)
#expect(violations.first?.reason == "Prefer the specific matcher 'XCTAssertEqual' instead")
}
func testEqualInCommentNotConsidered() {
XCTAssert(noViolation(in: "XCTAssert(foo, \"a == b\")"))
@Test
func equalInCommentNotConsidered() {
#expect(noViolation(in: "XCTAssert(foo, \"a == b\")"))
}
func testEqualInFunctionCall() {
XCTAssert(noViolation(in: "XCTAssert(foo(bar == baz))"))
XCTAssert(noViolation(in: "XCTAssertTrue(foo(bar == baz), \"toto\")"))
@Test
func equalInFunctionCall() {
#expect(noViolation(in: "XCTAssert(foo(bar == baz))"))
#expect(noViolation(in: "XCTAssertTrue(foo(bar == baz), \"toto\")"))
}
// MARK: - Identity Operator Tests
func testAssertIdentical() {
@Test
func assertIdentical() {
let example = Example("XCTAssert(foo === bar)")
let violations = self.violations(example)
XCTAssertEqual(violations.count, 1)
XCTAssertEqual(violations.first?.reason, "Prefer the specific matcher 'XCTAssertIdentical' instead")
#expect(violations.count == 1)
#expect(violations.first?.reason == "Prefer the specific matcher 'XCTAssertIdentical' instead")
}
func testAssertNotIdentical() {
@Test
func assertNotIdentical() {
let example = Example("XCTAssert(foo !== bar)")
let violations = self.violations(example)
XCTAssertEqual(violations.count, 1)
XCTAssertEqual(violations.first?.reason, "Prefer the specific matcher 'XCTAssertNotIdentical' instead")
#expect(violations.count == 1)
#expect(violations.first?.reason == "Prefer the specific matcher 'XCTAssertNotIdentical' instead")
}
func testAssertTrueIdentical() {
@Test
func assertTrueIdentical() {
let example = Example("XCTAssertTrue(foo === bar)")
let violations = self.violations(example)
XCTAssertEqual(violations.count, 1)
XCTAssertEqual(violations.first?.reason, "Prefer the specific matcher 'XCTAssertIdentical' instead")
#expect(violations.count == 1)
#expect(violations.first?.reason == "Prefer the specific matcher 'XCTAssertIdentical' instead")
}
func testAssertTrueNotIdentical() {
@Test
func assertTrueNotIdentical() {
let example = Example("XCTAssertTrue(foo !== bar)")
let violations = self.violations(example)
XCTAssertEqual(violations.count, 1)
XCTAssertEqual(violations.first?.reason, "Prefer the specific matcher 'XCTAssertNotIdentical' instead")
#expect(violations.count == 1)
#expect(violations.first?.reason == "Prefer the specific matcher 'XCTAssertNotIdentical' instead")
}
func testAssertFalseIdentical() {
@Test
func assertFalseIdentical() {
let example = Example("XCTAssertFalse(foo === bar)")
let violations = self.violations(example)
XCTAssertEqual(violations.count, 1)
XCTAssertEqual(violations.first?.reason, "Prefer the specific matcher 'XCTAssertNotIdentical' instead")
#expect(violations.count == 1)
#expect(violations.first?.reason == "Prefer the specific matcher 'XCTAssertNotIdentical' instead")
}
func testAssertFalseNotIdentical() {
@Test
func assertFalseNotIdentical() {
let example = Example("XCTAssertFalse(foo !== bar)")
let violations = self.violations(example)
XCTAssertEqual(violations.count, 1)
XCTAssertEqual(violations.first?.reason, "Prefer the specific matcher 'XCTAssertIdentical' instead")
#expect(violations.count == 1)
#expect(violations.first?.reason == "Prefer the specific matcher 'XCTAssertIdentical' instead")
}
private func violations(_ example: Example) -> [StyleViolation] {
+18 -16
View File
@@ -1,22 +1,24 @@
import SwiftLintCore
import TestHelpers
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)
}
}
@@ -1,10 +1,12 @@
import SwiftLintCore
import SwiftParser
import SwiftSyntax
import XCTest
import Testing
final class CodeIndentingRewriterTests: XCTestCase {
func testIndentDefaultStyle() {
@Suite
struct CodeIndentingRewriterTests {
@Test
func indentDefaultStyle() {
assertIndent(
source: """
if c {
@@ -14,17 +16,18 @@ final class CodeIndentingRewriterTests: XCTestCase {
}
""",
indentedSource: """
if c {
// comment
return 1
// another comment
}
""",
if c {
// comment
return 1
// another comment
}
""",
style: .indentSpaces(4)
)
}
func testIndentThreeSpaces() {
@Test
func indentThreeSpaces() {
assertIndent(
source: """
if c {
@@ -34,17 +37,18 @@ final class CodeIndentingRewriterTests: XCTestCase {
}
""",
indentedSource: """
if c {
// comment
return 1
// another comment
}
""",
if c {
// comment
return 1
// another comment
}
""",
style: .indentSpaces(3)
)
}
func testIndentTabs() {
@Test
func indentTabs() {
assertIndent(
source: """
if c {
@@ -54,17 +58,18 @@ final class CodeIndentingRewriterTests: XCTestCase {
}
""",
indentedSource: """
\tif c {
\t // comment
\t return 1
\t // another comment
\t}
""",
\tif c {
\t // comment
\t return 1
\t // another comment
\t}
""",
style: .indentTabs(1)
)
}
func testIndentCodeBlock() {
@Test
func indentCodeBlock() {
assertIndent(
source: """
// initial comment
@@ -92,15 +97,16 @@ final class CodeIndentingRewriterTests: XCTestCase {
)
}
func testUnindentDefaultStyle() {
@Test
func unindentDefaultStyle() {
assertIndent(
source: """
if c {
// comment
return 1
// another comment
}
""",
if c {
// comment
return 1
// another comment
}
""",
indentedSource: """
if c {
// comment
@@ -112,15 +118,16 @@ final class CodeIndentingRewriterTests: XCTestCase {
)
}
func testUnindentTwoSpaces() {
@Test
func unindentTwoSpaces() {
assertIndent(
source: """
if c {
// comment
return 1
// another comment
}
""",
if c {
// comment
return 1
// another comment
}
""",
indentedSource: """
if c {
// comment
@@ -132,15 +139,16 @@ final class CodeIndentingRewriterTests: XCTestCase {
)
}
func testUnindentTabs() {
@Test
func unindentTabs() {
assertIndent(
source: """
\tif c {
\t\t // comment
\t\treturn 1
\t\t\t// another comment
\t}
""",
\tif c {
\t\t // comment
\t\treturn 1
\t\t\t// another comment
\t}
""",
indentedSource: """
if c {
\t // comment
@@ -154,6 +162,6 @@ final class CodeIndentingRewriterTests: XCTestCase {
private func assertIndent(source: String, indentedSource: String, style: CodeIndentingRewriter.IndentationStyle) {
let rewritten = CodeIndentingRewriter(style: style).rewrite(Parser.parse(source: source))
XCTAssertEqual(rewritten.description, indentedSource)
#expect(rewritten.description == indentedSource)
}
}
+40 -27
View File
@@ -1,35 +1,41 @@
@testable import SwiftLintCore
import XCTest
import SwiftLintCore
import Testing
final class CommentLinesVisitorTests: XCTestCase {
func testEmptyFile() {
XCTAssertEqual(commentOnlyLines(in: ""), [])
@Suite
struct CommentLinesVisitorTests {
@Test
func emptyFile() {
#expect(commentOnlyLines(in: "").isEmpty)
}
func testSingleLineComment() {
XCTAssertEqual(commentOnlyLines(in: "// This is a comment"), [1])
@Test
func singleLineComment() {
#expect(commentOnlyLines(in: "// This is a comment") == [1])
}
func testMultipleSingleLineComments() {
@Test
func multipleSingleLineComments() {
let contents = """
// First comment
// Second comment
// Third comment
"""
XCTAssertEqual(commentOnlyLines(in: contents), [1, 2, 3])
#expect(commentOnlyLines(in: contents) == [1, 2, 3])
}
func testBlockComment() {
@Test
func blockComment() {
let contents = """
/*
* This is a block comment
* spanning multiple lines
*/
"""
XCTAssertEqual(commentOnlyLines(in: contents), [1, 2, 3, 4])
#expect(commentOnlyLines(in: contents) == [1, 2, 3, 4])
}
func testMixedCommentsAndCode() {
@Test
func mixedCommentsAndCode() {
let contents = """
// Comment at the top
import Foundation
@@ -41,29 +47,32 @@ final class CommentLinesVisitorTests: XCTestCase {
}
// Final comment
"""
XCTAssertEqual(commentOnlyLines(in: contents), [1, 4, 6, 9])
#expect(commentOnlyLines(in: contents) == [1, 4, 6, 9])
}
func testCommentsWithWhitespace() {
@Test
func commentsWithWhitespace() {
let contents = """
// Comment with leading spaces
\t// Comment with leading tab
\t // Comment with mixed whitespace
"""
XCTAssertEqual(commentOnlyLines(in: contents), [1, 2, 3])
#expect(commentOnlyLines(in: contents) == [1, 2, 3])
}
func testEmptyLinesIgnored() {
@Test
func emptyLinesIgnored() {
let contents = """
// First comment
// Second comment after empty lines
"""
XCTAssertEqual(commentOnlyLines(in: contents), [1, 4])
#expect(commentOnlyLines(in: contents) == [1, 4])
}
func testDocumentationComments() {
@Test
func documentationComments() {
let contents = """
/// This is a documentation comment
/// for a function
@@ -72,26 +81,29 @@ final class CommentLinesVisitorTests: XCTestCase {
*/
func test() {}
"""
XCTAssertEqual(commentOnlyLines(in: contents), [1, 2, 3, 4, 5])
#expect(commentOnlyLines(in: contents) == [1, 2, 3, 4, 5])
}
func testInlineCommentsNotCounted() {
@Test
func inlineCommentsNotCounted() {
let contents = """
let x = 5 // This comment is on the same line as code
print("test") /* inline block comment */
"""
XCTAssertEqual(commentOnlyLines(in: contents), [])
#expect(commentOnlyLines(in: contents).isEmpty)
}
func testCommentBlockStartedOnCodeLine() {
@Test
func commentBlockStartedOnCodeLine() {
let contents = """
print("test") /* block
comment */
"""
XCTAssertEqual(commentOnlyLines(in: contents), [2])
#expect(commentOnlyLines(in: contents) == [2])
}
func testComplexExample() {
@Test
func complexExample() {
let contents = """
// Header comment
/*
@@ -118,10 +130,11 @@ final class CommentLinesVisitorTests: XCTestCase {
// Trailing comment
"""
XCTAssertEqual(commentOnlyLines(in: contents), [1, 2, 3, 4, 5, 9, 11, 14, 15, 16, 17, 19, 23])
#expect(commentOnlyLines(in: contents) == [1, 2, 3, 4, 5, 9, 11, 14, 15, 16, 17, 19, 23])
}
func testLineNumberAccuracy() {
@Test
func lineNumberAccuracy() {
let contents = """
let x = 1
// Line 2 comment
@@ -132,7 +145,7 @@ final class CommentLinesVisitorTests: XCTestCase {
let z = 3 // Line 7 inline
"""
XCTAssertEqual(commentOnlyLines(in: contents), [2, 4, 5, 6])
#expect(commentOnlyLines(in: contents) == [2, 4, 5, 6])
}
private func commentOnlyLines(in contents: String) -> [Int] {
@@ -1,86 +1,88 @@
@testable import SwiftLintCore
import XCTest
import SwiftLintCore
import Testing
final class ConditionallySourceKitFreeTests: XCTestCase {
// Mock rule for testing ConditionallySourceKitFree protocol
private struct MockConditionalRule: Rule, ConditionallySourceKitFree {
static let description = RuleDescription(
identifier: "mock_conditional",
name: "Mock Conditional Rule",
description: "A mock rule for testing ConditionallySourceKitFree",
kind: .style
)
var configuration = SeverityConfiguration<Self>(.warning)
var isEffectivelySourceKitFree = true
func validate(file _: SwiftLintFile) -> [StyleViolation] {
[]
}
}
private struct MockSourceKitFreeRule: Rule, SourceKitFreeRule {
static let description = RuleDescription(
identifier: "mock_sourcekit_free",
name: "Mock SourceKit Free Rule",
description: "A mock rule that is always SourceKit-free",
kind: .style
)
var configuration = SeverityConfiguration<Self>(.warning)
func validate(file _: SwiftLintFile) -> [StyleViolation] {
[]
}
}
private struct MockRegularRule: Rule {
static let description = RuleDescription(
identifier: "mock_regular",
name: "Mock Regular Rule",
description: "A mock rule that requires SourceKit",
kind: .style
)
var configuration = SeverityConfiguration<Self>(.warning)
func validate(file _: SwiftLintFile) -> [StyleViolation] {
[]
}
}
func testRequiresSourceKitForDifferentRuleTypes() {
@Suite
struct ConditionallySourceKitFreeTests {
@Test
func requiresSourceKitForDifferentRuleTypes() {
// SourceKitFreeRule should not require SourceKit
let sourceKitFreeRule = MockSourceKitFreeRule()
XCTAssertFalse(sourceKitFreeRule.requiresSourceKit)
#expect(!sourceKitFreeRule.requiresSourceKit)
// ConditionallySourceKitFree rule that is effectively SourceKit-free
var conditionalRuleFree = MockConditionalRule()
conditionalRuleFree.isEffectivelySourceKitFree = true
XCTAssertFalse(conditionalRuleFree.requiresSourceKit)
#expect(!conditionalRuleFree.requiresSourceKit)
// ConditionallySourceKitFree rule that requires SourceKit
var conditionalRuleRequires = MockConditionalRule()
conditionalRuleRequires.isEffectivelySourceKitFree = false
XCTAssertTrue(conditionalRuleRequires.requiresSourceKit)
#expect(conditionalRuleRequires.requiresSourceKit)
// Regular rule should require SourceKit
let regularRule = MockRegularRule()
XCTAssertTrue(regularRule.requiresSourceKit)
#expect(regularRule.requiresSourceKit)
}
func testTypeCheckingBehavior() {
@Test
func typeCheckingBehavior() {
// Verify instance-level checks work correctly
let sourceKitFreeRule: any Rule = MockSourceKitFreeRule()
XCTAssertTrue(sourceKitFreeRule is any SourceKitFreeRule)
XCTAssertFalse(sourceKitFreeRule is any ConditionallySourceKitFree)
#expect(sourceKitFreeRule is any SourceKitFreeRule)
#expect(!(sourceKitFreeRule is any ConditionallySourceKitFree))
let conditionalRule: any Rule = MockConditionalRule()
XCTAssertFalse(conditionalRule is any SourceKitFreeRule)
XCTAssertTrue(conditionalRule is any ConditionallySourceKitFree)
#expect(!(conditionalRule is any SourceKitFreeRule))
#expect(conditionalRule is any ConditionallySourceKitFree)
let regularRule: any Rule = MockRegularRule()
XCTAssertFalse(regularRule is any SourceKitFreeRule)
XCTAssertFalse(regularRule is any ConditionallySourceKitFree)
#expect(!(regularRule is any SourceKitFreeRule))
#expect(!(regularRule is any ConditionallySourceKitFree))
}
}
private struct MockConditionalRule: Rule, ConditionallySourceKitFree {
static let description = RuleDescription(
identifier: "mock_conditional",
name: "Mock Conditional Rule",
description: "A mock rule for testing ConditionallySourceKitFree",
kind: .style
)
var configuration = SeverityConfiguration<Self>(.warning)
var isEffectivelySourceKitFree = true
func validate(file _: SwiftLintFile) -> [StyleViolation] {
[]
}
}
private struct MockSourceKitFreeRule: Rule, SourceKitFreeRule {
static let description = RuleDescription(
identifier: "mock_sourcekit_free",
name: "Mock SourceKit Free Rule",
description: "A mock rule that is always SourceKit-free",
kind: .style
)
var configuration = SeverityConfiguration<Self>(.warning)
func validate(file _: SwiftLintFile) -> [StyleViolation] {
[]
}
}
private struct MockRegularRule: Rule {
static let description = RuleDescription(
identifier: "mock_regular",
name: "Mock Regular Rule",
description: "A mock rule that requires SourceKit",
kind: .style
)
var configuration = SeverityConfiguration<Self>(.warning)
func validate(file _: SwiftLintFile) -> [StyleViolation] {
[]
}
}
+52 -99
View File
@@ -1,162 +1,115 @@
import SwiftLintCore
import TestHelpers
import XCTest
import Testing
final class DisableAllTests: SwiftLintTestCase {
@Suite(.rulesRegistered)
struct DisableAllTests {
/// Example violations. Could be replaced with other single violations.
private let violatingPhrases = [
Example("let r = 0"), // Violates identifier_name
Example(#"let myString:String = """#), // Violates colon_whitespace
Example("// TODO: Some todo"), // Violates todo
private static let violatingPhrases = [
Example("let r = 0"), // Violates identifier_name
Example(#"let myString:String = """#), // Violates colon_whitespace
Example("// TODO: Some todo"), // Violates todo
]
// MARK: Violating Phrase
/// Tests whether example violating phrases trigger when not applying disable rule
func testViolatingPhrase() {
for violatingPhrase in violatingPhrases {
XCTAssertEqual(
violations(violatingPhrase.with(code: violatingPhrase.code + "\n")).count,
1,
#function,
file: violatingPhrase.file,
line: violatingPhrase.line)
}
@Test(arguments: violatingPhrases)
func violatingPhrase(_ violatingPhrase: Example) {
#expect(violations(violatingPhrase.with(code: violatingPhrase.code + "\n")).count == 1)
}
// MARK: Enable / Disable Base
/// Tests whether swiftlint:disable all protects properly
func testDisableAll() {
for violatingPhrase in violatingPhrases {
let code = "// swiftlint:disable all\n" + violatingPhrase.code + "\n// swiftlint:enable all\n"
let protectedPhrase = violatingPhrase.with(code: code)
XCTAssertEqual(
violations(protectedPhrase).count,
0,
#function,
file: violatingPhrase.file,
line: violatingPhrase.line)
}
@Test(arguments: violatingPhrases)
func disableAll(_ violatingPhrase: Example) {
let code = "// swiftlint:disable all\n" + violatingPhrase.code + "\n// swiftlint:enable all\n"
let protectedPhrase = violatingPhrase.with(code: code)
#expect(violations(protectedPhrase).isEmpty)
}
/// Tests whether swiftlint:enable all unprotects properly
func testEnableAll() {
for violatingPhrase in violatingPhrases {
let unprotectedPhrase = violatingPhrase.with(code: """
@Test(arguments: violatingPhrases)
func enableAll(_ violatingPhrase: Example) {
let unprotectedPhrase = violatingPhrase.with(
code: """
// swiftlint:disable all
\(violatingPhrase.code)
// swiftlint:enable all
\(violatingPhrase.code)\n
""")
XCTAssertEqual(
violations(unprotectedPhrase).count,
1,
#function,
file: violatingPhrase.file,
line: violatingPhrase.line)
}
#expect(violations(unprotectedPhrase).count == 1)
}
// MARK: Enable / Disable Previous
/// Tests whether swiftlint:disable:previous all protects properly
func testDisableAllPrevious() {
for violatingPhrase in violatingPhrases {
let protectedPhrase = violatingPhrase
.with(code: """
@Test(arguments: violatingPhrases)
func disableAllPrevious(_ violatingPhrase: Example) {
let protectedPhrase =
violatingPhrase
.with(
code: """
\(violatingPhrase.code)
// swiftlint:disable:previous all\n
""")
XCTAssertEqual(
violations(protectedPhrase).count,
0,
#function,
file: violatingPhrase.file,
line: violatingPhrase.line)
}
#expect(violations(protectedPhrase).isEmpty)
}
/// Tests whether swiftlint:enable:previous all unprotects properly
func testEnableAllPrevious() {
for violatingPhrase in violatingPhrases {
let unprotectedPhrase = violatingPhrase.with(code: """
@Test(arguments: violatingPhrases)
func enableAllPrevious(_ violatingPhrase: Example) {
let unprotectedPhrase = violatingPhrase.with(
code: """
// swiftlint:disable all
\(violatingPhrase.code)
\(violatingPhrase.code)
// swiftlint:enable:previous all
// swiftlint:enable all
""")
XCTAssertEqual(
violations(unprotectedPhrase).count,
1,
#function,
file: violatingPhrase.file,
line: violatingPhrase.line)
}
#expect(violations(unprotectedPhrase).count == 1)
}
// MARK: Enable / Disable Next
/// Tests whether swiftlint:disable:next all protects properly
func testDisableAllNext() {
for violatingPhrase in violatingPhrases {
let protectedPhrase = violatingPhrase.with(code: "// swiftlint:disable:next all\n" + violatingPhrase.code)
XCTAssertEqual(
violations(protectedPhrase).count,
0,
#function,
file: violatingPhrase.file,
line: violatingPhrase.line)
}
@Test(arguments: violatingPhrases)
func disableAllNext(_ violatingPhrase: Example) {
let protectedPhrase = violatingPhrase.with(code: "// swiftlint:disable:next all\n" + violatingPhrase.code)
#expect(violations(protectedPhrase).isEmpty)
}
/// Tests whether swiftlint:enable:next all unprotects properly
func testEnableAllNext() {
for violatingPhrase in violatingPhrases {
let unprotectedPhrase = violatingPhrase.with(code: """
@Test(arguments: violatingPhrases)
func enableAllNext(_ violatingPhrase: Example) {
let unprotectedPhrase = violatingPhrase.with(
code: """
// swiftlint:disable all
\(violatingPhrase.code)
// swiftlint:enable:next all
\(violatingPhrase.code)
// swiftlint:enable all
""")
XCTAssertEqual(
violations(unprotectedPhrase).count,
1,
#function,
file: violatingPhrase.file,
line: violatingPhrase.line)
}
#expect(violations(unprotectedPhrase).count == 1)
}
// MARK: Enable / Disable This
/// Tests whether swiftlint:disable:this all protects properly
func testDisableAllThis() {
for violatingPhrase in violatingPhrases {
let rawViolatingPhrase = violatingPhrase.code.replacingOccurrences(of: "\n", with: "")
let protectedPhrase = violatingPhrase.with(code: rawViolatingPhrase + "// swiftlint:disable:this all\n")
XCTAssertEqual(
violations(protectedPhrase).count,
0,
#function,
file: violatingPhrase.file,
line: violatingPhrase.line)
}
@Test(arguments: violatingPhrases)
func disableAllThis(_ violatingPhrase: Example) {
let rawViolatingPhrase = violatingPhrase.code.replacingOccurrences(of: "\n", with: "")
let protectedPhrase = violatingPhrase.with(code: rawViolatingPhrase + "// swiftlint:disable:this all\n")
#expect(violations(protectedPhrase).isEmpty)
}
/// Tests whether swiftlint:enable:next all unprotects properly
func testEnableAllThis() {
for violatingPhrase in violatingPhrases {
let rawViolatingPhrase = violatingPhrase.code.replacingOccurrences(of: "\n", with: "")
let unprotectedPhrase = violatingPhrase.with(code: """
@Test(arguments: violatingPhrases)
func enableAllThis(_ violatingPhrase: Example) {
let rawViolatingPhrase = violatingPhrase.code.replacingOccurrences(of: "\n", with: "")
let unprotectedPhrase = violatingPhrase.with(
code: """
// swiftlint:disable all
\(violatingPhrase.code)
\(rawViolatingPhrase)// swiftlint:enable:this all
// swiftlint:enable all
""")
XCTAssertEqual(
violations(unprotectedPhrase).count,
1,
#function,
file: violatingPhrase.file,
line: violatingPhrase.line)
}
#expect(violations(unprotectedPhrase).count == 1)
}
}
+36 -31
View File
@@ -1,62 +1,67 @@
import SwiftLintCore
import TestHelpers
import XCTest
import SwiftLintFramework
import Testing
final class ExampleTests: SwiftLintTestCase {
func testEquatableDoesNotLookAtFile() {
@Suite
struct ExampleTests {
@Test
func equatableDoesNotLookAtFile() {
let first = Example("foo", file: "a", line: 1)
let second = Example("foo", file: "b", line: 1)
XCTAssertEqual(first, second)
#expect(first == second)
}
func testEquatableDoesNotLookAtLine() {
@Test
func equatableDoesNotLookAtLine() {
let first = Example("foo", file: "a", line: 1)
let second = Example("foo", file: "a", line: 2)
XCTAssertEqual(first, second)
#expect(first == second)
}
func testEquatableLooksAtCode() {
@Test
func equatableLooksAtCode() {
let first = Example("a", file: "a", line: 1)
let second = Example("a", file: "x", line: 2)
let third = Example("c", file: "y", line: 2)
XCTAssertEqual(first, second)
XCTAssertNotEqual(first, third)
#expect(first == second)
#expect(first != third)
}
func testTestMultiByteOffsets() {
XCTAssertTrue(Example("").testMultiByteOffsets)
XCTAssertTrue(Example("", testMultiByteOffsets: true).testMultiByteOffsets)
XCTAssertFalse(Example("", testMultiByteOffsets: false).testMultiByteOffsets)
@Test
func testMultiByteOffsets() {
#expect(Example("").testMultiByteOffsets)
#expect(Example("", testMultiByteOffsets: true).testMultiByteOffsets)
#expect(!Example("", testMultiByteOffsets: false).testMultiByteOffsets)
}
func testTestOnLinux() {
XCTAssertTrue(Example("").testOnLinux)
XCTAssertTrue(Example("", testOnLinux: true).testOnLinux)
XCTAssertFalse(Example("", testOnLinux: false).testOnLinux)
@Test
func testOnLinux() {
#expect(Example("").testOnLinux)
#expect(Example("", testOnLinux: true).testOnLinux)
#expect(!Example("", testOnLinux: false).testOnLinux)
}
func testRemovingViolationMarkers() {
@Test
func removingViolationMarkers() {
let example = Example("↓T↓E↓S↓T")
XCTAssertEqual(example.removingViolationMarkers(), Example("TEST"))
#expect(example.removingViolationMarkers() == Example("TEST"))
}
func testComparable() {
XCTAssertLessThan(Example("a"), Example("b"))
@Test
func comparable() {
#expect(Example("a") < Example("b"))
}
func testWithCode() {
@Test
func withCode() {
let original = Example("original code")
XCTAssertNotNil(original.file)
XCTAssertNotNil(original.line)
#expect(original.code == "original code")
let new = original.with(code: "new code")
XCTAssertEqual(new.code, "new code")
XCTAssertNotNil(new.file)
XCTAssertNotNil(new.line)
#expect(new.code == "new code")
// When modifying the code, it's important that the file and line
// numbers remain intact
XCTAssertEqual(new.file.description, original.file.description)
XCTAssertEqual(new.line, original.line)
#expect(new.file.description == original.file.description)
#expect(new.line == original.line)
}
}
+8 -7
View File
@@ -1,9 +1,10 @@
import SourceKittenFramework
import TestHelpers
import XCTest
import Testing
final class ExtendedNSStringTests: SwiftLintTestCase {
func testLineAndCharacterForByteOffset_forContentsContainingMultibyteCharacters() {
@Suite
struct ExtendedNSStringTests {
@Test
func lineAndCharacterForByteOffset_forContentsContainingMultibyteCharacters() {
let contents = "" +
"import Foundation\n" + // 18 characters
"class Test {\n" + // 13 characters
@@ -14,10 +15,10 @@ final class ExtendedNSStringTests: SwiftLintTestCase {
"}"
// A character placed on 80 offset indicates a white-space before 'do' at 5th line.
if let lineAndCharacter = StringView(contents).lineAndCharacter(forCharacterOffset: 80) {
XCTAssertEqual(lineAndCharacter.line, 5)
XCTAssertEqual(lineAndCharacter.character, 3)
#expect(lineAndCharacter.line == 5)
#expect(lineAndCharacter.character == 3)
} else {
XCTFail("NSString.lineAndCharacterForByteOffset should return non-nil tuple.")
Issue.record("NSString.lineAndCharacterForByteOffset should return non-nil tuple.")
}
}
}
+8 -7
View File
@@ -1,10 +1,11 @@
import TestHelpers
import XCTest
import Testing
final class ExtendedStringTests: SwiftLintTestCase {
func testCountOccurrences() {
XCTAssertEqual("aabbabaaba".countOccurrences(of: "a"), 6)
XCTAssertEqual("".countOccurrences(of: "a"), 0)
XCTAssertEqual("\n\n".countOccurrences(of: "\n"), 2)
@Suite
struct ExtendedStringTests {
@Test
func countOccurrences() {
#expect("aabbabaaba".countOccurrences(of: "a") == 6)
#expect("".countOccurrences(of: "a") == 0)
#expect("\n\n".countOccurrences(of: "\n") == 2)
}
}
+8 -6
View File
@@ -1,14 +1,16 @@
import SwiftLintCore
import TestHelpers
import XCTest
import Testing
final class LineEndingTests: SwiftLintTestCase {
func testCarriageReturnDoesNotCauseError() {
XCTAssert(
@Suite
struct LineEndingTests {
@Test
func carriageReturnDoesNotCauseError() {
#expect(
violations(
Example(
"// swiftlint:disable:next blanket_disable_command\r\n" +
"// swiftlint:disable all\r\nprint(123)\r\n"
"// swiftlint:disable:next blanket_disable_command\r\n"
+ "// swiftlint:disable all\r\nprint(123)\r\n"
)
).isEmpty
)
+33 -26
View File
@@ -1,25 +1,29 @@
@testable import SwiftLintCore
import SwiftLintCore
import TestHelpers
import XCTest
import Testing
final class RegexConfigurationTests: SwiftLintTestCase {
func testShouldValidateIsTrueByDefault() {
@Suite
struct RegexConfigurationTests {
@Test
func shouldValidateIsTrueByDefault() {
let config = RegexConfiguration<RuleMock>(identifier: "example")
XCTAssertTrue(config.shouldValidate(filePath: "App/file.swift"))
#expect(config.shouldValidate(filePath: "App/file.swift"))
}
func testShouldValidateWithSingleExluded() throws {
@Test
func shouldValidateWithSingleExluded() throws {
var config = RegexConfiguration<RuleMock>(identifier: "example")
try config.apply(configuration: [
"regex": "try!",
"excluded": "Tests/.*\\.swift",
])
XCTAssertFalse(config.shouldValidate(filePath: "Tests/file.swift"))
XCTAssertTrue(config.shouldValidate(filePath: "App/file.swift"))
#expect(!config.shouldValidate(filePath: "Tests/file.swift"))
#expect(config.shouldValidate(filePath: "App/file.swift"))
}
func testShouldValidateWithArrayExluded() throws {
@Test
func shouldValidateWithArrayExluded() throws {
var config = RegexConfiguration<RuleMock>(identifier: "example")
try config.apply(configuration: [
"regex": "try!",
@@ -29,24 +33,26 @@ final class RegexConfigurationTests: SwiftLintTestCase {
] as Any,
])
XCTAssertFalse(config.shouldValidate(filePath: "Tests/file.swift"))
XCTAssertFalse(config.shouldValidate(filePath: "MyFramework/Tests/file.swift"))
XCTAssertTrue(config.shouldValidate(filePath: "App/file.swift"))
#expect(!config.shouldValidate(filePath: "Tests/file.swift"))
#expect(!config.shouldValidate(filePath: "MyFramework/Tests/file.swift"))
#expect(config.shouldValidate(filePath: "App/file.swift"))
}
func testShouldValidateWithSingleIncluded() throws {
@Test
func shouldValidateWithSingleIncluded() throws {
var config = RegexConfiguration<RuleMock>(identifier: "example")
try config.apply(configuration: [
"regex": "try!",
"included": "App/.*\\.swift",
])
XCTAssertFalse(config.shouldValidate(filePath: "Tests/file.swift"))
XCTAssertFalse(config.shouldValidate(filePath: "MyFramework/Tests/file.swift"))
XCTAssertTrue(config.shouldValidate(filePath: "App/file.swift"))
#expect(!config.shouldValidate(filePath: "Tests/file.swift"))
#expect(!config.shouldValidate(filePath: "MyFramework/Tests/file.swift"))
#expect(config.shouldValidate(filePath: "App/file.swift"))
}
func testShouldValidateWithArrayIncluded() throws {
@Test
func shouldValidateWithArrayIncluded() throws {
var config = RegexConfiguration<RuleMock>(identifier: "example")
try config.apply(configuration: [
"regex": "try!",
@@ -56,12 +62,13 @@ final class RegexConfigurationTests: SwiftLintTestCase {
] as Any,
])
XCTAssertFalse(config.shouldValidate(filePath: "Tests/file.swift"))
XCTAssertTrue(config.shouldValidate(filePath: "App/file.swift"))
XCTAssertTrue(config.shouldValidate(filePath: "MyFramework/file.swift"))
#expect(!config.shouldValidate(filePath: "Tests/file.swift"))
#expect(config.shouldValidate(filePath: "App/file.swift"))
#expect(config.shouldValidate(filePath: "MyFramework/file.swift"))
}
func testShouldValidateWithIncludedAndExcluded() throws {
@Test
func shouldValidateWithIncludedAndExcluded() throws {
var config = RegexConfiguration<RuleMock>(identifier: "example")
try config.apply(configuration: [
"regex": "try!",
@@ -75,11 +82,11 @@ final class RegexConfigurationTests: SwiftLintTestCase {
] as Any,
])
XCTAssertTrue(config.shouldValidate(filePath: "App/file.swift"))
XCTAssertTrue(config.shouldValidate(filePath: "MyFramework/file.swift"))
#expect(config.shouldValidate(filePath: "App/file.swift"))
#expect(config.shouldValidate(filePath: "MyFramework/file.swift"))
XCTAssertFalse(config.shouldValidate(filePath: "App/Fixtures/file.swift"))
XCTAssertFalse(config.shouldValidate(filePath: "Tests/file.swift"))
XCTAssertFalse(config.shouldValidate(filePath: "MyFramework/Tests/file.swift"))
#expect(!config.shouldValidate(filePath: "App/Fixtures/file.swift"))
#expect(!config.shouldValidate(filePath: "Tests/file.swift"))
#expect(!config.shouldValidate(filePath: "MyFramework/Tests/file.swift"))
}
}
+74 -58
View File
@@ -1,79 +1,89 @@
import SwiftLintCore
import TestHelpers
import XCTest
import Testing
final class RegionTests: SwiftLintTestCase {
// MARK: Regions From Files
func testNoRegionsInEmptyFile() {
@Suite
struct RegionTests {
@Test
func noRegionsInEmptyFile() {
let file = SwiftLintFile(contents: "")
XCTAssertEqual(file.regions(), [])
#expect(file.regions().isEmpty)
}
func testNoRegionsInFileWithNoCommands() {
@Test
func noRegionsInFileWithNoCommands() {
let file = SwiftLintFile(contents: String(repeating: "\n", count: 100))
XCTAssertEqual(file.regions(), [])
#expect(file.regions().isEmpty)
}
func testRegionsFromSingleCommand() {
@Test
func regionsFromSingleCommand() {
// disable
do {
let file = SwiftLintFile(contents: "// swiftlint:disable rule_id\n")
let start = Location(file: nil, line: 1, character: 29)
let end = Location(file: nil, line: .max, character: .max)
XCTAssertEqual(file.regions(), [Region(start: start, end: end, disabledRuleIdentifiers: ["rule_id"])])
#expect(file.regions() == [Region(start: start, end: end, disabledRuleIdentifiers: ["rule_id"])])
}
// enable
do {
let file = SwiftLintFile(contents: "// swiftlint:enable rule_id\n")
let start = Location(file: nil, line: 1, character: 28)
let end = Location(file: nil, line: .max, character: .max)
XCTAssertEqual(file.regions(), [Region(start: start, end: end, disabledRuleIdentifiers: [])])
#expect(file.regions() == [Region(start: start, end: end, disabledRuleIdentifiers: [])])
}
}
func testRegionsFromMatchingPairCommands() {
@Test
func regionsFromMatchingPairCommands() {
// disable/enable
do {
let file = SwiftLintFile(contents: "// swiftlint:disable rule_id\n// swiftlint:enable rule_id\n")
XCTAssertEqual(file.regions(), [
Region(start: Location(file: nil, line: 1, character: 29),
end: Location(file: nil, line: 2, character: 27),
disabledRuleIdentifiers: ["rule_id"]),
Region(start: Location(file: nil, line: 2, character: 28),
end: Location(file: nil, line: .max, character: .max),
disabledRuleIdentifiers: []),
#expect(file.regions() == [
Region(
start: Location(file: nil, line: 1, character: 29),
end: Location(file: nil, line: 2, character: 27),
disabledRuleIdentifiers: ["rule_id"]),
Region(
start: Location(file: nil, line: 2, character: 28),
end: Location(file: nil, line: .max, character: .max),
disabledRuleIdentifiers: []),
])
}
// enable/disable
do {
let file = SwiftLintFile(contents: "// swiftlint:enable rule_id\n// swiftlint:disable rule_id\n")
XCTAssertEqual(file.regions(), [
Region(start: Location(file: nil, line: 1, character: 28),
end: Location(file: nil, line: 2, character: 28),
disabledRuleIdentifiers: []),
Region(start: Location(file: nil, line: 2, character: 29),
end: Location(file: nil, line: .max, character: .max),
disabledRuleIdentifiers: ["rule_id"]),
#expect(file.regions() == [
Region(
start: Location(file: nil, line: 1, character: 28),
end: Location(file: nil, line: 2, character: 28),
disabledRuleIdentifiers: []),
Region(
start: Location(file: nil, line: 2, character: 29),
end: Location(file: nil, line: .max, character: .max),
disabledRuleIdentifiers: ["rule_id"]),
])
}
}
func testRegionsFromThreeCommandForSingleLine() {
let file = SwiftLintFile(contents: "// swiftlint:disable:next 1\n" +
"// swiftlint:disable:this 2\n" +
"// swiftlint:disable:previous 3\n")
XCTAssertEqual(file.regions(), [
Region(start: Location(file: nil, line: 2, character: nil),
end: Location(file: nil, line: 2, character: .max - 1),
disabledRuleIdentifiers: ["1", "2", "3"]),
Region(start: Location(file: nil, line: 2, character: .max),
end: Location(file: nil, line: .max, character: .max),
disabledRuleIdentifiers: []),
@Test
func regionsFromThreeCommandForSingleLine() {
let file = SwiftLintFile(
contents: "// swiftlint:disable:next 1\n" + "// swiftlint:disable:this 2\n"
+ "// swiftlint:disable:previous 3\n")
#expect(file.regions() == [
Region(
start: Location(file: nil, line: 2, character: nil),
end: Location(file: nil, line: 2, character: .max - 1),
disabledRuleIdentifiers: ["1", "2", "3"]),
Region(
start: Location(file: nil, line: 2, character: .max),
end: Location(file: nil, line: .max, character: .max),
disabledRuleIdentifiers: []),
])
}
func testSeveralRegionsFromSeveralCommands() {
@Test
func severalRegionsFromSeveralCommands() {
let file = SwiftLintFile(contents: """
// swiftlint:disable 1
// swiftlint:disable 2
@@ -83,25 +93,31 @@ final class RegionTests: SwiftLintTestCase {
// swiftlint:enable 3
"""
)
XCTAssertEqual(file.regions(), [
Region(start: Location(file: nil, line: 1, character: 23),
end: Location(file: nil, line: 2, character: 22),
disabledRuleIdentifiers: ["1"]),
Region(start: Location(file: nil, line: 2, character: 23),
end: Location(file: nil, line: 3, character: 22),
disabledRuleIdentifiers: ["1", "2"]),
Region(start: Location(file: nil, line: 3, character: 23),
end: Location(file: nil, line: 4, character: 21),
disabledRuleIdentifiers: ["1", "2", "3"]),
Region(start: Location(file: nil, line: 4, character: 22),
end: Location(file: nil, line: 5, character: 21),
disabledRuleIdentifiers: ["2", "3"]),
Region(start: Location(file: nil, line: 5, character: 22),
end: Location(file: nil, line: 6, character: 21),
disabledRuleIdentifiers: ["3"]),
Region(start: Location(file: nil, line: 6, character: 22),
end: Location(file: nil, line: .max, character: .max),
disabledRuleIdentifiers: []),
#expect(file.regions() == [
Region(
start: Location(file: nil, line: 1, character: 23),
end: Location(file: nil, line: 2, character: 22),
disabledRuleIdentifiers: ["1"]),
Region(
start: Location(file: nil, line: 2, character: 23),
end: Location(file: nil, line: 3, character: 22),
disabledRuleIdentifiers: ["1", "2"]),
Region(
start: Location(file: nil, line: 3, character: 23),
end: Location(file: nil, line: 4, character: 21),
disabledRuleIdentifiers: ["1", "2", "3"]),
Region(
start: Location(file: nil, line: 4, character: 22),
end: Location(file: nil, line: 5, character: 21),
disabledRuleIdentifiers: ["2", "3"]),
Region(
start: Location(file: nil, line: 5, character: 22),
end: Location(file: nil, line: 6, character: 21),
disabledRuleIdentifiers: ["3"]),
Region(
start: Location(file: nil, line: 6, character: 22),
end: Location(file: nil, line: .max, character: .max),
disabledRuleIdentifiers: []),
])
}
}
@@ -1,21 +1,21 @@
@testable import SwiftLintCore
import TestHelpers
import XCTest
import Testing
// swiftlint:disable file_length
// swiftlint:disable:next type_body_length
final class RuleConfigurationDescriptionTests: SwiftLintTestCase {
@Suite
struct RuleConfigurationDescriptionTests { // swiftlint:disable:this type_body_length
@AutoConfigParser
private struct TestConfiguration: RuleConfiguration {
typealias Parent = RuleMock // swiftlint:disable:this nesting
typealias Parent = RuleMock // swiftlint:disable:this nesting
@ConfigurationElement(key: "flag")
var flag = true
@ConfigurationElement(key: "string")
var string = "value"
@ConfigurationElement(key: "symbol")
var symbol = try! Symbol(fromAny: "value", context: "rule") // swiftlint:disable:this force_try
var symbol = try! Symbol(fromAny: "value", context: "rule") // swiftlint:disable:this force_try
@ConfigurationElement(key: "integer")
var integer = 2
@ConfigurationElement(key: "null")
@@ -45,186 +45,190 @@ final class RuleConfigurationDescriptionTests: SwiftLintTestCase {
func isEqualTo(_: some RuleConfiguration) -> Bool { false }
}
// swiftlint:disable:next function_body_length
func testDescriptionFromConfiguration() throws {
@Test
func descriptionFromConfiguration() throws { // swiftlint:disable:this function_body_length
var configuration = TestConfiguration()
try configuration.apply(configuration: Void()) // Configure to set keys.
try configuration.apply(configuration: Void()) // Configure to set keys.
let description = RuleConfigurationDescription.from(configuration: configuration)
XCTAssertEqual(description.oneLiner(), """
flag: true; \
string: "value"; \
symbol: value; \
integer: 2; \
my_double: 2.1; \
severity: warning; \
list: ["STRING1", "STRING2"]; \
set: [1, 2, 3]; \
set_of_doubles: [1.0, 2.0, 3.0, 4.7]; \
severity: error; \
SEVERITY: warning; \
warning: 1; \
levels: warning: 3, error: 2
""")
#expect(
description.oneLiner() == """
flag: true; \
string: "value"; \
symbol: value; \
integer: 2; \
my_double: 2.1; \
severity: warning; \
list: ["STRING1", "STRING2"]; \
set: [1, 2, 3]; \
set_of_doubles: [1.0, 2.0, 3.0, 4.7]; \
severity: error; \
SEVERITY: warning; \
warning: 1; \
levels: warning: 3, error: 2
""")
XCTAssertEqual(description.markdown(), """
<table>
<thead>
<tr><th>Key</th><th>Value</th></tr>
</thead>
<tbody>
<tr>
<td>
flag
</td>
<td>
true
</td>
</tr>
<tr>
<td>
string
</td>
<td>
&quot;value&quot;
</td>
</tr>
<tr>
<td>
symbol
</td>
<td>
value
</td>
</tr>
<tr>
<td>
integer
</td>
<td>
2
</td>
</tr>
<tr>
<td>
my_double
</td>
<td>
2.1
</td>
</tr>
<tr>
<td>
severity
</td>
<td>
warning
</td>
</tr>
<tr>
<td>
list
</td>
<td>
[&quot;STRING1&quot;, &quot;STRING2&quot;]
</td>
</tr>
<tr>
<td>
set
</td>
<td>
[1, 2, 3]
</td>
</tr>
<tr>
<td>
set_of_doubles
</td>
<td>
[1.0, 2.0, 3.0, 4.7]
</td>
</tr>
<tr>
<td>
severity
</td>
<td>
error
</td>
</tr>
<tr>
<td>
SEVERITY
</td>
<td>
warning
</td>
</tr>
<tr>
<td>
warning
</td>
<td>
1
</td>
</tr>
<tr>
<td>
levels
</td>
<td>
<table>
<thead>
<tr><th>Key</th><th>Value</th></tr>
</thead>
<tbody>
<tr>
<td>
warning
</td>
<td>
3
</td>
</tr>
<tr>
<td>
error
</td>
<td>
2
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
""")
#expect(
description.markdown() == """
<table>
<thead>
<tr><th>Key</th><th>Value</th></tr>
</thead>
<tbody>
<tr>
<td>
flag
</td>
<td>
true
</td>
</tr>
<tr>
<td>
string
</td>
<td>
&quot;value&quot;
</td>
</tr>
<tr>
<td>
symbol
</td>
<td>
value
</td>
</tr>
<tr>
<td>
integer
</td>
<td>
2
</td>
</tr>
<tr>
<td>
my_double
</td>
<td>
2.1
</td>
</tr>
<tr>
<td>
severity
</td>
<td>
warning
</td>
</tr>
<tr>
<td>
list
</td>
<td>
[&quot;STRING1&quot;, &quot;STRING2&quot;]
</td>
</tr>
<tr>
<td>
set
</td>
<td>
[1, 2, 3]
</td>
</tr>
<tr>
<td>
set_of_doubles
</td>
<td>
[1.0, 2.0, 3.0, 4.7]
</td>
</tr>
<tr>
<td>
severity
</td>
<td>
error
</td>
</tr>
<tr>
<td>
SEVERITY
</td>
<td>
warning
</td>
</tr>
<tr>
<td>
warning
</td>
<td>
1
</td>
</tr>
<tr>
<td>
levels
</td>
<td>
<table>
<thead>
<tr><th>Key</th><th>Value</th></tr>
</thead>
<tbody>
<tr>
<td>
warning
</td>
<td>
3
</td>
</tr>
<tr>
<td>
error
</td>
<td>
2
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
""")
XCTAssertEqual(description.yaml(), """
flag: true
string: "value"
symbol: value
integer: 2
my_double: 2.1
severity: warning
list: ["STRING1", "STRING2"]
set: [1, 2, 3]
set_of_doubles: [1.0, 2.0, 3.0, 4.7]
severity: error
SEVERITY: warning
warning: 1
levels:
warning: 3
error: 2
""")
#expect(
description.yaml() == """
flag: true
string: "value"
symbol: value
integer: 2
my_double: 2.1
severity: warning
list: ["STRING1", "STRING2"]
set: [1, 2, 3]
set_of_doubles: [1.0, 2.0, 3.0, 4.7]
severity: error
SEVERITY: warning
warning: 1
levels:
warning: 3
error: 2
""")
}
func testPrefersParameterDescription() {
@Test
func prefersParameterDescription() {
struct Config: RuleConfiguration {
typealias Parent = RuleMock // swiftlint:disable:this nesting
typealias Parent = RuleMock // swiftlint:disable:this nesting
var parameterDescription: RuleConfigurationDescription? {
"visible" => .flag(true)
@@ -233,43 +237,45 @@ final class RuleConfigurationDescriptionTests: SwiftLintTestCase {
@ConfigurationElement(key: "invisible")
var invisible = true
mutating func apply(configuration _: Any) throws(Issue) { /* conformance for test */ }
mutating func apply(configuration _: Any) throws(SwiftLintCore.Issue) { /* conformance for test */ }
func isEqualTo(_: some RuleConfiguration) -> Bool { false }
}
let description = RuleConfigurationDescription.from(configuration: Config())
XCTAssertEqual(description.oneLiner(), "visible: true")
XCTAssertEqual(description.markdown(), """
<table>
<thead>
<tr><th>Key</th><th>Value</th></tr>
</thead>
<tbody>
<tr>
<td>
visible
</td>
<td>
true
</td>
</tr>
</tbody>
</table>
""")
XCTAssertEqual(description.yaml(), "visible: true")
#expect(description.oneLiner() == "visible: true")
#expect(
description.markdown() == """
<table>
<thead>
<tr><th>Key</th><th>Value</th></tr>
</thead>
<tbody>
<tr>
<td>
visible
</td>
<td>
true
</td>
</tr>
</tbody>
</table>
""")
#expect(description.yaml() == "visible: true")
}
func testEmptyDescription() {
@Test
func emptyDescription() {
let description = description { RuleConfigurationOption.noOptions }
XCTAssertTrue(description.oneLiner().isEmpty)
XCTAssertTrue(description.markdown().isEmpty)
XCTAssertTrue(description.yaml().isEmpty)
#expect(description.oneLiner().isEmpty)
#expect(description.markdown().isEmpty)
#expect(description.yaml().isEmpty)
}
// swiftlint:disable:next function_body_length
func testBasicTypes() {
@Test
func basicTypes() { // swiftlint:disable:this function_body_length
let description = description {
"flag" => .flag(true)
"string" => .string("value")
@@ -280,196 +286,205 @@ final class RuleConfigurationDescriptionTests: SwiftLintTestCase {
"list" => .list([.symbol("value"), .string("value"), .float(12.8)])
}
XCTAssertEqual(description.markdown(), """
<table>
<thead>
<tr><th>Key</th><th>Value</th></tr>
</thead>
<tbody>
<tr>
<td>
flag
</td>
<td>
true
</td>
</tr>
<tr>
<td>
string
</td>
<td>
&quot;value&quot;
</td>
</tr>
<tr>
<td>
symbol
</td>
<td>
value
</td>
</tr>
<tr>
<td>
integer
</td>
<td>
-12
</td>
</tr>
<tr>
<td>
float
</td>
<td>
42.0
</td>
</tr>
<tr>
<td>
severity
</td>
<td>
error
</td>
</tr>
<tr>
<td>
list
</td>
<td>
[value, &quot;value&quot;, 12.8]
</td>
</tr>
</tbody>
</table>
""")
#expect(
description.markdown() == """
<table>
<thead>
<tr><th>Key</th><th>Value</th></tr>
</thead>
<tbody>
<tr>
<td>
flag
</td>
<td>
true
</td>
</tr>
<tr>
<td>
string
</td>
<td>
&quot;value&quot;
</td>
</tr>
<tr>
<td>
symbol
</td>
<td>
value
</td>
</tr>
<tr>
<td>
integer
</td>
<td>
-12
</td>
</tr>
<tr>
<td>
float
</td>
<td>
42.0
</td>
</tr>
<tr>
<td>
severity
</td>
<td>
error
</td>
</tr>
<tr>
<td>
list
</td>
<td>
[value, &quot;value&quot;, 12.8]
</td>
</tr>
</tbody>
</table>
""")
XCTAssertEqual(description.oneLiner(), """
flag: true; string: "value"; symbol: value; integer: -12; float: 42.0; \
severity: error; list: [value, "value", 12.8]
""")
#expect(
description.oneLiner() == """
flag: true; string: "value"; symbol: value; integer: -12; float: 42.0; \
severity: error; list: [value, "value", 12.8]
""")
XCTAssertEqual(description.yaml(), """
flag: true
string: "value"
symbol: value
integer: -12
float: 42.0
severity: error
list: [value, "value", 12.8]
""")
#expect(
description.yaml() == """
flag: true
string: "value"
symbol: value
integer: -12
float: 42.0
severity: error
list: [value, "value", 12.8]
""")
}
// swiftlint:disable:next function_body_length
func testNestedDescription() {
@Test
func nestedDescription() { // swiftlint:disable:this function_body_length
let description = description {
"flag" => .flag(true)
"nested 1" => .nest {
"integer" => .integer(2)
"nested 2" => .nest {
"float" => .float(42.1)
"nested 1"
=> .nest {
"integer" => .integer(2)
"nested 2"
=> .nest {
"float" => .float(42.1)
}
"symbol" => .symbol("value")
}
"symbol" => .symbol("value")
}
"string" => .string("value")
}
XCTAssertEqual(description.markdown(), """
<table>
<thead>
<tr><th>Key</th><th>Value</th></tr>
</thead>
<tbody>
<tr>
<td>
flag
</td>
<td>
true
</td>
</tr>
<tr>
<td>
nested 1
</td>
<td>
<table>
<thead>
<tr><th>Key</th><th>Value</th></tr>
</thead>
<tbody>
<tr>
<td>
integer
</td>
<td>
2
</td>
</tr>
<tr>
<td>
nested 2
</td>
<td>
<table>
<thead>
<tr><th>Key</th><th>Value</th></tr>
</thead>
<tbody>
<tr>
<td>
float
</td>
<td>
42.1
</td>
</tr>
</tbody>
</table>
</td>
</tr>
<tr>
<td>
symbol
</td>
<td>
value
</td>
</tr>
</tbody>
</table>
</td>
</tr>
<tr>
<td>
string
</td>
<td>
&quot;value&quot;
</td>
</tr>
</tbody>
</table>
""")
#expect(
description.markdown() == """
<table>
<thead>
<tr><th>Key</th><th>Value</th></tr>
</thead>
<tbody>
<tr>
<td>
flag
</td>
<td>
true
</td>
</tr>
<tr>
<td>
nested 1
</td>
<td>
<table>
<thead>
<tr><th>Key</th><th>Value</th></tr>
</thead>
<tbody>
<tr>
<td>
integer
</td>
<td>
2
</td>
</tr>
<tr>
<td>
nested 2
</td>
<td>
<table>
<thead>
<tr><th>Key</th><th>Value</th></tr>
</thead>
<tbody>
<tr>
<td>
float
</td>
<td>
42.1
</td>
</tr>
</tbody>
</table>
</td>
</tr>
<tr>
<td>
symbol
</td>
<td>
value
</td>
</tr>
</tbody>
</table>
</td>
</tr>
<tr>
<td>
string
</td>
<td>
&quot;value&quot;
</td>
</tr>
</tbody>
</table>
""")
XCTAssertEqual(description.oneLiner(), """
flag: true; nested 1: integer: 2, nested 2: float: 42.1, symbol: value; string: "value"
""")
#expect(
description.oneLiner() == """
flag: true; nested 1: integer: 2, nested 2: float: 42.1, symbol: value; string: "value"
""")
XCTAssertEqual(description.yaml(), """
flag: true
nested 1:
integer: 2
nested 2:
float: 42.1
symbol: value
string: "value"
""")
#expect(
description.yaml() == """
flag: true
nested 1:
integer: 2
nested 2:
float: 42.1
symbol: value
string: "value"
""")
}
func testUpdate() throws {
@Test
func update() throws {
var configuration = TestConfiguration()
try configuration.apply(configuration: [
@@ -487,41 +502,44 @@ final class RuleConfigurationDescriptionTests: SwiftLintTestCase {
"levels": ["warning": 6, "error": 7],
])
XCTAssertFalse(configuration.flag)
XCTAssertEqual(configuration.string, "new value")
XCTAssertEqual(configuration.symbol, try Symbol(fromAny: "new symbol", context: "rule"))
XCTAssertEqual(configuration.integer, 5)
XCTAssertEqual(configuration.null, 0)
XCTAssertEqual(configuration.myDouble, 5.1)
XCTAssertEqual(configuration.severity, .error)
XCTAssertEqual(configuration.list, ["STRING3", "STRING4"])
XCTAssertEqual(configuration.set, [4, 5, 6])
XCTAssertEqual(configuration.severityConfig, .error)
XCTAssertEqual(configuration.renamedSeverityConfig, .error)
XCTAssertEqual(configuration.inlinedSeverityLevels, SeverityLevelsConfiguration(warning: 12))
XCTAssertEqual(configuration.nestedSeverityLevels, SeverityLevelsConfiguration(warning: 6, error: 7))
#expect(!configuration.flag)
#expect(configuration.string == "new value")
#expect(configuration.symbol == (try Symbol(fromAny: "new symbol", context: "rule")))
#expect(configuration.integer == 5)
#expect(configuration.null == 0)
#expect(configuration.myDouble == 5.1)
#expect(configuration.severity == .error)
#expect(configuration.list == ["STRING3", "STRING4"])
#expect(configuration.set == [4, 5, 6])
#expect(configuration.severityConfig == .error)
#expect(configuration.renamedSeverityConfig == .error)
#expect(configuration.inlinedSeverityLevels == SeverityLevelsConfiguration(warning: 12))
#expect(configuration.nestedSeverityLevels == SeverityLevelsConfiguration(warning: 6, error: 7))
}
func testDeprecationWarning() async throws {
@Test
func deprecationWarning() async throws {
let console = try await Issue.captureConsole {
var configuration = TestConfiguration()
try configuration.apply(configuration: ["set": [6, 7]])
}
XCTAssertEqual(
console,
"warning: Configuration option 'set' in 'my_rule' rule is deprecated. Use the option 'other_opt' instead."
#expect(console == """
warning: Configuration option 'set' in 'my_rule' rule is deprecated. Use the option 'other_opt' instead.
"""
)
}
func testNoDeprecationWarningIfNoDeprecatedPropertySet() async throws {
@Test
func noDeprecationWarningIfNoDeprecatedPropertySet() async throws {
let console = try await Issue.captureConsole {
var configuration = TestConfiguration()
try configuration.apply(configuration: ["flag": false])
}
XCTAssertTrue(console.isEmpty)
#expect(console.isEmpty)
}
func testInvalidKeys() async throws {
@Test
func invalidKeys() async throws {
let console = try await Issue.captureConsole {
var configuration = TestConfiguration()
try configuration.apply(configuration: [
@@ -531,9 +549,9 @@ final class RuleConfigurationDescriptionTests: SwiftLintTestCase {
"unsupported": true,
])
}
XCTAssertEqual(
console,
"warning: Configuration for 'RuleMock' rule contains the invalid key(s) 'unknown', 'unsupported'."
#expect(
console
== "warning: Configuration for 'RuleMock' rule contains the invalid key(s) 'unknown', 'unsupported'."
)
}
+72 -36
View File
@@ -1,15 +1,37 @@
import SwiftLintCore
import TestHelpers
import XCTest
import Testing
final class RuleTests: SwiftLintTestCase {
struct RuleWithLevelsMock: Rule {
var configuration = SeverityLevelsConfiguration<Self>(warning: 2, error: 3)
static let description = RuleDescription(
identifier: "severity_level_mock",
name: "",
description: "",
kind: .style,
deprecatedAliases: ["mock"]
)
init() { /* conformance for test */ }
init(configuration: Any) throws {
self.init()
try self.configuration.apply(configuration: configuration)
}
func validate(file _: SwiftLintFile) -> [StyleViolation] { [] }
}
@Suite
struct RuleTests {
fileprivate struct RuleMock1: Rule {
var configuration = SeverityConfiguration<Self>(.warning)
var configurationDescription: some Documentable { RuleConfigurationOption.noOptions }
static let description = RuleDescription(identifier: "RuleMock1", name: "",
description: "", kind: .style)
static let description = RuleDescription(
identifier: "RuleMock1", name: "",
description: "", kind: .style
)
init() { /* conformance for test */ }
init() { /* conformance for test */ }
init(configuration _: Any) throws { self.init() }
func validate(file _: SwiftLintFile) -> [StyleViolation] {
@@ -20,10 +42,12 @@ final class RuleTests: SwiftLintTestCase {
fileprivate struct RuleMock2: Rule {
var configuration = SeverityConfiguration<Self>(.warning)
var configurationDescription: some Documentable { RuleConfigurationOption.noOptions }
static let description = RuleDescription(identifier: "RuleMock2", name: "",
description: "", kind: .style)
static let description = RuleDescription(
identifier: "RuleMock2", name: "",
description: "", kind: .style
)
init() { /* conformance for test */ }
init() { /* conformance for test */ }
init(configuration _: Any) throws { self.init() }
func validate(file _: SwiftLintFile) -> [StyleViolation] {
@@ -34,11 +58,13 @@ final class RuleTests: SwiftLintTestCase {
fileprivate struct RuleWithLevelsMock2: Rule {
var configuration = SeverityLevelsConfiguration<Self>(warning: 2, error: 3)
static let description = RuleDescription(identifier: "violation_level_mock2",
name: "",
description: "", kind: .style)
static let description = RuleDescription(
identifier: "violation_level_mock2",
name: "",
description: "", kind: .style
)
init() { /* conformance for test */ }
init() { /* conformance for test */ }
init(configuration: Any) throws {
self.init()
try self.configuration.apply(configuration: configuration)
@@ -47,79 +73,89 @@ final class RuleTests: SwiftLintTestCase {
func validate(file _: SwiftLintFile) -> [StyleViolation] { [] }
}
func testRuleIsEqualTo() {
XCTAssertTrue(RuleMock1().isEqualTo(RuleMock1()))
@Test
func ruleIsEqualTo() {
#expect(RuleMock1().isEqualTo(RuleMock1()))
}
func testRuleIsNotEqualTo() {
XCTAssertFalse(RuleMock1().isEqualTo(RuleMock2()))
@Test
func ruleIsNotEqualTo() {
#expect(!RuleMock1().isEqualTo(RuleMock2()))
}
func testRuleArraysWithDifferentCountsNotEqual() {
// swiftlint:disable:next xct_specific_matcher
XCTAssertFalse([RuleMock1(), RuleMock2()] == [RuleMock1()])
@Test
func ruleArraysWithDifferentCountsNotEqual() {
#expect(!([RuleMock1(), RuleMock2()] == [RuleMock1()]))
}
func testSeverityLevelRuleInitsWithConfigDictionary() {
@Test
func severityLevelRuleInitsWithConfigDictionary() {
let config = ["warning": 17, "error": 7]
let rule = try? RuleWithLevelsMock(configuration: config)
var comp = RuleWithLevelsMock()
comp.configuration.warning = 17
comp.configuration.error = 7
XCTAssertEqual(rule?.isEqualTo(comp), true)
#expect(rule?.isEqualTo(comp) == true)
}
func testSeverityLevelRuleInitsWithWarningOnlyConfigDictionary() {
@Test
func severityLevelRuleInitsWithWarningOnlyConfigDictionary() {
let config = ["warning": 17]
let rule = try? RuleWithLevelsMock(configuration: config)
var comp = RuleWithLevelsMock()
comp.configuration.warning = 17
comp.configuration.error = nil
XCTAssertEqual(rule?.isEqualTo(comp), true)
#expect(rule?.isEqualTo(comp) == true)
}
func testSeverityLevelRuleInitsWithErrorOnlyConfigDictionary() {
@Test
func severityLevelRuleInitsWithErrorOnlyConfigDictionary() {
let config = ["error": 17]
let rule = try? RuleWithLevelsMock(configuration: config)
var comp = RuleWithLevelsMock()
comp.configuration.error = 17
XCTAssertEqual(rule?.isEqualTo(comp), true)
#expect(rule?.isEqualTo(comp) == true)
}
func testSeverityLevelRuleInitsWithConfigArray() {
@Test
func severityLevelRuleInitsWithConfigArray() {
let config = [17, 7] as Any
let rule = try? RuleWithLevelsMock(configuration: config)
var comp = RuleWithLevelsMock()
comp.configuration.warning = 17
comp.configuration.error = 7
XCTAssertEqual(rule?.isEqualTo(comp), true)
#expect(rule?.isEqualTo(comp) == true)
}
func testSeverityLevelRuleInitsWithSingleValueConfigArray() {
@Test
func severityLevelRuleInitsWithSingleValueConfigArray() {
let config = [17] as Any
let rule = try? RuleWithLevelsMock(configuration: config)
var comp = RuleWithLevelsMock()
comp.configuration.warning = 17
comp.configuration.error = nil
XCTAssertEqual(rule?.isEqualTo(comp), true)
#expect(rule?.isEqualTo(comp) == true)
}
func testSeverityLevelRuleInitsWithLiteral() {
@Test
func severityLevelRuleInitsWithLiteral() {
let config = 17 as Any
let rule = try? RuleWithLevelsMock(configuration: config)
var comp = RuleWithLevelsMock()
comp.configuration.warning = 17
comp.configuration.error = nil
XCTAssertEqual(rule?.isEqualTo(comp), true)
#expect(rule?.isEqualTo(comp) == true)
}
func testSeverityLevelRuleNotEqual() {
@Test
func severityLevelRuleNotEqual() {
let config = 17 as Any
let rule = try? RuleWithLevelsMock(configuration: config)
XCTAssertEqual(rule?.isEqualTo(RuleWithLevelsMock()), false)
#expect(rule?.isEqualTo(RuleWithLevelsMock()) == false)
}
func testDifferentSeverityLevelRulesNotEqual() {
XCTAssertFalse(RuleWithLevelsMock().isEqualTo(RuleWithLevelsMock2()))
@Test
func differentSeverityLevelRulesNotEqual() {
#expect(!RuleWithLevelsMock().isEqualTo(RuleWithLevelsMock2()))
}
}
@@ -1,6 +1,6 @@
@testable import SwiftLintCore
import TestHelpers
import XCTest
import Testing
struct MockSeverityLevelsRule: Rule {
static let identifier = "test_severity_levels"
@@ -18,149 +18,166 @@ struct MockSeverityLevelsRule: Rule {
}
}
final class SeverityLevelsConfigurationTests: SwiftLintTestCase {
func testInitializationWithWarningOnly() {
@Suite
struct SeverityLevelsConfigurationTests {
@Test
func initializationWithWarningOnly() {
let config = SeverityLevelsConfiguration<MockSeverityLevelsRule>(warning: 10)
XCTAssertEqual(config.warning, 10)
XCTAssertNil(config.error)
#expect(config.warning == 10)
#expect(config.error == nil)
let params = config.params
XCTAssertEqual(params.count, 1)
XCTAssertEqual(params[0].severity, .warning)
XCTAssertEqual(params[0].value, 10)
#expect(params.count == 1)
#expect(params[0].severity == .warning)
#expect(params[0].value == 10)
}
func testInitializationWithWarningAndError() {
@Test
func initializationWithWarningAndError() {
let config = SeverityLevelsConfiguration<MockSeverityLevelsRule>(warning: 10, error: 20)
XCTAssertEqual(config.warning, 10)
XCTAssertEqual(config.error, 20)
#expect(config.warning == 10)
#expect(config.error == 20)
let params = config.params
XCTAssertEqual(params.count, 2)
XCTAssertEqual(params[0].severity, .error)
XCTAssertEqual(params[0].value, 20)
XCTAssertEqual(params[1].severity, .warning)
XCTAssertEqual(params[1].value, 10)
#expect(params.count == 2)
#expect(params[0].severity == .error)
#expect(params[0].value == 20)
#expect(params[1].severity == .warning)
#expect(params[1].value == 10)
}
func testApplyConfigurationWithSingleElementArray() throws {
@Test
func applyConfigurationWithSingleElementArray() throws {
var config = SeverityLevelsConfiguration<MockSeverityLevelsRule>(warning: 0, error: 0)
try config.apply(configuration: [15])
XCTAssertEqual(config.warning, 15)
XCTAssertNil(config.error)
#expect(config.warning == 15)
#expect(config.error == nil)
}
func testApplyConfigurationWithTwoElementArray() throws {
@Test
func applyConfigurationWithTwoElementArray() throws {
var config = SeverityLevelsConfiguration<MockSeverityLevelsRule>(warning: 0, error: 0)
try config.apply(configuration: [10, 25])
XCTAssertEqual(config.warning, 10)
XCTAssertEqual(config.error, 25)
#expect(config.warning == 10)
#expect(config.error == 25)
}
func testApplyConfigurationWithMultipleElementArray() throws {
@Test
func applyConfigurationWithMultipleElementArray() throws {
var config = SeverityLevelsConfiguration<MockSeverityLevelsRule>(warning: 0, error: 0)
try config.apply(configuration: [10, 25, 50])
XCTAssertEqual(config.warning, 10)
XCTAssertEqual(config.error, 25) // Only first two elements are used
#expect(config.warning == 10)
#expect(config.error == 25) // Only first two elements are used // Only first two elements are used
}
func testApplyConfigurationWithEmptyArray() {
@Test
func applyConfigurationWithEmptyArray() {
var config = SeverityLevelsConfiguration<MockSeverityLevelsRule>(warning: 12, error: nil)
checkError(Issue.nothingApplied(ruleID: MockSeverityLevelsRule.identifier)) {
#expect(throws: Issue.nothingApplied(ruleID: MockSeverityLevelsRule.identifier)) {
try config.apply(configuration: [] as [Int])
}
}
func testApplyConfigurationWithInvalidArrayType() {
@Test
func applyConfigurationWithInvalidArrayType() {
var config = SeverityLevelsConfiguration<MockSeverityLevelsRule>(warning: 12, error: nil)
checkError(Issue.nothingApplied(ruleID: MockSeverityLevelsRule.identifier)) {
#expect(throws: Issue.nothingApplied(ruleID: MockSeverityLevelsRule.identifier)) {
try config.apply(configuration: ["invalid"])
}
}
func testApplyConfigurationWithWarningOnlyDictionary() throws {
@Test
func applyConfigurationWithWarningOnlyDictionary() throws {
var config = SeverityLevelsConfiguration<MockSeverityLevelsRule>(warning: 0, error: 0)
try config.apply(configuration: ["warning": 15])
XCTAssertEqual(config.warning, 15)
XCTAssertNil(config.error)
#expect(config.warning == 15)
#expect(config.error == nil)
}
func testApplyConfigurationWithWarningAndErrorDictionary() throws {
@Test
func applyConfigurationWithWarningAndErrorDictionary() throws {
var config = SeverityLevelsConfiguration<MockSeverityLevelsRule>(warning: 0, error: 0)
try config.apply(configuration: ["warning": 10, "error": 25])
XCTAssertEqual(config.warning, 10)
XCTAssertEqual(config.error, 25)
#expect(config.warning == 10)
#expect(config.error == 25)
}
func testApplyConfigurationWithErrorOnlyDictionary() throws {
@Test
func applyConfigurationWithErrorOnlyDictionary() throws {
var config = SeverityLevelsConfiguration<MockSeverityLevelsRule>(warning: 12, error: nil)
try config.apply(configuration: ["error": 25])
XCTAssertEqual(config.warning, 12) // Should remain unchanged
XCTAssertEqual(config.error, 25)
#expect(config.warning == 12) // Should remain unchanged // Should remain unchanged
#expect(config.error == 25)
}
func testApplyConfigurationWithNilErrorDictionary() throws {
@Test
func applyConfigurationWithNilErrorDictionary() throws {
var config = SeverityLevelsConfiguration<MockSeverityLevelsRule>(warning: 10, error: 20)
try config.apply(configuration: ["error": nil as Int?])
XCTAssertEqual(config.warning, 10)
XCTAssertNil(config.error)
#expect(config.warning == 10)
#expect(config.error == nil)
}
func testApplyConfigurationWithWarningSetToNilError() throws {
@Test
func applyConfigurationWithWarningSetToNilError() throws {
var config = SeverityLevelsConfiguration<MockSeverityLevelsRule>(warning: 10, error: 20)
try config.apply(configuration: ["warning": 15])
XCTAssertEqual(config.warning, 15)
XCTAssertNil(config.error) // Should be set to nil when warning is specified without error
#expect(config.warning == 15)
#expect(config.error == nil) // Should be set to nil when warning is specified without error
}
func testApplyConfigurationWithInvalidWarningType() {
@Test
func applyConfigurationWithInvalidWarningType() {
var config = SeverityLevelsConfiguration<MockSeverityLevelsRule>(warning: 12, error: nil)
checkError(Issue.invalidConfiguration(ruleID: MockSeverityLevelsRule.identifier)) {
#expect(throws: Issue.invalidConfiguration(ruleID: MockSeverityLevelsRule.identifier)) {
try config.apply(configuration: ["warning": "invalid"])
}
}
func testApplyConfigurationWithInvalidErrorType() {
@Test
func applyConfigurationWithInvalidErrorType() {
var config = SeverityLevelsConfiguration<MockSeverityLevelsRule>(warning: 12, error: nil)
checkError(Issue.invalidConfiguration(ruleID: MockSeverityLevelsRule.identifier)) {
#expect(throws: Issue.invalidConfiguration(ruleID: MockSeverityLevelsRule.identifier)) {
try config.apply(configuration: ["error": "invalid"])
}
}
func testApplyConfigurationWithInvalidConfigurationType() {
@Test
func applyConfigurationWithInvalidConfigurationType() {
var config = SeverityLevelsConfiguration<MockSeverityLevelsRule>(warning: 12, error: nil)
checkError(Issue.nothingApplied(ruleID: MockSeverityLevelsRule.identifier)) {
#expect(throws: Issue.nothingApplied(ruleID: MockSeverityLevelsRule.identifier)) {
try config.apply(configuration: "invalid")
}
}
func testApplyConfigurationWithEmptyDictionary() throws {
@Test
func applyConfigurationWithEmptyDictionary() throws {
var config = SeverityLevelsConfiguration<MockSeverityLevelsRule>(warning: 12, error: 15)
try config.apply(configuration: [:] as [String: Any])
XCTAssertEqual(config.warning, 12)
XCTAssertEqual(config.error, 15) // Should remain unchanged when nothing is applied
#expect(config.warning == 12)
#expect(config.error == 15) // Should remain unchanged when nothing is applied
}
}
+38 -34
View File
@@ -1,48 +1,52 @@
import TestHelpers
import XCTest
import Testing
final class StringExtensionTests: SwiftLintTestCase {
func testRelativePathExpression() {
XCTAssertEqual("Folder/Test", "Root/Folder/Test".path(relativeTo: "Root"))
XCTAssertEqual("Test", "Root/Folder/Test".path(relativeTo: "Root/Folder"))
XCTAssertEqual("", "Root/Folder/Test".path(relativeTo: "Root/Folder/Test"))
XCTAssertEqual("../Test", "Root/Folder/Test".path(relativeTo: "Root/Folder/SubFolder"))
XCTAssertEqual("../..", "Root".path(relativeTo: "Root/Folder/SubFolder"))
XCTAssertEqual("../../OtherFolder/Test", "Root/OtherFolder/Test".path(relativeTo: "Root/Folder/SubFolder"))
XCTAssertEqual("../MyFolder123", "Folder/MyFolder123".path(relativeTo: "Folder/MyFolder"))
XCTAssertEqual("../MyFolder123", "Folder/MyFolder123".path(relativeTo: "Folder/MyFolder/"))
XCTAssertEqual("Test", "Root////Folder///Test/".path(relativeTo: "Root//Folder////"))
XCTAssertEqual("Root/Folder/Test", "Root/Folder/Test/".path(relativeTo: ""))
@Suite
struct StringExtensionTests {
@Test
func relativePathExpression() {
#expect("Folder/Test" == "Root/Folder/Test".path(relativeTo: "Root"))
#expect("Test" == "Root/Folder/Test".path(relativeTo: "Root/Folder"))
#expect("" == "Root/Folder/Test".path(relativeTo: "Root/Folder/Test"))
#expect("../Test" == "Root/Folder/Test".path(relativeTo: "Root/Folder/SubFolder"))
#expect("../.." == "Root".path(relativeTo: "Root/Folder/SubFolder"))
#expect("../../OtherFolder/Test" == "Root/OtherFolder/Test".path(relativeTo: "Root/Folder/SubFolder"))
#expect("../MyFolder123" == "Folder/MyFolder123".path(relativeTo: "Folder/MyFolder"))
#expect("../MyFolder123" == "Folder/MyFolder123".path(relativeTo: "Folder/MyFolder/"))
#expect("Test" == "Root////Folder///Test/".path(relativeTo: "Root//Folder////"))
#expect("Root/Folder/Test" == "Root/Folder/Test/".path(relativeTo: ""))
}
func testIndent() {
XCTAssertEqual("string".indent(by: 3), " string")
XCTAssertEqual(" string".indent(by: 2), " string")
XCTAssertEqual("""
@Test
func indent() {
#expect("string".indent(by: 3) == " string")
#expect(" string".indent(by: 2) == " string")
#expect(
"""
1
2
3
""".indent(by: 2), """
1
2
3
"""
""".indent(by: 2) == """
1
2
3
"""
)
}
func testCharacterPosition() {
XCTAssertNil("string".characterPosition(of: -1))
XCTAssertEqual("string".characterPosition(of: 0), 0)
XCTAssertEqual("string".characterPosition(of: 1), 1)
XCTAssertNil("string".characterPosition(of: 6))
XCTAssertNil("string".characterPosition(of: 7))
@Test
func characterPosition() {
#expect("string".characterPosition(of: -1) == nil)
#expect("string".characterPosition(of: 0) == 0)
#expect("string".characterPosition(of: 1) == 1)
#expect("string".characterPosition(of: 6) == nil)
#expect("string".characterPosition(of: 7) == nil)
XCTAssertEqual("s🤵🏼‍♀️s".characterPosition(of: 0), 0)
XCTAssertEqual("s🤵🏼‍♀️s".characterPosition(of: 1), 1)
#expect("s🤵🏼‍♀️s".characterPosition(of: 0) == 0)
#expect("s🤵🏼‍♀️s".characterPosition(of: 1) == 1)
for bytes in 2...17 {
XCTAssertNil("s🤵🏼‍♀️s".characterPosition(of: bytes))
#expect("s🤵🏼‍♀️s".characterPosition(of: bytes) == nil)
}
XCTAssertEqual("s🤵🏼‍♀️s".characterPosition(of: 18), 2)
XCTAssertNil("s🤵🏼‍♀️s".characterPosition(of: 19))
#expect("s🤵🏼‍♀️s".characterPosition(of: 18) == 2)
#expect("s🤵🏼‍♀️s".characterPosition(of: 19) == nil)
}
}
+39 -29
View File
@@ -1,69 +1,79 @@
@testable import SwiftLintCore
import TestHelpers
import XCTest
import Foundation
import Testing
final class SwiftLintFileTests: SwiftLintTestCase {
@testable import SwiftLintCore
@Suite
final class SwiftLintFileTests {
private let tempFile = FileManager.default.temporaryDirectory.appendingPathComponent(UUID().uuidString)
override func setUp() async throws {
try await super.setUp()
init() throws {
try Data("let i = 2".utf8).write(to: tempFile)
}
override func tearDown() async throws {
try FileManager.default.removeItem(at: tempFile)
try await super.tearDown()
deinit {
do {
try FileManager.default.removeItem(at: tempFile)
} catch {
Issue.record("Failed to remove temporary file: \(error)")
}
}
func testFileFromStringUpdate() {
@Test
func fileFromStringUpdate() {
let file = SwiftLintFile(contents: "let i = 1")
XCTAssertTrue(file.isVirtual)
XCTAssertNil(file.path)
XCTAssertEqual(file.contents, "let i = 1")
#expect(file.isVirtual)
#expect(file.path == nil)
#expect(file.contents == "let i = 1")
file.write("let j = 2")
XCTAssertEqual(file.contents, "let j = 2")
#expect(file.contents == "let j = 2")
file.append("2")
XCTAssertEqual(file.contents, "let j = 22")
#expect(file.contents == "let j = 22")
}
func testFileUpdate() throws {
@Test
func fileUpdate() throws {
let file = SwiftLintFile(path: tempFile.path)!
XCTAssertFalse(file.isVirtual)
XCTAssertNotNil(file.path)
XCTAssertEqual(file.contents, "let i = 2")
#expect(!file.isVirtual)
#expect(file.path != nil)
#expect(file.contents == "let i = 2")
file.write("let j = 2")
XCTAssertEqual(file.contents, "let j = 2")
XCTAssertEqual(FileManager.default.contents(atPath: tempFile.path), Data("let j = 2".utf8))
#expect(file.contents == "let j = 2")
#expect(FileManager.default.contents(atPath: tempFile.path) == Data("let j = 2".utf8))
file.append("2")
XCTAssertEqual(file.contents, "let j = 22")
XCTAssertEqual(FileManager.default.contents(atPath: tempFile.path), Data("let j = 22".utf8))
#expect(file.contents == "let j = 22")
#expect(FileManager.default.contents(atPath: tempFile.path) == Data("let j = 22".utf8))
}
func testFileNotTouchedIfNothingAppended() throws {
@Test
func fileNotTouchedIfNothingAppended() throws {
let file = SwiftLintFile(path: tempFile.path)!
let initialModificationData = FileManager.default.modificationDate(forFileAtPath: tempFile.path)
let initialModificationData = FileManager.default.modificationDate(
forFileAtPath: tempFile.path)
file.append("")
XCTAssertEqual(initialModificationData, FileManager.default.modificationDate(forFileAtPath: tempFile.path))
#expect(initialModificationData == FileManager.default.modificationDate(forFileAtPath: tempFile.path))
}
func testFileNotTouchedIfNothingNewWritten() throws {
@Test
func fileNotTouchedIfNothingNewWritten() throws {
let file = SwiftLintFile(path: tempFile.path)!
let initialModificationData = FileManager.default.modificationDate(forFileAtPath: tempFile.path)
let initialModificationData = FileManager.default.modificationDate(
forFileAtPath: tempFile.path)
file.write("let i = 2")
XCTAssertEqual(initialModificationData, FileManager.default.modificationDate(forFileAtPath: tempFile.path))
#expect(initialModificationData == FileManager.default.modificationDate(forFileAtPath: tempFile.path))
}
}
+29 -34
View File
@@ -1,42 +1,37 @@
import Foundation
import TestHelpers
import XCTest
import Testing
import Yams
final class YamlSwiftLintTests: SwiftLintTestCase {
func testFlattenYaml() throws {
do {
guard let yamlDict = try Yams.load(yaml: try getTestYaml()) as? [String: Any] else {
XCTFail("Failed to load YAML from file")
return
}
let dict1 = (yamlDict["dictionary1"] as? [Swift.String: Any])!
let dict2 = (yamlDict["dictionary2"] as? [Swift.String: Any])!
XCTAssertTrue(dict1["bool"] as? Bool == true && dict2["bool"] as? Bool == true)
XCTAssertTrue(dict1["int"] as? Int == 1 && dict2["int"] as? Int == 1)
XCTAssertTrue(dict1["double"] as? Double == 1.0 && dict2["double"] as? Double == 1.0)
XCTAssertTrue(dict1["string"] as? String == "string" &&
dict2["string"] as? String == "string")
let array1 = (dict1["array"] as? [Any])!
let array2 = (dict1["array"] as? [Any])!
XCTAssertTrue(array1[0] as? Bool == true && array2[0] as? Bool == true)
XCTAssertTrue(array1[1] as? Int == 1 && array2[1] as? Int == 1)
XCTAssertTrue(array1[2] as? Double == 1.0 && array2[2] as? Double == 1.0)
XCTAssertTrue(array1[3] as? String == "string" && array2[3] as? String == "string")
let dictFromArray1 = (array1[4] as? [Swift.String: Any])!
let dictFromArray2 = (array2[4] as? [Swift.String: Any])!
XCTAssertTrue(dictFromArray1["bool"] as? Bool == true && dictFromArray2["bool"] as? Bool == true)
XCTAssertTrue(dictFromArray1["int"] as? Int == 1 && dictFromArray2["int"] as? Int == 1)
XCTAssertTrue(dictFromArray1["double"] as? Double == 1.0 &&
dictFromArray2["double"] as? Double == 1.0)
XCTAssertTrue(dictFromArray1["string"] as? String == "string" &&
dictFromArray2["string"] as? String == "string")
} catch {
XCTFail(error.localizedDescription)
@Suite
struct YamlSwiftLintTests {
@Test
func flattenYaml() throws {
guard let yamlDict = try Yams.load(yaml: try getTestYaml()) as? [String: Any] else {
Issue.record("Failed to load YAML from file")
return
}
let dict1 = (yamlDict["dictionary1"] as? [Swift.String: Any])!
let dict2 = (yamlDict["dictionary2"] as? [Swift.String: Any])!
#expect(dict1["bool"] as? Bool == true && dict2["bool"] as? Bool == true)
#expect(dict1["int"] as? Int == 1 && dict2["int"] as? Int == 1)
#expect(dict1["double"] as? Double == 1.0 && dict2["double"] as? Double == 1.0)
#expect(dict1["string"] as? String == "string" && dict2["string"] as? String == "string")
let array1 = (dict1["array"] as? [Any])!
let array2 = (dict1["array"] as? [Any])!
#expect(array1[0] as? Bool == true && array2[0] as? Bool == true)
#expect(array1[1] as? Int == 1 && array2[1] as? Int == 1)
#expect(array1[2] as? Double == 1.0 && array2[2] as? Double == 1.0)
#expect(array1[3] as? String == "string" && array2[3] as? String == "string")
let dictFromArray1 = (array1[4] as? [Swift.String: Any])!
let dictFromArray2 = (array2[4] as? [Swift.String: Any])!
#expect(dictFromArray1["bool"] as? Bool == true && dictFromArray2["bool"] as? Bool == true)
#expect(dictFromArray1["int"] as? Int == 1 && dictFromArray2["int"] as? Int == 1)
#expect(dictFromArray1["double"] as? Double == 1.0 && dictFromArray2["double"] as? Double == 1.0)
#expect(dictFromArray1["string"] as? String == "string" && dictFromArray2["string"] as? String == "string")
}
private func getTestYaml() throws -> String {
+1 -14
View File
@@ -7,26 +7,13 @@ filegroup(
visibility = ["//visibility:public"],
)
genrule(
name = "ExtraRulesLinuxMain",
outs = ["main.swift"],
cmd = """
echo "import XCTest
XCTMain([testCase(ExtraRulesTests.allTests)])" >> $(OUTS)
""",
)
swift_library(
name = "ExtraRulesTests.library",
package_name = "SwiftLint",
testonly = True,
srcs = [
"ExtraRulesTests.swift",
] + select({
"@platforms//os:linux": [":ExtraRulesLinuxMain"],
"//conditions:default": [],
}),
],
copts = STRICT_COPTS,
module_name = "ExtraRulesTests",
visibility = ["//visibility:public"],
+7 -9
View File
@@ -1,16 +1,14 @@
@testable import SwiftLintExtraRules
import TestHelpers
import Testing
final class ExtraRulesTests: SwiftLintTestCase, @unchecked Sendable {
func testWithDefaultConfiguration() {
@testable import SwiftLintExtraRules
@Suite
struct ExtraRulesTests {
@Test
func withDefaultConfiguration() {
for ruleType in extraRules() {
verifyRule(ruleType.description)
}
}
}
extension ExtraRulesTests {
static var allTests: [(String, (ExtraRulesTests) -> () throws -> Void)] {
[("testWithDefaultConfiguration", testWithDefaultConfiguration)]
}
}
+71 -81
View File
@@ -1,45 +1,37 @@
@testable import SwiftLintBuiltInRules
import XCTest
import Foundation
import TestHelpers
import Testing
@testable import SwiftLintBuiltInRules
@testable import SwiftLintCore
private var temporaryDirectoryPath: String {
let result = URL(
fileURLWithPath: NSTemporaryDirectory(),
isDirectory: true
).path
// swiftlint:disable:next blanket_disable_command
// swiftlint:disable contains_over_filter_is_empty
#if os(macOS)
return "/private" + result
#else
return result
#endif
}
final class BaselineTests: XCTestCase {
extension FileSystemAccessTestSuite.BaselineTests {
private static let example = """
import Foundation
import SwiftLintFramework
import Foundation
import SwiftLintFramework
class Example: NSObject {
private var foo: Int
private var bar: String
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
}
"""
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,
@@ -56,46 +48,40 @@ final class BaselineTests: XCTestCase {
Baseline(violations: ruleDescriptions.violations(for: filePath))
}
private nonisolated(unsafe) static var currentDirectoryPath: String?
override static func setUp() {
super.setUp()
currentDirectoryPath = FileManager.default.currentDirectoryPath
XCTAssertTrue(FileManager.default.changeCurrentDirectoryPath(temporaryDirectoryPath))
}
override static func tearDown() {
XCTAssertTrue(FileManager.default.changeCurrentDirectoryPath(currentDirectoryPath!))
super.tearDown()
}
func testWritingAndReading() throws {
@Test
@TemporaryDirectory
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
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)).isEmpty)
}
}
func testShiftedViolations() throws {
@Test
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).isEmpty)
}
}
func testNewViolation() throws {
@Test
func newViolation() throws {
try testViolationDetection(
violationRuleDescriptions: Self.ruleDescriptions,
newViolationRuleDescription: EmptyCollectionLiteralRule.description,
@@ -103,7 +89,15 @@ final class BaselineTests: XCTestCase {
)
}
func testViolationDetection() throws {
@Test(
arguments: [
ArrayInitRule.description,
BlockBasedKVORule.description,
ClosingBraceRule.description,
DirectReturnRule.description,
]
)
func violationDetection(_ ruleDescription: RuleDescription) throws {
let violationRuleDescriptions = [
ArrayInitRule.description,
BlockBasedKVORule.description,
@@ -117,36 +111,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
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)))
}
}
@@ -170,14 +158,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))
@@ -191,7 +181,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) ?? []

Some files were not shown because too many files have changed in this diff Show More