Skip to content

Commit e7fd368

Browse files
authored
Merge pull request #702 from f3dm76/fix/test-references
Fix test references
2 parents 8319462 + 3755512 commit e7fd368

File tree

139 files changed

+222
-61
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

139 files changed

+222
-61
lines changed

Macaw.xcodeproj/xcshareddata/xcschemes/MacawTests.xcscheme

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,22 @@
55
<BuildAction
66
parallelizeBuildables = "YES"
77
buildImplicitDependencies = "YES">
8+
<BuildActionEntries>
9+
<BuildActionEntry
10+
buildForTesting = "YES"
11+
buildForRunning = "YES"
12+
buildForProfiling = "YES"
13+
buildForArchiving = "YES"
14+
buildForAnalyzing = "YES">
15+
<BuildableReference
16+
BuildableIdentifier = "primary"
17+
BlueprintIdentifier = "57FCD26B1D76EA4600CC0FB6"
18+
BuildableName = "Macaw.framework"
19+
BlueprintName = "Macaw"
20+
ReferencedContainer = "container:Macaw.xcodeproj">
21+
</BuildableReference>
22+
</BuildActionEntry>
23+
</BuildActionEntries>
824
</BuildAction>
925
<TestAction
1026
buildConfiguration = "Debug"
@@ -23,8 +39,6 @@
2339
</BuildableReference>
2440
</TestableReference>
2541
</Testables>
26-
<AdditionalOptions>
27-
</AdditionalOptions>
2842
</TestAction>
2943
<LaunchAction
3044
buildConfiguration = "Debug"
@@ -36,15 +50,22 @@
3650
debugDocumentVersioning = "YES"
3751
debugServiceExtension = "internal"
3852
allowLocationSimulation = "YES">
39-
<AdditionalOptions>
40-
</AdditionalOptions>
4153
</LaunchAction>
4254
<ProfileAction
4355
buildConfiguration = "Release"
4456
shouldUseLaunchSchemeArgsEnv = "YES"
4557
savedToolIdentifier = ""
4658
useCustomWorkingDirectory = "NO"
4759
debugDocumentVersioning = "YES">
60+
<MacroExpansion>
61+
<BuildableReference
62+
BuildableIdentifier = "primary"
63+
BlueprintIdentifier = "57FCD26B1D76EA4600CC0FB6"
64+
BuildableName = "Macaw.framework"
65+
BlueprintName = "Macaw"
66+
ReferencedContainer = "container:Macaw.xcodeproj">
67+
</BuildableReference>
68+
</MacroExpansion>
4869
</ProfileAction>
4970
<AnalyzeAction
5071
buildConfiguration = "Debug">

