Add ability to run only one(focused) example (#3911)
* Add ability to focus on a specific test example * Update CHANGELOG.md Co-authored-by: JP Simard <jp@jpsim.com> * Update CONTRIBUTING.md Co-authored-by: JP Simard <jp@jpsim.com> Co-authored-by: JP Simard <jp@jpsim.com>
This commit is contained in:
parent
702b36a781
commit
1616023b63
|
@ -48,6 +48,10 @@
|
||||||
environments, such as in Swift Package Manager plugins.
|
environments, such as in Swift Package Manager plugins.
|
||||||
[Juozas Valancius](https://github.com/juozasvalancius)
|
[Juozas Valancius](https://github.com/juozasvalancius)
|
||||||
|
|
||||||
|
* Add ability to run only one (focused) example.
|
||||||
|
[PaulTaykalo](https://github.com/PaulTaykalo)
|
||||||
|
[#3911](https://github.com/realm/SwiftLint/issues/3911)
|
||||||
|
|
||||||
#### Bug Fixes
|
#### Bug Fixes
|
||||||
|
|
||||||
* Extend `class_delegate_protocol` to correctly identify cases with the protocol
|
* Extend `class_delegate_protocol` to correctly identify cases with the protocol
|
||||||
|
|
|
@ -72,6 +72,19 @@ over time. This way adding a unit test for your new Rule is just a matter of
|
||||||
adding a test case in `RulesTests.swift` which simply calls
|
adding a test case in `RulesTests.swift` which simply calls
|
||||||
`verifyRule(YourNewRule.description)`.
|
`verifyRule(YourNewRule.description)`.
|
||||||
|
|
||||||
|
For debugging purposes examples can be marked as `focused`. If there are any
|
||||||
|
focused examples found, then only those will be run when running tests for that rule.
|
||||||
|
```
|
||||||
|
nonTriggeringExamples: [
|
||||||
|
Example("let x: [Int]"),
|
||||||
|
Example("let x: [Int: String]").focused() // only this one will be run in tests
|
||||||
|
],
|
||||||
|
triggeringExamples: [
|
||||||
|
Example("let x: ↓Array<String>"),
|
||||||
|
Example("let x: ↓Dictionary<Int, String>")
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
### `ConfigurationProviderRule`
|
### `ConfigurationProviderRule`
|
||||||
|
|
||||||
If your rule supports user-configurable options via `.swiftlint.yml`, you can
|
If your rule supports user-configurable options via `.swiftlint.yml`, you can
|
||||||
|
|
|
@ -32,6 +32,9 @@ public struct Example {
|
||||||
/// pathological use cases which are indeed important to test but not helpful for understanding can be
|
/// pathological use cases which are indeed important to test but not helpful for understanding can be
|
||||||
/// hidden from the documentation with this option.
|
/// hidden from the documentation with this option.
|
||||||
let excludeFromDocumentation: Bool
|
let excludeFromDocumentation: Bool
|
||||||
|
|
||||||
|
/// Specifies whether the test example should be the only example run during the current test case execution.
|
||||||
|
var isFocused: Bool
|
||||||
}
|
}
|
||||||
|
|
||||||
public extension Example {
|
public extension Example {
|
||||||
|
@ -55,6 +58,7 @@ public extension Example {
|
||||||
self.file = file
|
self.file = file
|
||||||
self.line = line
|
self.line = line
|
||||||
self.excludeFromDocumentation = excludeFromDocumentation
|
self.excludeFromDocumentation = excludeFromDocumentation
|
||||||
|
self.isFocused = false
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the same example, but with the `code` that is passed in
|
/// Returns the same example, but with the `code` that is passed in
|
||||||
|
@ -69,6 +73,13 @@ public extension Example {
|
||||||
func removingViolationMarkers() -> Example {
|
func removingViolationMarkers() -> Example {
|
||||||
return with(code: code.replacingOccurrences(of: "↓", with: ""))
|
return with(code: code.replacingOccurrences(of: "↓", with: ""))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Makes the current example focused.
|
||||||
|
func focused() -> Example {
|
||||||
|
var new = self
|
||||||
|
new.isFocused = true
|
||||||
|
return new
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension Example: Hashable {
|
extension Example: Hashable {
|
||||||
|
|
|
@ -356,7 +356,11 @@ extension XCTestCase {
|
||||||
requiresFileOnDisk: ruleDescription.requiresFileOnDisk,
|
requiresFileOnDisk: ruleDescription.requiresFileOnDisk,
|
||||||
file: file, line: line)
|
file: file, line: line)
|
||||||
}
|
}
|
||||||
|
func makeViolations(_ example: Example) -> [StyleViolation] {
|
||||||
|
return violations(example, config: config, requiresFileOnDisk: ruleDescription.requiresFileOnDisk)
|
||||||
|
}
|
||||||
|
|
||||||
|
let ruleDescription = ruleDescription.focused()
|
||||||
let triggers = ruleDescription.triggeringExamples
|
let triggers = ruleDescription.triggeringExamples
|
||||||
let nonTriggers = ruleDescription.nonTriggeringExamples
|
let nonTriggers = ruleDescription.nonTriggeringExamples
|
||||||
verify(triggers: triggers, nonTriggers: nonTriggers)
|
verify(triggers: triggers, nonTriggers: nonTriggers)
|
||||||
|
@ -369,10 +373,6 @@ extension XCTestCase {
|
||||||
verify(triggers: triggers.map(addShebang), nonTriggers: nonTriggers.map(addShebang))
|
verify(triggers: triggers.map(addShebang), nonTriggers: nonTriggers.map(addShebang))
|
||||||
}
|
}
|
||||||
|
|
||||||
func makeViolations(_ example: Example) -> [StyleViolation] {
|
|
||||||
return violations(example, config: config, requiresFileOnDisk: ruleDescription.requiresFileOnDisk)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Comment doesn't violate
|
// Comment doesn't violate
|
||||||
if !skipCommentTests {
|
if !skipCommentTests {
|
||||||
XCTAssertEqual(
|
XCTAssertEqual(
|
||||||
|
@ -401,6 +401,8 @@ extension XCTestCase {
|
||||||
|
|
||||||
func verifyCorrections(_ ruleDescription: RuleDescription, config: Configuration,
|
func verifyCorrections(_ ruleDescription: RuleDescription, config: Configuration,
|
||||||
disableCommands: [String], testMultiByteOffsets: Bool) {
|
disableCommands: [String], testMultiByteOffsets: Bool) {
|
||||||
|
let ruleDescription = ruleDescription.focused()
|
||||||
|
|
||||||
parserDiagnosticsDisabledForTests = true
|
parserDiagnosticsDisabledForTests = true
|
||||||
|
|
||||||
// corrections
|
// corrections
|
||||||
|
@ -509,3 +511,37 @@ extension XCTestCase {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private struct FocusedRuleDescription {
|
||||||
|
let nonTriggeringExamples: [Example]
|
||||||
|
let triggeringExamples: [Example]
|
||||||
|
let corrections: [Example: Example]
|
||||||
|
|
||||||
|
init(rule: RuleDescription) {
|
||||||
|
let nonTriggering = rule.nonTriggeringExamples.filter(\.isFocused)
|
||||||
|
let triggering = rule.triggeringExamples.filter(\.isFocused)
|
||||||
|
let corrections = rule.corrections.filter { _, value in value.isFocused }
|
||||||
|
let anyFocused = nonTriggering.isNotEmpty || triggering.isNotEmpty || corrections.isNotEmpty
|
||||||
|
|
||||||
|
if anyFocused {
|
||||||
|
self.nonTriggeringExamples = nonTriggering
|
||||||
|
self.triggeringExamples = triggering
|
||||||
|
self.corrections = corrections
|
||||||
|
#if DISABLE_FOCUSED_EXAMPLES
|
||||||
|
(nonTriggering + triggering + corrections.values).forEach { example in
|
||||||
|
XCTFail("Focused examples are disabled", file: example.file, line: example.line)
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
|
self.nonTriggeringExamples = rule.nonTriggeringExamples
|
||||||
|
self.triggeringExamples = rule.triggeringExamples
|
||||||
|
self.corrections = rule.corrections
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private extension RuleDescription {
|
||||||
|
func focused() -> FocusedRuleDescription {
|
||||||
|
return FocusedRuleDescription(rule: self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@ jobs:
|
||||||
containerImage: swift:5.6
|
containerImage: swift:5.6
|
||||||
container: $[ variables['containerImage'] ]
|
container: $[ variables['containerImage'] ]
|
||||||
steps:
|
steps:
|
||||||
- script: swift test --parallel
|
- script: swift test --parallel -Xswiftc -DDISABLE_FOCUSED_EXAMPLES
|
||||||
displayName: swift test
|
displayName: swift test
|
||||||
|
|
||||||
- job: Xcode
|
- job: Xcode
|
||||||
|
@ -32,7 +32,7 @@ jobs:
|
||||||
sw_vers
|
sw_vers
|
||||||
xcodebuild -version
|
xcodebuild -version
|
||||||
displayName: Version Informations
|
displayName: Version Informations
|
||||||
- script: xcodebuild -scheme swiftlint test -destination "platform=macOS"
|
- script: xcodebuild -scheme swiftlint test -destination "platform=macOS" OTHER_SWIFT_FLAGS="-D DISABLE_FOCUSED_EXAMPLES"
|
||||||
displayName: xcodebuild test
|
displayName: xcodebuild test
|
||||||
|
|
||||||
- job: SwiftPM
|
- job: SwiftPM
|
||||||
|
@ -50,7 +50,7 @@ jobs:
|
||||||
sw_vers
|
sw_vers
|
||||||
xcodebuild -version
|
xcodebuild -version
|
||||||
displayName: Version Informations
|
displayName: Version Informations
|
||||||
- script: swift test --parallel --enable-code-coverage
|
- script: swift test --parallel --enable-code-coverage -Xswiftc -DDISABLE_FOCUSED_EXAMPLES
|
||||||
displayName: swift test
|
displayName: swift test
|
||||||
- script: |
|
- script: |
|
||||||
xcrun llvm-cov export -format="lcov" .build/debug/SwiftLintPackageTests.xctest/Contents/MacOS/SwiftLintPackageTests -instr-profile .build/debug/codecov/default.profdata > coverage.lcov
|
xcrun llvm-cov export -format="lcov" .build/debug/SwiftLintPackageTests.xctest/Contents/MacOS/SwiftLintPackageTests -instr-profile .build/debug/codecov/default.profdata > coverage.lcov
|
||||||
|
|
Loading…
Reference in New Issue