@@ -14,10 +14,10 @@ import AsyncAlgorithms
1414import AsyncSequenceValidation
1515
1616extension XCTestCase {
17- func recordFailure( _ description: String , detail : String ? = nil , system: Bool = false , at location: AsyncSequenceValidation . SourceLocation ) {
17+ func recordFailure( _ description: String , system: Bool = false , at location: AsyncSequenceValidation . SourceLocation ) {
1818#if canImport(Darwin)
1919 let context = XCTSourceCodeContext ( location: XCTSourceCodeLocation ( filePath: location. file. description, lineNumber: Int ( location. line) ) )
20- let issue = XCTIssue ( type: system ? . system : . assertionFailure, compactDescription: description, detailedDescription: detail , sourceCodeContext: context, associatedError: nil , attachments: [ ] )
20+ let issue = XCTIssue ( type: system ? . system : . assertionFailure, compactDescription: description, detailedDescription: nil , sourceCodeContext: context, associatedError: nil , attachments: [ ] )
2121 record ( issue)
2222#else
2323 XCTFail ( description, file: location. file, line: location. line)
@@ -26,32 +26,36 @@ extension XCTestCase {
2626
2727 func validate< Test: AsyncSequenceValidationTest , Theme: AsyncSequenceValidationTheme > ( theme: Theme , expectedFailures: Set < String > , @AsyncSequenceValidationDiagram _ build: ( AsyncSequenceValidationDiagram ) -> Test , file: StaticString = #file, line: UInt = #line) {
2828 var expectations = expectedFailures
29+ var result : AsyncSequenceValidationDiagram . ExpectationResult ?
30+ var failures = [ AsyncSequenceValidationDiagram . ExpectationFailure] ( )
2931 let baseLoc = AsyncSequenceValidation . SourceLocation ( file: file, line: line)
32+ var accountedFailures = [ AsyncSequenceValidationDiagram . ExpectationFailure] ( )
3033 do {
31- let ( result, failures) = try AsyncSequenceValidationDiagram . test ( theme: theme, build)
32- var detail : String ?
33- if failures. count > 0 {
34- detail = """
35- Expected
36- \( result. reconstituteExpected ( theme: theme) )
37- Actual
38- \( result. reconstituteActual ( theme: theme) )
39- """
40- print ( " Expected " )
41- print ( result. reconstituteExpected ( theme: theme) )
42- print ( " Actual " )
43- print ( result. reconstituteActual ( theme: theme) )
44- }
34+ ( result, failures) = try AsyncSequenceValidationDiagram . test ( theme: theme, build)
4535 for failure in failures {
4636 if expectations. remove ( failure. description) == nil {
47- recordFailure ( failure. description, detail: detail, at: failure. specification? . location ?? baseLoc)
37+ recordFailure ( failure. description, at: failure. specification? . location ?? baseLoc)
38+ } else {
39+ accountedFailures. append ( failure)
4840 }
4941 }
5042 } catch {
5143 if expectations. remove ( " \( error) " ) == nil {
5244 recordFailure ( " \( error) " , system: true , at: ( error as? SourceFailure ) ? . location ?? baseLoc)
5345 }
5446 }
47+ // If no failures were expected and the result reconstitues to something different
48+ // than what was expected, dump that out as a failure for easier diagnostics, this
49+ // likely should be done via attachments but that does not display inline code
50+ // nicely. Ideally we would want to have this display as a runtime warning but those
51+ // do not have source line attribution; for now XCTFail is good enough.
52+ if let result = result, expectedFailures. count == 0 {
53+ let expected = result. reconstituteExpected ( theme: theme)
54+ let actual = result. reconstituteActual ( theme: theme)
55+ if expected != actual {
56+ XCTFail ( " Validation failure: \n Expected: \n \( expected) \n Actual: \n \( actual) " , file: file, line: line)
57+ }
58+ }
5559 // any remaining expectations are failures that were expected but did not happen
5660 for expectation in expectations {
5761 XCTFail ( " Expected failure: \( expectation) did not occur. " , file: file, line: line)
0 commit comments