Skip to content
Open
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
Original file line number Diff line number Diff line change
Expand Up @@ -81,12 +81,6 @@
</ActionContent>
</ExecutionAction>
</PostActions>
<TestPlans>
<TestPlanReference
default = "YES"
reference = "container:iOS.xctestplan">
</TestPlanReference>
</TestPlans>
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
Expand Down Expand Up @@ -122,6 +116,12 @@
isEnabled = "NO">
</EnvironmentVariable>
</EnvironmentVariables>
<TestPlans>
<TestPlanReference
reference = "container:iOS.xctestplan"
default = "YES">
</TestPlanReference>
</TestPlans>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
Expand Down
4 changes: 4 additions & 0 deletions Sources/XcodeProj/Extensions/AEXML+XcodeFormat.swift
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,10 @@ let attributesOrder: [String: [String]] = [
"value",
"isEnabled",
],
"TestPlanReference": [
"reference",
"default",
],
"TestableReference": [
"skipped",
"parallelizable",
Expand Down
5 changes: 3 additions & 2 deletions Sources/XcodeProj/Scheme/XCScheme+BuildAction.swift
Original file line number Diff line number Diff line change
Expand Up @@ -158,8 +158,9 @@ public extension XCScheme {
attributes["buildArchitectures"] = buildArchitecturesXMLString
}

if let runPostActionsOnFailure {
attributes["runPostActionsOnFailure"] = runPostActionsOnFailure.xmlString
// Xcode omits the attribute unless it is enabled.
if runPostActionsOnFailure == true {
attributes["runPostActionsOnFailure"] = true.xmlString
}

let element = AEXMLElement(name: "BuildAction",
Expand Down
2 changes: 1 addition & 1 deletion Sources/XcodeProj/Scheme/XCScheme+LaunchAction.swift
Original file line number Diff line number Diff line change
Expand Up @@ -445,7 +445,7 @@ public extension XCScheme {
macro.addChild(macroExpansion.xmlElement())
}

if let commandlineArguments {
if let commandlineArguments, !commandlineArguments.arguments.isEmpty {
element.addChild(commandlineArguments.xmlElement())
}

Expand Down
2 changes: 1 addition & 1 deletion Sources/XcodeProj/Scheme/XCScheme+ProfileAction.swift
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ public extension XCScheme {
if !enableTestabilityWhenProfilingTests {
element.attributes["enableTestabilityWhenProfilingTests"] = "No"
}
if let commandlineArguments {
if let commandlineArguments, !commandlineArguments.arguments.isEmpty {
element.addChild(commandlineArguments.xmlElement())
}
if let environmentVariables {
Expand Down
25 changes: 14 additions & 11 deletions Sources/XcodeProj/Scheme/XCScheme+TestAction.swift
Original file line number Diff line number Diff line change
Expand Up @@ -204,24 +204,20 @@ public extension XCScheme {
let element = AEXMLElement(name: "TestAction", value: nil, attributes: attributes)
super.writeXML(parent: element)

if let testPlans {
let testPlansElement = element.addChild(name: "TestPlans")
for testPlan in testPlans {
testPlansElement.addChild(testPlan.xmlElement())
}
}

if let macroExpansion {
let macro = element.addChild(name: "MacroExpansion")
macro.addChild(macroExpansion.xmlElement())
}

let testablesElement = element.addChild(name: "Testables")
for testable in testables {
testablesElement.addChild(testable.xmlElement())
// Xcode omits empty testables when the scheme uses test plans.
if !testables.isEmpty || testPlans == nil {
let testablesElement = element.addChild(name: "Testables")
for testable in testables {
testablesElement.addChild(testable.xmlElement())
}
}

if let commandlineArguments {
if let commandlineArguments, !commandlineArguments.arguments.isEmpty {
element.addChild(commandlineArguments.xmlElement())
}

Expand All @@ -243,6 +239,13 @@ public extension XCScheme {
}
}

if let testPlans {
let testPlansElement = element.addChild(name: "TestPlans")
for testPlan in testPlans {
testPlansElement.addChild(testPlan.xmlElement())
}
}

return element
}

Expand Down
31 changes: 31 additions & 0 deletions Tests/XcodeProjTests/Scheme/XCSchemeTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,37 @@ final class XCSchemeIntegrationTests: XCTestCase {
XCTAssertEqual(subject, reconstructedSubject)
}

func test_testAction_withTestPlans_serializesLikeXcode() throws {
// Given
let subject = try XCScheme.TestAction(buildConfiguration: "Debug",
macroExpansion: nil,
testPlans: [.init(reference: "container:App.xctestplan", default: true)],
codeCoverageTargets: [buildableReferenceWithStringBluePrint()],
commandlineArguments: .init(arguments: []))

// When
let element = subject.xmlElement()

// Then
XCTAssertEqual(element.children.map(\.name), ["CodeCoverageTargets", "TestPlans"])
}

func test_testAction_withoutTestPlans_keepsEmptyTestables() {
// Given
let subject = XCScheme.TestAction(buildConfiguration: "Debug", macroExpansion: nil)

// When
let element = subject.xmlElement()

// Then
XCTAssertEqual(element.children.map(\.name), ["Testables"])
}

func test_buildAction_runPostActionsOnFailure_onlySerializedWhenEnabled() {
XCTAssertNil(XCScheme.BuildAction(runPostActionsOnFailure: false).xmlElement().attributes["runPostActionsOnFailure"])
XCTAssertEqual(XCScheme.BuildAction(runPostActionsOnFailure: true).xmlElement().attributes["runPostActionsOnFailure"], "YES")
}

func test_scheme_remoteRunnable() throws {
// Given / When
let subject = try XCScheme(path: watchAppSchemePath)
Expand Down