Added option to only generate HTML/JUnit for failed tests via -f by amleszk · Pull Request #236 · XCTestHTMLReport/XCTestHTMLReport · GitHub
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
1 change: 0 additions & 1 deletion Sources/XCTestHTMLReport/Argument.swift
3 changes: 1 addition & 2 deletions Sources/XCTestHTMLReport/Command.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,7 @@ struct Command
var isValid: Bool {
let flagIndexes = CommandLine.arguments.enumerated().map { $0.element.first == "-" ? $0.offset : nil }.compactMap { $0 }

for index in 0..<arguments.count {
let argument = arguments[index]
for argument in arguments {
let argWithDash = "-" + argument.shortFlag

var argIndexes = CommandLine.arguments.enumerated().filter { $0.element == argWithDash }.map { $0.offset }
Expand Down
34 changes: 27 additions & 7 deletions Sources/XCTestHTMLReport/main.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,19 +17,38 @@ var junitEnabled = false
var junit = BlockArgument("j", "junit", required: false, helpMessage: "Provide JUnit XML output") {
junitEnabled = true
}
var result = ValueArgument(.path, "r", "resultBundlePath", required: true, allowsMultiple: true, helpMessage: "Path to a result bundle (allows multiple)")
var renderingMode = Summary.RenderingMode.linking
var inlineAssets = BlockArgument("i", "inlineAssets", required: false, helpMessage: "Inline all assets in the resulting html-file, making it heavier, but more portable") {
var result = ValueArgument(
.path, "r", "resultBundlePath", required: true,
allowsMultiple: true,
helpMessage: "Path to a result bundle (allows multiple)")
var renderingMode = RenderingMode.linking
var inlineAssets = BlockArgument(
"i", "inlineAssets",
required: false,
helpMessage: "Inline all assets in the resulting html-file, making it heavier, but more portable") {
renderingMode = .inline
}
var downsizeImagesEnabled = false
var downsizeImages = BlockArgument("z", "downsize-images", required: false, helpMessage: "Downsize image screenshots") {
var downsizeImages = BlockArgument(
"z", "downsize-images",
required: false,
helpMessage: "Downsize image screenshots to max width of 200 pixels") {
downsizeImagesEnabled = true
}
var deleteUnattachedFilesEnabled = false
var deleteUnattachedFiles = BlockArgument("d", "delete-unattached", required: false, helpMessage: "Delete unattached files from bundle, reducing bundle size") {
var deleteUnattachedFiles = BlockArgument(
"d", "delete-unattached",
required: false,
helpMessage: "Delete unattached files from bundle, reducing bundle size. The bundle will not be renderable in Xcode, so make a copy before applying this change") {
deleteUnattachedFilesEnabled = true
}
var failingTestsOnlyEnabled = false
var failingTestsOnly = BlockArgument(
"f", "failing-tests-only",
required: false,
helpMessage: "Only failng tests will be rendered in the HTML report, This option saves report generation run time when there are a lot of tests in the bundle") {
failingTestsOnlyEnabled = true
}


command.arguments = [help,
Expand All @@ -38,14 +57,15 @@ command.arguments = [help,
downsizeImages,
deleteUnattachedFiles,
result,
inlineAssets]
inlineAssets,
failingTestsOnly]

if !command.isValid {
print(command.usage)
exit(EXIT_FAILURE)
}

let summary = Summary(resultPaths: result.values, renderingMode: renderingMode)
let summary = Summary(resultPaths: result.values, renderingArgs: RenderingArguments(renderingMode: renderingMode, failingTestsOnly: failingTestsOnlyEnabled))

Logger.step("Building HTML..")
let html = summary.generatedHtmlReport()
Expand Down
2 changes: 1 addition & 1 deletion Sources/XCTestHTMLReportCore/Classes/Models/Activity.swift
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ struct Activity: HTML
return cls
}

init(summary: ActionTestActivitySummary, file: ResultFile, padding: Int = 0, renderingMode: Summary.RenderingMode) {
init(summary: ActionTestActivitySummary, file: ResultFile, padding: Int = 0, renderingMode: RenderingMode) {
self.uuid = summary.uuid
self.startTime = summary.start?.timeIntervalSince1970 ?? 0
self.finishTime = summary.finish?.timeIntervalSince1970 ?? 0
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ struct Attachment: HTML
let type: AttachmentType
let name: AttachmentName?

init(attachment: ActionTestAttachment, file: ResultFile, padding: Int = 0, renderingMode: Summary.RenderingMode) {
init(attachment: ActionTestAttachment, file: ResultFile, padding: Int = 0, renderingMode: RenderingMode) {
self.filename = attachment.filename ?? ""
self.type = AttachmentType(rawValue: attachment.uniformTypeIdentifier) ?? .unknown
self.name = attachment.name.map(AttachmentName.init(rawValue:))
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
//
// RenderingArguments.swift
//
//
// Created by Alistair Leszkiewicz on 11/4/21.
//

import Foundation

public struct RenderingArguments {

/// The mode for rendering attachments
public let renderingMode: RenderingMode

/// When `true` the report generation process will exclude passing tests
public let failingTestsOnly: Bool

public init(renderingMode: RenderingMode, failingTestsOnly: Bool) {
self.renderingMode = renderingMode
self.failingTestsOnly = failingTestsOnly
}

}

public enum RenderingMode {
case inline
case linking
}
4 changes: 2 additions & 2 deletions Sources/XCTestHTMLReportCore/Classes/Models/ResultFile.swift
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ class ResultFile {
extension ResultFile {

func exportPayloadContent(id: String,
renderingMode: Summary.RenderingMode) -> RenderingContent {
renderingMode: RenderingMode) -> RenderingContent {
switch renderingMode {
case .inline:
return exportPayloadData(id: id).map(RenderingContent.data) ?? .none
Expand All @@ -108,7 +108,7 @@ extension ResultFile {
}

func exportLogsContent(id: String,
renderingMode: Summary.RenderingMode) -> RenderingContent {
renderingMode: RenderingMode) -> RenderingContent {
switch renderingMode {
case .inline:
return exportLogsData(id: id).map(RenderingContent.data) ?? .none
Expand Down
6 changes: 3 additions & 3 deletions Sources/XCTestHTMLReportCore/Classes/Models/Run.swift
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ struct Run: HTML
return allTests.filter { $0.status == .failure }.count
}

init?(action: ActionRecord, file: ResultFile, renderingMode: Summary.RenderingMode) {
init?(action: ActionRecord, file: ResultFile, renderingArgs: RenderingArguments) {
self.file = file
self.runDestination = RunDestination(record: action.runDestination)

Expand All @@ -62,15 +62,15 @@ struct Run: HTML
if let logReference = action.actionResult.logRef {
self.logContent = file.exportLogsContent(
id: logReference.id,
renderingMode: renderingMode
renderingMode: renderingArgs.renderingMode
)
} else {
Logger.warning("Can't find test reference for action \(action.title ?? "")")
self.logContent = .none
}
self.testSummaries = testPlanSummaries.summaries
.flatMap { $0.testableSummaries }
.map { TestSummary(summary: $0, file: file, renderingMode: renderingMode) }
.compactMap { TestSummary(summary: $0, file: file, renderingArgs: renderingArgs) }
}

private var logSource: String? {
Expand Down
9 changes: 2 additions & 7 deletions Sources/XCTestHTMLReportCore/Classes/Models/Summary.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,7 @@ public struct Summary
{
let runs: [Run]

public enum RenderingMode {
case inline
case linking
}

public init(resultPaths: [String], renderingMode: RenderingMode) {
public init(resultPaths: [String], renderingArgs: RenderingArguments) {
var runs: [Run] = []
for resultPath in resultPaths {
Logger.step("Parsing \(resultPath)")
Expand All @@ -29,7 +24,7 @@ public struct Summary
break
}
let resultRuns = invocationRecord.actions.compactMap {
Run(action: $0, file: resultFile, renderingMode: renderingMode)
Run(action: $0, file: resultFile, renderingArgs: renderingArgs)
}
runs.append(contentsOf: resultRuns)
}
Expand Down
23 changes: 17 additions & 6 deletions Sources/XCTestHTMLReportCore/Classes/Models/Test.swift
Original file line number Diff line number Diff line change
Expand Up @@ -73,35 +73,46 @@ struct Test: HTML
let a = subTests.reduce(0) { $0 + $1.amountSubTests }
return a == 0 ? subTests.count : a
}

var isEmpty: Bool {
return allSubTests.isEmpty && activities.isEmpty
}

init(group: ActionTestSummaryGroup, file: ResultFile, renderingMode: Summary.RenderingMode) {
init?(group: ActionTestSummaryGroup, file: ResultFile, renderingArgs: RenderingArguments) {
self.uuid = NSUUID().uuidString
self.identifier = group.identifier ?? "---identifier-not-found---"
self.duration = group.duration
self.name = group.name ?? "---group-name-not-found---"
if group.subtests.isEmpty {
self.subTests = group.subtestGroups.map { Test(group: $0, file: file, renderingMode: renderingMode) }
self.subTests = group.subtestGroups.compactMap { Test(group: $0, file: file, renderingArgs: renderingArgs) }
} else {
self.subTests = group.subtests.map { Test(metadata: $0, file: file, renderingMode: renderingMode) }
self.subTests = group.subtests.compactMap { Test(metadata: $0, file: file, renderingArgs: renderingArgs) }
}
self.objectClass = .testSummaryGroup
self.activities = []
self.status = .unknown // ???: Usefull?
testScreenshotFlow = TestScreenshotFlow(activities: activities)
if isEmpty {
return nil
}
}

init(metadata: ActionTestMetadata, file: ResultFile, renderingMode: Summary.RenderingMode) {
init?(metadata: ActionTestMetadata, file: ResultFile, renderingArgs: RenderingArguments) {
let status = Status(rawValue: metadata.testStatus) ?? .failure
if status == .success && renderingArgs.failingTestsOnly {
return nil
}
self.uuid = NSUUID().uuidString
self.identifier = metadata.identifier
self.duration = metadata.duration ?? 0
self.name = metadata.name
self.subTests = []
self.status = Status(rawValue: metadata.testStatus) ?? .failure
self.status = status
self.objectClass = .testSummary
if let id = metadata.summaryRef?.id,
let actionTestSummary = file.getActionTestSummary(id: id) {
self.activities = actionTestSummary.activitySummaries.map {
Activity(summary: $0, file: file, padding: 20, renderingMode: renderingMode)
Activity(summary: $0, file: file, padding: 20, renderingMode: renderingArgs.renderingMode)
}
} else {
self.activities = []
Expand Down
11 changes: 9 additions & 2 deletions Sources/XCTestHTMLReportCore/Classes/Models/TestSummary.swift
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,18 @@ struct TestSummary: HTML

return status
}

var isEmpty: Bool {
return tests.isEmpty
}

init(summary: ActionTestableSummary, file: ResultFile, renderingMode: Summary.RenderingMode) {
init?(summary: ActionTestableSummary, file: ResultFile, renderingArgs: RenderingArguments) {
self.uuid = UUID().uuidString
self.testName = summary.targetName ?? ""
self.tests = summary.tests.map { Test(group: $0, file: file, renderingMode: renderingMode) }
self.tests = summary.tests.compactMap { Test(group: $0, file: file, renderingArgs: renderingArgs) }
if isEmpty {
return nil
}
}

// PRAGMA MARK: - HTML
Expand Down
2 changes: 1 addition & 1 deletion Tests/XCTestHTMLReportTests/SummaryTests.swift