Skip to content

Commit

Permalink
[FEATURE] Sort screenshots into language/region-based folders (#37)
Browse files Browse the repository at this point in the history
Change Description: These changes implement #34 to allow for sorting the screenshots/attachments based off of the language and/or region that the device ran in. Use case for this would be for folks who want to run tests across multiple test plan configurations (perhaps because the configuration enables certain features, simulates the GPS coordinate in a particular area, etc.) but want to group the screenshots back into localization buckets for easy review by language experts/localizers.

With these changes, the new boolean flags of --language & --region have been added. If the language flag is specified, we create folders using the language name if it was specified or use "System Default" if the language was the device's system language. Region behaves similarly. If both language & region are specified, the folder is made with the format "language (region)" similar to what we do when both --model and --os are specified.

Test Plan/Testing Performed: Tested that with these changes, I can now get screenshots from my configurations with German language all in one folder ("xcparse screenshots --language --region ./Test.xcresult ./screenshots") & separate from my Korean language configs.
  • Loading branch information
abotkin-cpi authored Nov 22, 2019
1 parent c9c4cfc commit 0d05b69
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 14 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ Options available include:
| ```--model``` | Divide by test target model |
| ```--os``` | Divide by test target operating system |
| ```--test-plan-config``` | Divide by test run configuration |
| ```--language``` | Divide by test language |
| ```--region``` | Divide by test region |
| ```--test``` | Divide by test |

See ```xcparse screenshots --help``` for a full-listing
Expand Down
6 changes: 6 additions & 0 deletions Sources/xcparse/AttachmentsCommand.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ struct AttachmentsCommand: Command {
var divideByOS: OptionArgument<Bool>
var divideByTestRun: OptionArgument<Bool>
var divideByTestPlanConfig: OptionArgument<Bool>
var divideByLanguage: OptionArgument<Bool>
var divideByRegion: OptionArgument<Bool>
var divideByTest: OptionArgument<Bool>

var utiWhitelist: OptionArgument<[String]>
Expand All @@ -40,6 +42,8 @@ struct AttachmentsCommand: Command {
divideByOS = subparser.add(option: "--os", shortName: nil, kind: Bool.self, usage: "Divide attachments by OS")
divideByTestRun = subparser.add(option: "--test-run", shortName: nil, kind: Bool.self, usage: "Deprecated. Use --test-plan-config")
divideByTestPlanConfig = subparser.add(option: "--test-plan-config", shortName: nil, kind: Bool.self, usage: "Divide attachments by test plan configuration")
divideByLanguage = subparser.add(option: "--language", shortName: nil, kind: Bool.self, usage: "Divide attachments by test language")
divideByRegion = subparser.add(option: "--region", shortName: nil, kind: Bool.self, usage: "Divide attachments by test region")
divideByTest = subparser.add(option: "--test", shortName: nil, kind: Bool.self, usage: "Divide attachments by test")

utiWhitelist = subparser.add(option: "--uti", shortName: nil, kind: [String].self, strategy: .upToNextOption,
Expand Down Expand Up @@ -79,6 +83,8 @@ struct AttachmentsCommand: Command {
divideByTargetModel: arguments.get(self.divideByModel) ?? false,
divideByTargetOS: arguments.get(self.divideByOS) ?? false,
divideByTestPlanConfig: arguments.get(self.divideByTestPlanConfig) ?? (arguments.get(self.divideByTestRun) ?? false),
divideByLanguage: arguments.get(self.divideByLanguage) ?? false,
divideByRegion: arguments.get(self.divideByRegion) ?? false,
divideByTest: arguments.get(self.divideByTest) ?? false)
if let allowedUTIsToExport = arguments.get(self.utiWhitelist) {
options.attachmentFilter = {
Expand Down
6 changes: 6 additions & 0 deletions Sources/xcparse/ScreenshotsCommand.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ struct ScreenshotsCommand: Command {
var divideByOS: OptionArgument<Bool>
var divideByTestRun: OptionArgument<Bool>
var divideByTestPlanConfig: OptionArgument<Bool>
var divideByLanguage: OptionArgument<Bool>
var divideByRegion: OptionArgument<Bool>
var divideByTest: OptionArgument<Bool>

var testStatusWhitelist: OptionArgument<[String]>
Expand All @@ -42,6 +44,8 @@ struct ScreenshotsCommand: Command {
divideByOS = subparser.add(option: "--os", shortName: nil, kind: Bool.self, usage: "Divide screenshots by OS")
divideByTestRun = subparser.add(option: "--test-run", shortName: nil, kind: Bool.self, usage: "Deprecated. Use --test-plan-config")
divideByTestPlanConfig = subparser.add(option: "--test-plan-config", shortName: nil, kind: Bool.self, usage: "Divide attachments by test plan configuration")
divideByLanguage = subparser.add(option: "--language", shortName: nil, kind: Bool.self, usage: "Divide attachments by test language")
divideByRegion = subparser.add(option: "--region", shortName: nil, kind: Bool.self, usage: "Divide attachments by test region")
divideByTest = subparser.add(option: "--test", shortName: nil, kind: Bool.self, usage: "Divide screenshots by test")

testStatusWhitelist = subparser.add(option: "--test-status", shortName: nil, kind: [String].self, strategy: .upToNextOption,
Expand Down Expand Up @@ -81,6 +85,8 @@ struct ScreenshotsCommand: Command {
divideByTargetModel: arguments.get(self.divideByModel) ?? false,
divideByTargetOS: arguments.get(self.divideByOS) ?? false,
divideByTestPlanConfig: arguments.get(self.divideByTestPlanConfig) ?? (arguments.get(self.divideByTestRun) ?? false),
divideByLanguage: arguments.get(self.divideByLanguage) ?? false,
divideByRegion: arguments.get(self.divideByRegion) ?? false,
divideByTest: arguments.get(self.divideByTest) ?? false,
attachmentFilter: {
return UTTypeConformsTo($0.uniformTypeIdentifier as CFString, "public.image" as CFString)
Expand Down
63 changes: 49 additions & 14 deletions Sources/xcparse/XCPParser.swift
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@ struct AttachmentExportOptions {
var divideByTargetModel: Bool = false
var divideByTargetOS: Bool = false
var divideByTestPlanConfig: Bool = false
var divideByLanguage: Bool = false
var divideByRegion: Bool = false
var divideByTest: Bool = false

var xcresulttoolCompatability = XCResultToolCompatability()
Expand Down Expand Up @@ -141,6 +143,31 @@ struct AttachmentExportOptions {
}
}

func screenshotDirectoryURL(_ testableSummary: ActionTestableSummary, forBaseURL baseURL: Foundation.URL) -> Foundation.URL {
var languageRegionDirectoryName: String? = nil

let testLanguage = testableSummary.testLanguage ?? "System Language"
let testRegion = testableSummary.testRegion ?? "System Region"
if self.divideByLanguage == true, self.divideByRegion == true {
languageRegionDirectoryName = "\(testLanguage) (\(testRegion))"
} else if self.divideByLanguage == true {
languageRegionDirectoryName = testLanguage
} else if self.divideByRegion == true {
languageRegionDirectoryName = testRegion
}

if let folderName = languageRegionDirectoryName {
if self.xcresulttoolCompatability.supportsUnicodeExportPaths != true {
let asciiFolderName = folderName.lossyASCIIString() ?? folderName
return baseURL.appendingPathComponent(asciiFolderName, isDirectory: true)
} else {
return baseURL.appendingPathComponent(folderName, isDirectory: true)
}
} else {
return baseURL
}
}

func screenshotDirectoryURL(_ testSummary: ActionTestSummary, forBaseURL baseURL: Foundation.URL) -> Foundation.URL {
guard let summaryIdentifier = testSummary.identifier else {
return baseURL
Expand Down Expand Up @@ -242,25 +269,33 @@ class XCPParser {
}

let testableSummaries = testPlanRun.testableSummaries
let testableSummariesToTestActivity = testableSummaries.flatMap { $0.flattenedTestSummaryMap(withXCResult: xcresult) }
for (testableSummary, childActivitySummaries) in testableSummariesToTestActivity {
if options.testSummaryFilter(testableSummary) == false {
for testableSummary in testableSummaries {
let testableSummaryScreenshotDirectoryURL = options.screenshotDirectoryURL(testableSummary, forBaseURL: testPlanRunScreenshotURL)
if testableSummaryScreenshotDirectoryURL.createDirectoryIfNecessary() != true {
continue
}

let filteredChildActivities = childActivitySummaries.filter(options.activitySummaryFilter)
let filteredAttachments = filteredChildActivities.flatMap { $0.attachments.filter(options.attachmentFilter) }

let testableSummaryScreenshotURL = options.screenshotDirectoryURL(testableSummary, forBaseURL: testPlanRunScreenshotURL)
if testableSummaryScreenshotURL.createDirectoryIfNecessary(createIntermediates: true) != true {
continue
let testableSummariesToTestActivity = testableSummary.flattenedTestSummaryMap(withXCResult: xcresult)
for (testSummary, childActivitySummaries) in testableSummariesToTestActivity {
if options.testSummaryFilter(testSummary) == false {
continue
}

let filteredChildActivities = childActivitySummaries.filter(options.activitySummaryFilter)
let filteredAttachments = filteredChildActivities.flatMap { $0.attachments.filter(options.attachmentFilter) }

let testSummaryScreenshotURL = options.screenshotDirectoryURL(testSummary, forBaseURL: testableSummaryScreenshotDirectoryURL)
if testSummaryScreenshotURL.createDirectoryIfNecessary(createIntermediates: true) != true {
continue
}

// Now that we know what we want to export, save it to the dictionary so we can have all the exports
// done at once with one progress bar per URL
var existingAttachmentsForURL = exportURLsToAttachments[testSummaryScreenshotURL.path] ?? []
existingAttachmentsForURL.append(contentsOf: filteredAttachments)
exportURLsToAttachments[testSummaryScreenshotURL.path] = existingAttachmentsForURL
}

// Now that we know what we want to export, save it to the dictionary so we can have all the exports
// done at once with one progress bar per URL
var existingAttachmentsForURL = exportURLsToAttachments[testableSummaryScreenshotURL.path] ?? []
existingAttachmentsForURL.append(contentsOf: filteredAttachments)
exportURLsToAttachments[testableSummaryScreenshotURL.path] = existingAttachmentsForURL
}
}
}
Expand Down

0 comments on commit 0d05b69

Please sign in to comment.