@@ -3,29 +3,15 @@ import UIKit
33
44/// The testing tool which generates snapshot images from scenarios managed by `Playbook`.
55public struct Snapshot : TestTool {
6- /// A base directory for exporting snapshot image files.
7- public var directory : URL
8-
9- /// Specifies whether that to clean directory before generating snapshots.
10- public var clean : Bool
11-
12- /// An image file format of exported data.
13- public var format : SnapshotSupport . ImageFormat
14-
15- /// A timeout interval until the finish snapshot of all scenarios.
16- public var timeout : TimeInterval
17-
18- /// A rendering scale of the snapshot image.
19- public var scale : CGFloat
20-
21- /// The key window of the application.
22- public weak var keyWindow : UIWindow ?
23-
24- /// A set of snapshot environment simulating devices.
25- public var devices : [ SnapshotDevice ]
26-
27- /// A closure to preprocess scenario UIView before generating snapshot.
28- public var viewPreprocessor : ( ( UIView ) -> UIView ) ?
6+ private let directory : URL
7+ private let clean : Bool
8+ private let format : SnapshotSupport . ImageFormat
9+ private let timeout : TimeInterval
10+ private let scale : CGFloat
11+ private let keyWindow : UIWindow ?
12+ private let devices : [ SnapshotDevice ]
13+ private let logOutput : TextOutputStream ?
14+ private let viewPreprocessor : ( ( UIView ) -> UIView ) ?
2915
3016 /// Creates a new snapshot tool for export all image files into specified directory.
3117 ///
@@ -46,6 +32,7 @@ public struct Snapshot: TestTool {
4632 scale: CGFloat = UIScreen . main. scale,
4733 keyWindow: UIWindow ? = nil ,
4834 devices: [ SnapshotDevice ] ,
35+ logOutput: TextOutputStream ? = nil ,
4936 viewPreprocessor: ( ( UIView ) -> UIView ) ? = nil
5037 ) {
5138 self . directory = directory
@@ -55,6 +42,7 @@ public struct Snapshot: TestTool {
5542 self . scale = scale
5643 self . keyWindow = keyWindow
5744 self . devices = devices
45+ self . logOutput = logOutput
5846 self . viewPreprocessor = viewPreprocessor
5947 }
6048
@@ -64,11 +52,8 @@ public struct Snapshot: TestTool {
6452 /// - playbook: A `Playbook` instance to be tested.
6553 public func run( with playbook: Playbook ) throws {
6654 let timeoutTimestamp = Date . timeIntervalSinceReferenceDate + timeout
67-
6855 let group = DispatchGroup ( )
69-
7056 let fileManager = FileManager . default
71-
7257 let directoryURL = URL ( fileURLWithPath: directory. path, isDirectory: true )
7358
7459 if clean && fileManager. fileExists ( atPath: directoryURL. path) {
@@ -86,21 +71,21 @@ public struct Snapshot: TestTool {
8671
8772 try fileManager. createDirectory ( at: directoryURL, withIntermediateDirectories: true )
8873
89- func attemptToWrite ( data : Data , scenario: Scenario ) {
74+ for scenario in store . scenarios {
9075 let fileURL =
9176 directoryURL
9277 . appendingPathComponent ( normalize ( scenario. title. rawValue) )
9378 . appendingPathExtension ( format. fileExtension)
9479
95- do {
96- try data. write ( to: fileURL)
97- }
98- catch {
99- writingFailureURLs. append ( fileURL)
100- }
101- }
80+ log (
81+ """
82+ Generating snapshot for:
83+ - Device: \( device. name. rawString)
84+ - Category: \( store. category. rawValue. rawString)
85+ - Scenario: \( scenario. title. rawValue. rawString)
86+ """
87+ )
10288
103- for scenario in store. scenarios {
10489 group. enter ( )
10590
10691 SnapshotSupport . data (
@@ -111,7 +96,20 @@ public struct Snapshot: TestTool {
11196 keyWindow: keyWindow,
11297 viewPreprocessor: viewPreprocessor,
11398 handler: { data in
114- attemptToWrite ( data: data, scenario: scenario)
99+ do {
100+ try data. write ( to: fileURL)
101+ log ( " Generated in \( fileURL. absoluteString) " )
102+ }
103+ catch {
104+ log (
105+ """
106+ Failed to write the snapshot in \( fileURL. absoluteString)
107+ Error: \( error)
108+ """
109+ )
110+ writingFailureURLs. append ( fileURL)
111+ }
112+
115113 group. leave ( )
116114 }
117115 )
@@ -133,14 +131,14 @@ public struct Snapshot: TestTool {
133131 let timeIntervalToRun = min ( 0.1 , remaining)
134132
135133 if timeIntervalToRun <= 0 {
136- throw SnapshotError . timeout ( timeout)
134+ try log ( error : . timeout( timeout) )
137135 }
138136
139137 runLoop. run ( mode: . default, before: Date ( timeIntervalSinceNow: timeIntervalToRun) )
140138 }
141139
142- guard writingFailureURLs. isEmpty else {
143- throw SnapshotError . fileWritingFailure ( urls: writingFailureURLs)
140+ if ! writingFailureURLs. isEmpty {
141+ try log ( error : . fileWritingFailure( urls: writingFailureURLs) )
144142 }
145143 }
146144}
@@ -154,4 +152,26 @@ private extension Snapshot {
154152 func normalize( _ string: String ) -> String {
155153 string. components ( separatedBy: Self . nameNormalizationCharacters) . joined ( separator: " _ " )
156154 }
155+
156+ func log( error: SnapshotError ) throws {
157+ log ( error. debugDescription)
158+ throw error
159+ }
160+
161+ func log( _ message: String ) {
162+ let log = " [Playbook] \( message) "
163+
164+ if var logOutput {
165+ logOutput. write ( log)
166+ }
167+ else {
168+ print ( log)
169+ }
170+ }
171+ }
172+
173+ private extension String {
174+ var rawString : String {
175+ unicodeScalars. reduce ( into: " " ) { $0 += $1. escaped ( asASCII: true ) }
176+ }
157177}
0 commit comments