Files
SwiftFormat/Tests/Rules/TestSuiteAccessControlTests.swift

818 lines
20 KiB
Swift

// Created by Cal Stephens on 10/16/25.
// Copyright © 2025 Nick Lockwood. All rights reserved.
import XCTest
@testable import SwiftFormat
final class TestSuiteAccessControlTests: XCTestCase {
// MARK: XCTest
func testXCTestMethodsAreInternal() {
let input = """
import XCTest
final class MyTests: XCTestCase {
public func testExample() {
XCTAssertTrue(true)
}
private func testHelper() {
XCTAssertTrue(true)
}
}
"""
let output = """
import XCTest
final class MyTests: XCTestCase {
func testExample() {
XCTAssertTrue(true)
}
private func testHelper() {
XCTAssertTrue(true)
}
}
"""
testFormatting(for: input, output, rule: .testSuiteAccessControl, exclude: [.unusedArguments, .validateTestCases])
}
func testXCTestHelperMethodsArePrivate() {
let input = """
import XCTest
final class MyTests: XCTestCase {
func testExample() {
helperMethod(arg: 0)
}
func helperMethod(arg: Int) {
// helper code
}
public func publicHelper(arg: Int) {
// helper code
}
}
"""
let output = """
import XCTest
final class MyTests: XCTestCase {
func testExample() {
helperMethod(arg: 0)
}
private func helperMethod(arg: Int) {
// helper code
}
private func publicHelper(arg: Int) {
// helper code
}
}
"""
testFormatting(for: input, output, rule: .testSuiteAccessControl, exclude: [.unusedArguments, .validateTestCases])
}
func testXCTestPropertiesArePrivate() {
let input = """
import XCTest
final class MyTests: XCTestCase {
var someProperty: String = ""
public var anotherProperty: Int = 0
func testExample() {
XCTAssertEqual(someProperty, "")
}
}
"""
let output = """
import XCTest
final class MyTests: XCTestCase {
private var someProperty: String = ""
private var anotherProperty: Int = 0
func testExample() {
XCTAssertEqual(someProperty, "")
}
}
"""
testFormatting(for: input, output, rule: .testSuiteAccessControl, exclude: [.unusedArguments, .validateTestCases])
}
func testXCTestClassIsInternal() {
let input = """
import XCTest
public final class MyTests: XCTestCase {
func testExample() {
XCTAssertTrue(true)
}
}
"""
let output = """
import XCTest
final class MyTests: XCTestCase {
func testExample() {
XCTAssertTrue(true)
}
}
"""
testFormatting(for: input, output, rule: .testSuiteAccessControl, exclude: [.unusedArguments, .validateTestCases])
}
func testXCTestWithParameterlessInitializerIsProcessed() {
let input = """
import XCTest
final class MyTests: XCTestCase {
private let dependency: Dependency = Dependency()
public init() {
// Custom initialization
}
func testExample() {
XCTAssertTrue(true)
}
}
"""
let output = """
import XCTest
final class MyTests: XCTestCase {
private let dependency: Dependency = Dependency()
init() {
// Custom initialization
}
func testExample() {
XCTAssertTrue(true)
}
}
"""
testFormatting(for: input, output, rule: .testSuiteAccessControl, exclude: [.unusedArguments, .validateTestCases, .redundantType])
}
func testXCTestPreservesOpenTestClass() {
let input = """
import XCTest
open class MyTests: XCTestCase {
func testExample() {
XCTAssertTrue(true)
}
}
"""
testFormatting(for: input, rule: .testSuiteAccessControl, exclude: [.unusedArguments, .validateTestCases])
}
func testXCTestPreservesStaticFunctions() {
let input = """
import XCTest
final class MyTests: XCTestCase {
func testExample() {
XCTAssertTrue(true)
}
static func helperMethod() {
// helper code
}
}
"""
testFormatting(for: input, rule: .testSuiteAccessControl, exclude: [.unusedArguments, .validateTestCases])
}
func testXCTestPreservesStaticProperties() {
let input = """
import XCTest
final class MyTests: XCTestCase {
static var sharedState: String = ""
func testExample() {
XCTAssertEqual(Self.sharedState, "")
}
}
"""
testFormatting(for: input, rule: .testSuiteAccessControl, exclude: [.unusedArguments, .validateTestCases])
}
func testXCTestPreservesOverrideMethods() {
let input = """
import XCTest
class BaseTestCase: XCTestCase {
func setUp() {
// setup code
}
}
class MyTests: BaseTestCase {
override func setUp() {
super.setUp()
}
func testExample() {
XCTAssertTrue(true)
}
}
"""
testFormatting(for: input, rule: .testSuiteAccessControl, exclude: [.unusedArguments, .validateTestCases])
}
func testXCTestPreservesObjcMethods() {
let input = """
import XCTest
final class MyTests: XCTestCase {
@objc func helperMethod() {
// helper code
}
func testExample() {
XCTAssertTrue(true)
}
}
"""
testFormatting(for: input, rule: .testSuiteAccessControl, exclude: [.unusedArguments, .validateTestCases])
}
func testXCTestHelperMethodWithTestPrefixAndParameters() {
let input = """
import XCTest
final class MyTests: XCTestCase {
func testExample() {
testHelper(value: 5)
}
func testHelper(value: Int) {
XCTAssertEqual(value, 5)
}
func testFormatter(string: String) -> String {
return string.uppercased()
}
}
"""
let output = """
import XCTest
final class MyTests: XCTestCase {
func testExample() {
testHelper(value: 5)
}
private func testHelper(value: Int) {
XCTAssertEqual(value, 5)
}
private func testFormatter(string: String) -> String {
return string.uppercased()
}
}
"""
testFormatting(for: input, output, rule: .testSuiteAccessControl, exclude: [.unusedArguments, .validateTestCases])
}
// MARK: Swift Testing
func testSwiftTestingPropertiesArePrivate() {
let input = """
import Testing
struct MyFeatureTests {
var someProperty: String = ""
public var anotherProperty: Int = 0
@Test func featureWorks() {
#expect(someProperty == "")
}
}
"""
let output = """
import Testing
struct MyFeatureTests {
private var someProperty: String = ""
private var anotherProperty: Int = 0
@Test func featureWorks() {
#expect(someProperty == "")
}
}
"""
testFormatting(for: input, output, rule: .testSuiteAccessControl, exclude: [.unusedArguments, .validateTestCases])
}
func testSwiftTestingHelperMethodsArePrivate() {
let input = """
import Testing
struct MyFeatureTests {
@Test func featureWorks() {
helperMethod()
}
func helperMethod() {
// helper code
}
public func publicHelper() {
// helper code
}
}
"""
let output = """
import Testing
struct MyFeatureTests {
@Test func featureWorks() {
helperMethod()
}
private func helperMethod() {
// helper code
}
private func publicHelper() {
// helper code
}
}
"""
testFormatting(for: input, output, rule: .testSuiteAccessControl, exclude: [.unusedArguments, .validateTestCases])
}
func testSwiftTestingClassIsInternal() {
let input = """
import Testing
public struct MyFeatureTests {
@Test func featureWorks() {
#expect(true)
}
}
"""
let output = """
import Testing
struct MyFeatureTests {
@Test func featureWorks() {
#expect(true)
}
}
"""
testFormatting(for: input, output, rule: .testSuiteAccessControl, exclude: [.unusedArguments, .validateTestCases])
}
func testSwiftTestingPrivateTestFunctionsAreMadeInternal() {
let input = """
import Testing
struct MyFeatureTests {
@Test private func featureWorks() {
#expect(true)
}
@Test fileprivate func anotherFeature() {
#expect(true)
}
}
"""
let output = """
import Testing
struct MyFeatureTests {
@Test func featureWorks() {
#expect(true)
}
@Test func anotherFeature() {
#expect(true)
}
}
"""
testFormatting(for: input, output, rule: .testSuiteAccessControl, exclude: [.unusedArguments, .validateTestCases])
}
// MARK: Base Classes
func testDoesNotApplyToBaseTestClasses() {
let input = """
import XCTest
public class MyFeatureTestsBase: XCTestCase {
public func helperMethod() {
// helper code
}
public var someProperty: String = ""
}
"""
testFormatting(for: input, rule: .testSuiteAccessControl, exclude: [.unusedArguments, .validateTestCases])
}
func testDoesNotApplyToSwiftTestingBaseClasses() {
let input = """
import Testing
public class MyFeatureTestsBase {
public func helperMethod() {
// helper code
}
public var someProperty: String = ""
}
"""
testFormatting(for: input, rule: .testSuiteAccessControl, exclude: [.unusedArguments, .validateTestCases])
}
func testDoesNotApplyToTestClassWithBaseInDocComment() {
let input = """
import XCTest
/// Base class for feature tests.
public class MyFeatureTests: XCTestCase {
public func helperMethod() {
// helper code
}
public var someProperty: String = ""
}
"""
testFormatting(for: input, rule: .testSuiteAccessControl, exclude: [.unusedArguments, .validateTestCases])
}
func testDoesNotApplyToTestClassWithSubclassInDocComment() {
let input = """
import XCTest
/// Intended to be subclassed for specific feature tests.
public class MyFeatureTests: XCTestCase {
public func helperMethod() {
// helper code
}
public var someProperty: String = ""
}
"""
testFormatting(for: input, rule: .testSuiteAccessControl, exclude: [.unusedArguments, .validateTestCases])
}
func testDoesNotApplyToSwiftTestingClassWithBaseInDocComment() {
let input = """
import Testing
/// Base struct for testing features.
public struct MyFeatureTests {
public func helperMethod() {
// helper code
}
}
"""
testFormatting(for: input, rule: .testSuiteAccessControl, exclude: [.unusedArguments, .validateTestCases])
}
// MARK: Disabled Tests
func testXCTestPreservesDisabledTestMethods() {
let input = """
import XCTest
final class MyTests: XCTestCase {
func disable_testExample() {
XCTAssertTrue(true)
}
func skip_testFeature() {
XCTAssertTrue(false)
}
}
"""
testFormatting(for: input, rule: .testSuiteAccessControl, exclude: [.unusedArguments, .validateTestCases])
}
func testSwiftTestingPreservesDisabledTestMethods() {
let input = """
import Testing
struct MyFeatureTests {
func disable_featureWorks() {
#expect(true)
}
func x_edgeCaseHandling() {
#expect(false)
}
}
"""
testFormatting(for: input, rule: .testSuiteAccessControl, exclude: [.unusedArguments, .validateTestCases])
}
func testXCTestPreservesCapitalizedDisabledTestMethods() {
let input = """
import XCTest
final class MyTests: XCTestCase {
func X_testExample() {
XCTAssertTrue(true)
}
func DISABLE_testFeature() {
XCTAssertTrue(false)
}
}
"""
testFormatting(for: input, rule: .testSuiteAccessControl, exclude: [.unusedArguments, .validateTestCases])
}
func testSwiftTestingPreservesCapitalizedDisabledTestMethods() {
let input = """
import Testing
struct MyFeatureTests {
func SKIP_featureWorks() {
#expect(true)
}
func DISABLED_edgeCaseHandling() {
#expect(false)
}
}
"""
testFormatting(for: input, rule: .testSuiteAccessControl, exclude: [.unusedArguments, .validateTestCases])
}
// MARK: Mixed Frameworks
func testDoesNotApplyWhenBothTestingFrameworksAreImported() {
let input = """
import XCTest
import Testing
final class MyTests: XCTestCase {
func testExample() {
XCTAssertTrue(true)
}
func helperMethod() {
// helper code
}
var someProperty: String = ""
}
"""
testFormatting(for: input, rule: .testSuiteAccessControl, exclude: [.unusedArguments, .validateTestCases, .sortImports])
}
func testXCTestIgnoresTypesWithParameterizedInit() {
let input = """
import XCTest
final class MyHelperClass: XCTestCase {
let dependency: String
init(dependency: String) {
self.dependency = dependency
}
func example() {
XCTAssertTrue(true)
}
}
"""
// No changes should be made - types with parameterized init are not test suites
testFormatting(for: input, rule: .testSuiteAccessControl, exclude: [.unusedArguments, .validateTestCases])
}
func testSwiftTestingIgnoresTypesWithParameterizedInit() {
let input = """
import Testing
struct MyHelperStruct {
let dependency: String
init(dependency: String) {
self.dependency = dependency
}
func example() {
#expect(true)
}
}
"""
// No changes should be made - types with parameterized init are not test suites
testFormatting(for: input, rule: .testSuiteAccessControl, exclude: [.unusedArguments, .validateTestCases, .redundantMemberwiseInit])
}
func testSwiftTestingPrivateVisibilityOption() {
let input = """
import Testing
struct MyFeatureTests {
@Test func featureWorks() {
#expect(true)
}
func helperMethod() {
// helper code
}
}
"""
let output = """
import Testing
private struct MyFeatureTests {
@Test private func featureWorks() {
#expect(true)
}
private func helperMethod() {
// helper code
}
}
"""
let options = FormatOptions(testCaseAccessControl: .private)
testFormatting(for: input, output, rule: .testSuiteAccessControl, options: options, exclude: [.unusedArguments])
}
func testSwiftTestingPublicVisibilityOption() {
let input = """
import Testing
struct MyFeatureTests {
@Test func featureWorks() {
#expect(true)
}
func helperMethod() {
// helper code
}
}
"""
let output = """
import Testing
public struct MyFeatureTests {
@Test public func featureWorks() {
#expect(true)
}
private func helperMethod() {
// helper code
}
}
"""
let options = FormatOptions(testCaseAccessControl: .public)
testFormatting(for: input, output, rule: .testSuiteAccessControl, options: options, exclude: [.unusedArguments])
}
func testXCTestPrivateVisibilityFallsBackToInternal() {
let input = """
import XCTest
final class MyTests: XCTestCase {
public func testExample() {
XCTAssertTrue(true)
}
func helperMethod() {
// helper code
}
}
"""
let output = """
import XCTest
final class MyTests: XCTestCase {
func testExample() {
XCTAssertTrue(true)
}
private func helperMethod() {
// helper code
}
}
"""
// XCTest doesn't support private tests, so private/fileprivate falls back to internal
let options = FormatOptions(testCaseAccessControl: .private)
testFormatting(for: input, output, rule: .testSuiteAccessControl, options: options, exclude: [.unusedArguments])
}
func testXCTestFileprivateVisibilityFallsBackToInternal() {
let input = """
import XCTest
final class MyTests: XCTestCase {
public func testExample() {
XCTAssertTrue(true)
}
}
"""
let output = """
import XCTest
final class MyTests: XCTestCase {
func testExample() {
XCTAssertTrue(true)
}
}
"""
// XCTest doesn't support fileprivate tests, so fileprivate falls back to internal
let options = FormatOptions(testCaseAccessControl: .fileprivate)
testFormatting(for: input, output, rule: .testSuiteAccessControl, options: options, exclude: [.unusedArguments])
}
func testSwiftTestingFileprivateVisibilityOption() {
let input = """
import Testing
struct MyFeatureTests {
@Test func featureWorks() {
#expect(true)
}
}
"""
let output = """
import Testing
fileprivate struct MyFeatureTests {
@Test fileprivate func featureWorks() {
#expect(true)
}
}
"""
let options = FormatOptions(testCaseAccessControl: .fileprivate)
testFormatting(for: input, output, rule: .testSuiteAccessControl, options: options, exclude: [.unusedArguments])
}
func testSwiftTestingPrivateVisibilityPreservesExistingPrivate() {
let input = """
import Testing
private struct MyFeatureTests {
@Test private func featureWorks() {
#expect(true)
}
}
"""
let options = FormatOptions(testCaseAccessControl: .private)
testFormatting(for: input, rule: .testSuiteAccessControl, options: options, exclude: [.unusedArguments])
}
}