Skip to content

Commit

Permalink
SharedSchemeSkipsTestsRule for #10
Browse files Browse the repository at this point in the history
  • Loading branch information
mattmassicotte committed Jan 24, 2024
1 parent c29be0c commit 90e461c
Show file tree
Hide file tree
Showing 12 changed files with 1,541 additions and 7 deletions.
15 changes: 8 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,16 +47,17 @@ This will run a default set of rules. But, you can customize its behavior with a
```yaml
# Some rules may not be appropriate for all projects. You must opt-in those.
opt_in_rules:
- embedded_build_setting # checks for build settings in the project file
- groups_sorted # checks that all group contents are alphabetically sorted
- implicit_dependencies # checks for any schemes that have "Find Implicit Dependencies" enabled
- targets_use_xcconfig # checks for any targets without a XCConfig file set
- projects_use_xcconfig # checks for any projects without a XCConfig file set
- embedded_build_setting # checks for build settings in the project file
- groups_sorted # checks that all group contents are alphabetically sorted
- implicit_dependencies # checks for any schemes that have "Find Implicit Dependencies" enabled
- targets_use_xcconfig # checks for any targets without a XCConfig file set
- projects_use_xcconfig # checks for any projects without a XCConfig file set
- shared_scheme_skips_tests # checks for any shared schemes that have disabled tests

# Other rules make sense for all projects by default. You must opt-out of those.
disabled_rules:
- build_files_ordered # checks that the ordering of techincally-unordered collections Xcode writes out is preserved
- validate_build_settings # checks that build settings have valid values
- build_files_ordered # checks that the ordering of techincally-unordered collections Xcode writes out is preserved
- validate_build_settings # checks that build settings have valid values
```
## Alternatives
Expand Down
69 changes: 69 additions & 0 deletions Sources/XCLinting/Rules/SharedSchemeSkipsTestsRule.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import Foundation

import XcodeProj
import XCConfig

// this is needed for XCScheme creation
import PathKit

/// Detect when a shared scheme has disabled tests.
struct SharedSchemeSkipsTestsRule {
func run(_ environment: XCLinter.Environment) throws -> [Violation] {
let sharedSchemesURL = environment
.projectRootURL
.appendingPathComponent("xcshareddata/xcschemes", isDirectory: true)
.standardizedFileURL

let fileManager = FileManager.default

guard fileManager.isReadableFile(atPath: sharedSchemesURL.path) else { return [] }

var violations = [Violation]()

for entry in try fileManager.contentsOfDirectory(atPath: sharedSchemesURL.path) {
let entryPath = sharedSchemesURL
.appendingPathComponent(entry, isDirectory: false)
.standardizedFileURL
.path

let scheme = try XCScheme(path: Path(entryPath))

guard let testAction = scheme.testAction else { continue }

if testAction.testables.contains(where: { $0.skipped == true }) {
violations.append(.init("Scheme \"\(entry)\" has skipped test bundles"))
}

if testAction.testables.contains(where: { $0.skippedTests.isEmpty == false }) {
violations.append(.init("Scheme \"\(entry)\" has skipped tests"))
}
}


return violations
}

private func validateSchemes(in url: URL) throws -> [Violation] {
let fileManager = FileManager.default

guard fileManager.isReadableFile(atPath: url.path) else { return [] }

var violations = [Violation]()

for entry in try fileManager.contentsOfDirectory(atPath: url.path) {
let entryPath = url
.appendingPathComponent(entry, isDirectory: false)
.standardizedFileURL
.path

let scheme = try XCScheme(path: Path(entryPath))

if scheme.buildAction?.buildImplicitDependencies == true {
violations.append(.init("Scheme \"\(entry)\" has implicit dependencies enabled"))
}
}

return violations
}
}

1 change: 1 addition & 0 deletions Sources/XCLinting/XCLinter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -81,5 +81,6 @@ extension XCLinter {
"implicit_dependencies": { try ImplicitDependenciesRule().run($0) },
"targets_use_xcconfig": { try TargetsUseXCConfigRule().run($0) },
"projects_use_xcconfig": { try ProjectsUseXCConfigRule().run($0) },
"shared_scheme_skips_tests": { try SharedSchemeSkipsTestsRule().run($0) }
]
}
54 changes: 54 additions & 0 deletions Tests/XCLintTests/SharedSchemeSkipsTestsRuleTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import XCTest

@testable import XCLinting
import XcodeProj

final class SharedSchemeSkipsTestsRuleTests: XCTestCase {
func testProjectWithNoSkippedTests() throws {
let url = try Bundle.module.testDataURL(named: "StockMacOSApp.xcodeproj")

let project = try XcodeProj(pathString: url.path)

let env = XCLinter.Environment(
project: project,
projectRootURL: url,
configuration: Configuration()
)

let violations = try SharedSchemeSkipsTestsRule().run(env)

XCTAssertTrue(violations.isEmpty)
}

func testProjectWithSkippedTests() throws {
let url = try Bundle.module.testDataURL(named: "SchemeSkipsTests.xcodeproj")

let project = try XcodeProj(pathString: url.path)

let env = XCLinter.Environment(
project: project,
projectRootURL: url,
configuration: Configuration()
)

let violations = try SharedSchemeSkipsTestsRule().run(env)

XCTAssertFalse(violations.isEmpty)
}

func testProjectWithSkippedTestBundles() throws {
let url = try Bundle.module.testDataURL(named: "SchemeSkipsTestBundles.xcodeproj")

let project = try XcodeProj(pathString: url.path)

let env = XCLinter.Environment(
project: project,
projectRootURL: url,
configuration: Configuration()
)

let violations = try SharedSchemeSkipsTestsRule().run(env)

XCTAssertFalse(violations.isEmpty)
}
}
Loading

0 comments on commit 90e461c

Please sign in to comment.