MacawTests/MacawSVGTests.swift

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,13 @@ class MacawSVGTests: XCTestCase {
2020
private let testFolderName = "MacawTestOutputData"
2121
private let shouldComparePNGImages = true
2222
private let multipleTestsWillRun = false
23-
private let shouldSaveFaildedTestImage = false
23+
private let shouldSaveFailedTestImage = false
2424

2525
override func setUp() {
2626
// Put setup code here. This method is called before the invocation of each test method in the class.
2727
super.setUp()
2828

29-
if shouldSaveFaildedTestImage {
29+
if shouldSaveFailedTestImage {
3030
setupTestFolderDirectory()
3131
}
3232
}
@@ -36,14 +36,29 @@ class MacawSVGTests: XCTestCase {
3636
super.tearDown()
3737
}
3838

39+
func compareResults(nodeContent: String?, referenceContent: String?) {
40+
guard let nodeContent = nodeContent else {
41+
XCTFail("nodeContent is empty")
42+
return
43+
}
44+
guard let referenceContent = referenceContent else {
45+
XCTFail("referenceContent is empty")
46+
return
47+
}
48+
49+
if nodeContent != referenceContent {
50+
XCTFail("nodeContent is not equal to referenceContent" + TestUtils.prettyFirstDifferenceBetweenStrings(s1: nodeContent, s2: referenceContent))
51+
}
52+
}
53+
3954
func validate(node: Node, referenceFile: String) {
4055
let bundle = Bundle(for: type(of: TestUtils()))
4156

4257
do {
4358
if let path = bundle.path(forResource: referenceFile, ofType: "reference") {
4459
let clipReferenceContent = try String.init(contentsOfFile: path).trimmingCharacters(in: .newlines)
4560
let result = SVGSerializer.serialize(node: node)
46-
XCTAssertEqual(result, clipReferenceContent)
61+
compareResults(nodeContent: result, referenceContent: clipReferenceContent)
4762
} else {
4863
XCTFail("No file \(referenceFile)")
4964
}
@@ -192,13 +207,10 @@ class MacawSVGTests: XCTestCase {
192207
let bundle = Bundle(for: type(of: TestUtils()))
193208
do {
194209
if let path = bundle.path(forResource: referenceFile, ofType: "reference") {
210+
195211
let referenceContent = try String(contentsOfFile: path)
196-
197212
let nodeContent = String(data: getJSONData(node: node), encoding: String.Encoding.utf8)
198-
199-
if nodeContent != referenceContent {
200-
XCTFail("nodeContent is not equal to referenceContent")
201-
}
213+
compareResults(nodeContent: nodeContent, referenceContent: referenceContent)
202214

203215
let nativeImage = getImage(from: referenceFile)
204216

@@ -261,9 +273,9 @@ class MacawSVGTests: XCTestCase {
261273

262274
if referenceContentData != nodeContentData {
263275

264-
var failInfo = "referenceContentData is not equal to nodeContentData"
276+
var failInfo = "referenceImageData is not equal to nodeImageData"
265277

266-
if shouldSaveFaildedTestImage {
278+
if shouldSaveFailedTestImage {
267279
let _ = saveImage(image: referenceImage, fileName: referenceFile + "_reference")
268280
let _ = saveImage(image: nodeImage, fileName: referenceFile + "_incorrect")
269281

@@ -314,7 +326,7 @@ class MacawSVGTests: XCTestCase {
314326
}
315327

316328
func writeToFile(string: String, fileName: String) -> URL? {
317-
guard let directory = try? FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false) as NSURL else {
329+
guard let directory = try? FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true) as NSURL else {
318330
return .none
319331
}
320332
do {

MacawTests/TestUtils.swift

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,4 +25,133 @@ class TestUtils {
2525
return result
2626
}
2727

28+
class func prettyFirstDifferenceBetweenStrings(s1: String, s2: String) -> String {
29+
return prettyFirstDifferenceBetweenNSStrings(s1: s1 as NSString, s2: s2 as NSString) as String
30+
}
31+
32+
}
33+
34+
/// Find first differing character between two strings
35+
///
36+
/// :param: s1 First String
37+
/// :param: s2 Second String
38+
///
39+
/// :returns: .DifferenceAtIndex(i) or .NoDifference
40+
fileprivate func firstDifferenceBetweenStrings(s1: NSString, s2: NSString) -> FirstDifferenceResult {
41+
let len1 = s1.length
42+
let len2 = s2.length
43+
44+
let lenMin = min(len1, len2)
45+
46+
for i in 0..<lenMin {
47+
if s1.character(at: i) != s2.character(at: i) {
48+
return .DifferenceAtIndex(i)
49+
}
50+
}
51+
52+
if len1 < len2 {
53+
return .DifferenceAtIndex(len1)
54+
}
55+
56+
if len2 < len1 {
57+
return .DifferenceAtIndex(len2)
58+
}
59+
60+
return .NoDifference
61+
}
62+
63+
64+
/// Create a formatted String representation of difference between strings
65+
///
66+
/// :param: s1 First string
67+
/// :param: s2 Second string
68+
///
69+
/// :returns: a string, possibly containing significant whitespace and newlines
70+
fileprivate func prettyFirstDifferenceBetweenNSStrings(s1: NSString, s2: NSString) -> NSString {
71+
let firstDifferenceResult = firstDifferenceBetweenStrings(s1: s1, s2: s2)
72+
return prettyDescriptionOfFirstDifferenceResult(firstDifferenceResult: firstDifferenceResult, s1: s1, s2: s2)
73+
}
74+
75+
76+
/// Create a formatted String representation of a FirstDifferenceResult for two strings
77+
///
78+
/// :param: firstDifferenceResult FirstDifferenceResult
79+
/// :param: s1 First string used in generation of firstDifferenceResult
80+
/// :param: s2 Second string used in generation of firstDifferenceResult
81+
///
82+
/// :returns: a printable string, possibly containing significant whitespace and newlines
83+
fileprivate func prettyDescriptionOfFirstDifferenceResult(firstDifferenceResult: FirstDifferenceResult, s1: NSString, s2: NSString) -> NSString {
84+
85+
func diffString(index: Int, s1: NSString, s2: NSString) -> NSString {
86+
let markerArrow = "\u{2b06}" // "⬆"
87+
let ellipsis = "\u{2026}" // "…"
88+
/// Given a string and a range, return a string representing that substring.
89+
///
90+
/// If the range starts at a position other than 0, an ellipsis
91+
/// will be included at the beginning.
92+
///
93+
/// If the range ends before the actual end of the string,
94+
/// an ellipsis is added at the end.
95+
func windowSubstring(s: NSString, range: NSRange) -> String {
96+
let validRange = NSMakeRange(range.location, min(range.length, s.length - range.location))
97+
let substring = s.substring(with: validRange)
98+
99+
let prefix = range.location > 0 ? ellipsis : ""
100+
let suffix = (s.length - range.location > range.length) ? ellipsis : ""
101+
102+
return "\(prefix)\(substring)\(suffix)"
103+
}
104+
105+
// Show this many characters before and after the first difference
106+
let windowPrefixLength = 10
107+
let windowSuffixLength = 10
108+
let windowLength = windowPrefixLength + 1 + windowSuffixLength
109+
110+
let windowIndex = max(index - windowPrefixLength, 0)
111+
let windowRange = NSMakeRange(windowIndex, windowLength)
112+
113+
let sub1 = windowSubstring(s: s1, range: windowRange)
114+
let sub2 = windowSubstring(s: s2, range: windowRange)
115+
116+
let markerPosition = min(windowSuffixLength, index) + (windowIndex > 0 ? 1 : 0)
117+
118+
let markerPrefix = String(repeating: " ", count: markerPosition)
119+
let markerLine = "\(markerPrefix)\(markerArrow)"
120+
121+
return "Difference at index \(index):\n\(sub1)\n\(sub2)\n\(markerLine)" as NSString
122+
}
123+
124+
switch firstDifferenceResult {
125+
case .NoDifference: return "No difference"
126+
case .DifferenceAtIndex(let index): return diffString(index: index, s1: s1, s2: s2)
127+
}
128+
}
129+
130+
/// Result type for firstDifferenceBetweenStrings()
131+
public enum FirstDifferenceResult {
132+
/// Strings are identical
133+
case NoDifference
134+
135+
/// Strings differ at the specified index.
136+
///
137+
/// This could mean that characters at the specified index are different,
138+
/// or that one string is longer than the other
139+
case DifferenceAtIndex(Int)
140+
}
141+
142+
extension FirstDifferenceResult: CustomStringConvertible {
143+
/// Textual representation of a FirstDifferenceResult
144+
public var description: String {
145+
switch self {
146+
case .NoDifference:
147+
return "NoDifference"
148+
case .DifferenceAtIndex(let index):
149+
return "DifferenceAtIndex(\(index))"
150+
}
151+
}
152+
153+
/// Textual representation of a FirstDifferenceResult for debugging purposes
154+
public var debugDescription: String {
155+
return self.description
156+
}
28157
}
0 Bytes
0 Bytes
0 Bytes
0 Bytes
0 Bytes
0 Bytes
0 Bytes

0 commit comments

Comments
 (0)