From 67f0df3f47796da6fde1a083b326591615d4d7a6 Mon Sep 17 00:00:00 2001 From: Dalton Claybrook Date: Thu, 27 Aug 2020 09:29:29 -0400 Subject: [PATCH 1/6] Support for specifying UI testing snapshot behavior in scheme test action --- Docs/ProjectSpec.md | 2 ++ Sources/ProjectSpec/Scheme.swift | 10 +++++++++- Sources/XcodeGenKit/SchemeGenerator.swift | 14 ++++++++++++++ 3 files changed, 25 insertions(+), 1 deletion(-) diff --git a/Docs/ProjectSpec.md b/Docs/ProjectSpec.md index 4d57e3f38..91d80e3f6 100644 --- a/Docs/ProjectSpec.md +++ b/Docs/ProjectSpec.md @@ -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 diff --git a/Sources/ProjectSpec/Scheme.swift b/Sources/ProjectSpec/Scheme.swift index e5e30b1b0..1718514f8 100644 --- a/Sources/ProjectSpec/Scheme.swift +++ b/Sources/ProjectSpec/Scheme.swift @@ -178,6 +178,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 @@ -236,7 +238,9 @@ public struct Scheme: Equatable { language: String? = nil, region: String? = nil, debugEnabled: Bool = debugEnabledDefault, - customLLDBInit: String? = nil + customLLDBInit: String? = nil, + captureScreenshotsAutomatically: Bool = true, + deleteScreenshotsWhenEachTestSucceeds: Bool = true ) { self.config = config self.gatherCoverageData = gatherCoverageData @@ -251,6 +255,8 @@ public struct Scheme: Equatable { self.region = region self.debugEnabled = debugEnabled self.customLLDBInit = customLLDBInit + self.captureScreenshotsAutomatically = captureScreenshotsAutomatically + self.deleteScreenshotsWhenEachTestSucceeds = deleteScreenshotsWhenEachTestSucceeds } public var shouldUseLaunchSchemeArgsEnv: Bool { @@ -475,6 +481,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") ?? true + deleteScreenshotsWhenEachTestSucceeds = jsonDictionary.json(atKeyPath: "deleteScreenshotsWhenEachTestSucceeds") ?? true } } diff --git a/Sources/XcodeGenKit/SchemeGenerator.swift b/Sources/XcodeGenKit/SchemeGenerator.swift index 907e2e5d4..67f681964 100644 --- a/Sources/XcodeGenKit/SchemeGenerator.swift +++ b/Sources/XcodeGenKit/SchemeGenerator.swift @@ -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 ) @@ -448,3 +449,16 @@ extension PBXProductType { } } } + +extension Scheme.Test { + var systemAttachmentLifetime: XCScheme.TestAction.AttachmentLifetime? { + switch (captureScreenshotsAutomatically, deleteScreenshotsWhenEachTestSucceeds) { + case (false, _): + return .keepNever + case (true, false): + return .keepAlways + case (true, true): + return nil + } + } +} From 4021ff1c1d12ee53f7e92705e002c2e92ad95a87 Mon Sep 17 00:00:00 2001 From: Dalton Claybrook Date: Thu, 27 Aug 2020 09:50:02 -0400 Subject: [PATCH 2/6] Add tests for new screenshot scheme options --- .../SchemeGeneratorTests.swift | 53 +++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/Tests/XcodeGenKitTests/SchemeGeneratorTests.swift b/Tests/XcodeGenKitTests/SchemeGeneratorTests.swift index 16f437464..3c27b8a91 100644 --- a/Tests/XcodeGenKitTests/SchemeGeneratorTests.swift +++ b/Tests/XcodeGenKitTests/SchemeGeneratorTests.swift @@ -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]) @@ -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 + } } } @@ -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) + } } From 9043bce8b12232ab9f99507203682c9f5d73d46c Mon Sep 17 00:00:00 2001 From: Dalton Claybrook Date: Thu, 27 Aug 2020 09:55:43 -0400 Subject: [PATCH 3/6] Update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d5c1a46c5..988888557 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 From 4d1f51afc4a9a4cf9ae64ef71cab2c4e92c27983 Mon Sep 17 00:00:00 2001 From: Dalton Claybrook Date: Mon, 21 Jun 2021 12:04:37 -0400 Subject: [PATCH 4/6] Add new fields to Scheme.Test json encoding --- Sources/ProjectSpec/Scheme.swift | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Sources/ProjectSpec/Scheme.swift b/Sources/ProjectSpec/Scheme.swift index 1718514f8..8c94b4891 100644 --- a/Sources/ProjectSpec/Scheme.swift +++ b/Sources/ProjectSpec/Scheme.swift @@ -498,6 +498,8 @@ extension Scheme.Test: JSONEncodable { "language": language, "region": region, "coverageTargets": coverageTargets.map { $0.reference }, + "captureScreenshotsAutomatically": captureScreenshotsAutomatically, + "deleteScreenshotsWhenEachTestSucceeds": deleteScreenshotsWhenEachTestSucceeds, ] if gatherCoverageData != Scheme.Test.gatherCoverageDataDefault { From 451820dc794a9835bf7e0aa754aef94ed4d26775 Mon Sep 17 00:00:00 2001 From: Dalton Claybrook Date: Mon, 21 Jun 2021 19:35:08 -0400 Subject: [PATCH 5/6] Only save values to JSON if they aren't the defaults --- Sources/ProjectSpec/Scheme.swift | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/Sources/ProjectSpec/Scheme.swift b/Sources/ProjectSpec/Scheme.swift index 8c94b4891..0ac260191 100644 --- a/Sources/ProjectSpec/Scheme.swift +++ b/Sources/ProjectSpec/Scheme.swift @@ -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 @@ -481,8 +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") ?? true - deleteScreenshotsWhenEachTestSucceeds = jsonDictionary.json(atKeyPath: "deleteScreenshotsWhenEachTestSucceeds") ?? true + captureScreenshotsAutomatically = jsonDictionary.json(atKeyPath: "captureScreenshotsAutomatically") ?? Scheme.Test.captureScreenshotsAutomaticallyDefault + deleteScreenshotsWhenEachTestSucceeds = jsonDictionary.json(atKeyPath: "deleteScreenshotsWhenEachTestSucceeds") ?? Scheme.Test.deleteScreenshotsWhenEachTestSucceedsDefault } } @@ -498,8 +500,6 @@ extension Scheme.Test: JSONEncodable { "language": language, "region": region, "coverageTargets": coverageTargets.map { $0.reference }, - "captureScreenshotsAutomatically": captureScreenshotsAutomatically, - "deleteScreenshotsWhenEachTestSucceeds": deleteScreenshotsWhenEachTestSucceeds, ] if gatherCoverageData != Scheme.Test.gatherCoverageDataDefault { @@ -518,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 } } From 2952a8bbf514b55248e6a55d4361a6cb9369b5ea Mon Sep 17 00:00:00 2001 From: Dalton Claybrook Date: Mon, 21 Jun 2021 19:37:08 -0400 Subject: [PATCH 6/6] Using new defaults constants --- Sources/ProjectSpec/Scheme.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Sources/ProjectSpec/Scheme.swift b/Sources/ProjectSpec/Scheme.swift index 0ac260191..ed921c89d 100644 --- a/Sources/ProjectSpec/Scheme.swift +++ b/Sources/ProjectSpec/Scheme.swift @@ -241,8 +241,8 @@ public struct Scheme: Equatable { region: String? = nil, debugEnabled: Bool = debugEnabledDefault, customLLDBInit: String? = nil, - captureScreenshotsAutomatically: Bool = true, - deleteScreenshotsWhenEachTestSucceeds: Bool = true + captureScreenshotsAutomatically: Bool = captureScreenshotsAutomaticallyDefault, + deleteScreenshotsWhenEachTestSucceeds: Bool = deleteScreenshotsWhenEachTestSucceedsDefault ) { self.config = config self.gatherCoverageData = gatherCoverageData