Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
- Added support for DocC Catalogs [#1091](https://github.com/yonaskolb/XcodeGen/pull/1091) @brevansio
- Added support for "driver-extension" and "system-extension" product types [#1092](https://github.com/yonaskolb/XcodeGen/issues/1092) @vgorloff
- Add support for conditionally linking dependencies for specific platforms [#1087](https://github.com/yonaskolb/XcodeGen/pull/1087) @daltonclaybrook
- Add ability to specify UI testing screenshot behavior in test schemes [#942](https://github.com/yonaskolb/XcodeGen/pull/942) @daltonclaybrook

### Changed
- **Breaking**: Rename the `platform` field on `Dependency` to `platformFilter` [#1087](https://github.com/yonaskolb/XcodeGen/pull/1087) @daltonclaybrook
Expand Down
2 changes: 2 additions & 0 deletions Docs/ProjectSpec.md
Original file line number Diff line number Diff line change
Expand Up @@ -814,6 +814,8 @@ A multiline script can be written using the various YAML multiline methods, for
- [ ] **coverageTargets**: **[String]** - a list of targets to gather code coverage. Each entry can either be a simple string, or a string using [Project Reference](#project-reference)
- [ ] **targets**: **[[Test Target](#test-target)]** - a list of targets to test. Each entry can either be a simple string, or a [Test Target](#test-target)
- [ ] **customLLDBInit**: **String** - the absolute path to the custom `.lldbinit` file
- [ ] **captureScreenshotsAutomatically**: **Bool** - indicates whether screenshots should be captured automatically while UI Testing. This defaults to true.
- [ ] **deleteScreenshotsWhenEachTestSucceeds**: **Bool** - whether successful UI tests should cause automatically-captured screenshots to be deleted. If `captureScreenshotsAutomatically` is false, this value is ignored. This defaults to true.

#### Test Target
- [x] **name**: **String** - The name of the target
Expand Down
20 changes: 19 additions & 1 deletion Sources/ProjectSpec/Scheme.swift
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,8 @@ public struct Scheme: Equatable {
public static let gatherCoverageDataDefault = false
public static let disableMainThreadCheckerDefault = false
public static let debugEnabledDefault = true
public static let captureScreenshotsAutomaticallyDefault = true
public static let deleteScreenshotsWhenEachTestSucceedsDefault = true

public var config: String?
public var gatherCoverageData: Bool
Expand All @@ -178,6 +180,8 @@ public struct Scheme: Equatable {
public var region: String?
public var debugEnabled: Bool
public var customLLDBInit: String?
public var captureScreenshotsAutomatically: Bool
public var deleteScreenshotsWhenEachTestSucceeds: Bool

public struct TestTarget: Equatable, ExpressibleByStringLiteral {
public static let randomExecutionOrderDefault = false
Expand Down Expand Up @@ -236,7 +240,9 @@ public struct Scheme: Equatable {
language: String? = nil,
region: String? = nil,
debugEnabled: Bool = debugEnabledDefault,
customLLDBInit: String? = nil
customLLDBInit: String? = nil,
captureScreenshotsAutomatically: Bool = captureScreenshotsAutomaticallyDefault,
deleteScreenshotsWhenEachTestSucceeds: Bool = deleteScreenshotsWhenEachTestSucceedsDefault
) {
self.config = config
self.gatherCoverageData = gatherCoverageData
Expand All @@ -251,6 +257,8 @@ public struct Scheme: Equatable {
self.region = region
self.debugEnabled = debugEnabled
self.customLLDBInit = customLLDBInit
self.captureScreenshotsAutomatically = captureScreenshotsAutomatically
self.deleteScreenshotsWhenEachTestSucceeds = deleteScreenshotsWhenEachTestSucceeds
}

public var shouldUseLaunchSchemeArgsEnv: Bool {
Expand Down Expand Up @@ -475,6 +483,8 @@ extension Scheme.Test: JSONObjectConvertible {
region = jsonDictionary.json(atKeyPath: "region")
debugEnabled = jsonDictionary.json(atKeyPath: "debugEnabled") ?? Scheme.Test.debugEnabledDefault
customLLDBInit = jsonDictionary.json(atKeyPath: "customLLDBInit")
captureScreenshotsAutomatically = jsonDictionary.json(atKeyPath: "captureScreenshotsAutomatically") ?? Scheme.Test.captureScreenshotsAutomaticallyDefault
deleteScreenshotsWhenEachTestSucceeds = jsonDictionary.json(atKeyPath: "deleteScreenshotsWhenEachTestSucceeds") ?? Scheme.Test.deleteScreenshotsWhenEachTestSucceedsDefault
}
}

Expand Down Expand Up @@ -508,6 +518,14 @@ extension Scheme.Test: JSONEncodable {
dict["customLLDBInit"] = customLLDBInit
}

if captureScreenshotsAutomatically != Scheme.Test.captureScreenshotsAutomaticallyDefault {
dict["captureScreenshotsAutomatically"] = captureScreenshotsAutomatically
}

if deleteScreenshotsWhenEachTestSucceeds != Scheme.Test.deleteScreenshotsWhenEachTestSucceedsDefault {
dict["deleteScreenshotsWhenEachTestSucceeds"] = deleteScreenshotsWhenEachTestSucceeds
}

return dict
}
}
Expand Down
14 changes: 14 additions & 0 deletions Sources/XcodeGenKit/SchemeGenerator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,7 @@ public class SchemeGenerator {
environmentVariables: testVariables,
language: scheme.test?.language,
region: scheme.test?.region,
systemAttachmentLifetime: scheme.test?.systemAttachmentLifetime,
customLLDBInitFile: scheme.test?.customLLDBInit
)

Expand Down Expand Up @@ -448,3 +449,16 @@ extension PBXProductType {
}
}
}

extension Scheme.Test {
var systemAttachmentLifetime: XCScheme.TestAction.AttachmentLifetime? {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seeing as though these 2 booleans end up as an enum, we could also just add a simple attachmentLifetime enum to the spec instead. Thoughts?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My thought was that the "attachment lifetime" is more of an implementation detail of the XCScheme rather than the Scheme in the project spec. From the user's perspective, the bools are a 1:1 mapping with these two checkboxes in the Xcode scheme editor. Happy to discuss this more, though.
Screen Shot 2020-09-06 at 12 07 11 PM

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@yonaskolb any more thoughts on this? I'm happy to make this change if you think it's the right call.

switch (captureScreenshotsAutomatically, deleteScreenshotsWhenEachTestSucceeds) {
case (false, _):
return .keepNever
case (true, false):
return .keepAlways
case (true, true):
return nil
}
}
}
53 changes: 53 additions & 0 deletions Tests/XcodeGenKitTests/SchemeGeneratorTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ class SchemeGeneratorTests: XCTestCase {
try expect(xcscheme.launchAction?.locationScenarioReference?.identifier) == "New York, NY, USA"
try expect(xcscheme.launchAction?.customLLDBInitFile) == "/sample/.lldbinit"
try expect(xcscheme.testAction?.customLLDBInitFile) == "/test/.lldbinit"
try expect(xcscheme.testAction?.systemAttachmentLifetime).to.beNil()
}

let frameworkTarget = Scheme.BuildTarget(target: .local(framework.name), buildTypes: [.archiving])
Expand Down Expand Up @@ -445,6 +446,42 @@ class SchemeGeneratorTests: XCTestCase {
let xcscheme = try unwrap(xcodeProject.sharedData?.schemes.first)
try expect(xcscheme.launchAction?.macroExpansion?.buildableName) == "MyApp.app"
}

$0.it("generates scheme capturing screenshots automatically and deleting on success") {
let xcscheme = try self.makeSnapshotScheme(
buildTarget: buildTarget,
captureScreenshotsAutomatically: true,
deleteScreenshotsWhenEachTestSucceeds: true)

try expect(xcscheme.testAction?.systemAttachmentLifetime).to.beNil()
}

$0.it("generates scheme capturing screenshots and not deleting") {
let xcscheme = try self.makeSnapshotScheme(
buildTarget: buildTarget,
captureScreenshotsAutomatically: true,
deleteScreenshotsWhenEachTestSucceeds: false)

try expect(xcscheme.testAction?.systemAttachmentLifetime) == .keepAlways
}

$0.it("generates scheme not capturing screenshots") {
let xcscheme = try self.makeSnapshotScheme(
buildTarget: buildTarget,
captureScreenshotsAutomatically: false,
deleteScreenshotsWhenEachTestSucceeds: false)

try expect(xcscheme.testAction?.systemAttachmentLifetime) == .keepNever
}

$0.it("ignores screenshot delete preference when not capturing screenshots") {
let xcscheme = try self.makeSnapshotScheme(
buildTarget: buildTarget,
captureScreenshotsAutomatically: false,
deleteScreenshotsWhenEachTestSucceeds: true)

try expect(xcscheme.testAction?.systemAttachmentLifetime) == .keepNever
}
}
}

Expand Down Expand Up @@ -503,4 +540,20 @@ class SchemeGeneratorTests: XCTestCase {
let xcodeProject = try project.generateXcodeProject()
return try unwrap(xcodeProject.sharedData?.schemes.first)
}

private func makeSnapshotScheme(buildTarget: Scheme.BuildTarget, captureScreenshotsAutomatically: Bool, deleteScreenshotsWhenEachTestSucceeds: Bool) throws -> XCScheme {
let scheme = Scheme(
name: "MyScheme",
build: Scheme.Build(targets: [buildTarget]),
run: Scheme.Run(config: "Debug"),
test: Scheme.Test(config: "Debug", captureScreenshotsAutomatically: captureScreenshotsAutomatically, deleteScreenshotsWhenEachTestSucceeds: deleteScreenshotsWhenEachTestSucceeds)
)
let project = Project(
name: "test",
targets: [app, framework],
schemes: [scheme]
)
let xcodeProject = try project.generateXcodeProject()
return try unwrap(xcodeProject.sharedData?.schemes.first)
}
}