@@ -96,19 +96,77 @@ type TestResult =
9696 | Failed of Path * string * exn
9797 | Pending of Path * string
9898
99+ type ITestReporter =
100+ abstract BeginSuite : name : string * level : int -> unit
101+ abstract ReportResult : result : TestResult * level : int -> unit
102+ abstract EndSuite : name : string * level : int -> unit
103+ abstract Info : message : string * indent : string * indentCount : int -> unit
104+ abstract Debug : message : string * indent : string * indentCount : int -> unit
105+ abstract End : TestResult list -> unit
106+
107+ type ConsoleReporter () =
108+ let sw = Stopwatch.StartNew()
109+ interface ITestReporter with
110+ member _.BeginSuite ( name , level ) =
111+ let indent = String.replicate ( level * 2 ) " "
112+ printfn $" {indent}{AnsiColours.green}{name}{AnsiColours.reset}"
113+
114+ member _.ReportResult ( result , level ) =
115+ let indent = String.replicate ( level * 2 ) " "
116+ match result with
117+ | Passed (_, name) ->
118+ printfn $" %s {indent}%s {AnsiColours.green} ✅ passed: %s {name}%s {AnsiColours.reset}"
119+ | Failed (_, name, ex) ->
120+ printfn $" %s {indent}%s {AnsiColours.red} ❌ failed: %s {name} - %s {ex.Message}%s {AnsiColours.reset}"
121+ | Pending (_, name) ->
122+ printfn $" %s {indent}%s {AnsiColours.grey} ❔ pending: %s {name}%s {AnsiColours.reset}"
123+
124+ member _.EndSuite ( _ , _ ) = ()
125+ member _.Debug ( message : string , indent : string , indentCount : int ): unit =
126+ let indent = String.replicate ( indentCount * 2 ) indent
127+ printfn $" %s {indent}%s {AnsiColours.grey}%s {message}%s {AnsiColours.reset}"
128+ member _.Info ( message : string , indent : string , indentCount : int ): unit =
129+ let indent = String.replicate ( indentCount * 2 ) indent
130+ printfn $" %s {indent}%s {AnsiColours.grey}%s {message}%s {AnsiColours.reset}"
131+ member _.End ( testResults : TestResult list ): unit =
132+ printfn $" got %d {List.length testResults} test results"
133+ testResults |> List.iter ( function
134+ // | Passed (path, name) ->
135+ // let pathString = String.concat " / " path.Value
136+ // context.Log $"Test passed: %s{AnsiColours.green}%s{pathString} - %s{name}%s{AnsiColours.reset}"
137+ | Failed ( path, name, ex) ->
138+ let pathString = String.concat " / " path.Value
139+ printfn $" Test failed: %s {AnsiColours.red}%s {pathString} / %s {name} - %s {ex.Message}%s {AnsiColours.reset}"
140+ // | Pending (path, name) ->
141+ // let pathString = String.concat " / " path.Value
142+ // context.Log $"Test pending: %s{AnsiColours.grey}%s{pathString} / %s{name}%s{AnsiColours.reset}")
143+ | _ -> ())
144+
145+ // Count results
146+ let passedCount = testResults |> List.filter ( function Passed _ -> true | _ -> false ) |> List.length
147+ let failedCount = testResults |> List.filter ( function Failed _ -> true | _ -> false ) |> List.length
148+ let pendingCount = testResults |> List.filter ( function Pending _ -> true | _ -> false ) |> List.length
149+
150+ printfn $" Summary: {passedCount} passed, {failedCount} failed, {pendingCount} pending"
151+ printfn $" Total time: %s {sw.Elapsed.ToString()}"
152+
99153type TestContext = {
100154 Path: Path
101155 ParentBeforeHooks: HookFunction list
102156 ParentAfterHooks: HookFunction list
103- IndentString: string
157+ Reporter: ITestReporter
158+ Indent: string
159+ IndentCount: int
104160 Log: string -> unit
105161}
106162with
107163 static member Empty = {
108164 Path = Path []
109165 ParentBeforeHooks = []
110166 ParentAfterHooks = []
111- IndentString = " "
167+ Indent = " "
168+ IndentCount = 2
169+ Reporter = ConsoleReporter() :> ITestReporter
112170 Log = printfn " %s "
113171 }
114172
@@ -125,20 +183,18 @@ let runTestCase path (testCase: It): TestResult =
125183 | None ->
126184 Pending ( path, testCase.Name)
127185
128- let rec doRunTestSuite ( sb : Describe ) ( context : TestContext ) =
129- let indentStr = String.replicate context.Path.Length context.IndentString
130-
186+ let rec doRunTestSuite ( suite : Describe ) ( context : TestContext ) =
131187 // setup logging functions
132188 let info ' , debug' = info, debug
133189 use _ = { new System.IDisposable with
134190 member _.Dispose () = info <- info'; debug <- debug' }
135- info <- fun s -> context.Log $ " %s {indentStr} %s {s} "
136- debug <- fun s -> context.Log $ " %s {indentStr} %s {AnsiColours.grey} %s {s} %s {AnsiColours.reset} "
191+ info <- fun s -> context.Reporter.Info ( s , context.Indent , context.IndentCount )
192+ debug <- fun s -> context.Reporter.Debug ( s , context.Indent , context.IndentCount )
137193
138- info $ " %s {indentStr} %s {sb. Name} "
194+ context.Reporter.BeginSuite ( suite. Name, context.IndentCount )
139195
140196 let beforeHooks , afterHooks =
141- sb .Each
197+ suite .Each
142198 |> List.fold ( fun ( be , af ) hook ->
143199 match hook with
144200 | Before hookFunction -> hookFunction :: be, af
@@ -148,23 +204,17 @@ let rec doRunTestSuite (sb: Describe) (context: TestContext) =
148204 let afterHooks = context.ParentAfterHooks |> List.append ( List.rev afterHooks)
149205
150206 let testResults = [
151- for testCase in sb .TestCases do
207+ for testCase in suite .TestCases do
152208 beforeHooks |> Seq.iter ( fun hookFunction -> hookFunction())
153209 runTestCase context.Path testCase
154210 afterHooks |> Seq.iter ( fun hookFunction -> hookFunction())
155211 ]
156212
157213 for result in testResults do
158- match result with
159- | Passed (_, name) ->
160- context.Log $" %s {indentStr}%s {AnsiColours.green} ✅ passed: %s {name}%s {AnsiColours.reset}"
161- | Failed (_, name, ex) ->
162- context.Log $" %s {indentStr}%s {AnsiColours.red} ❌ failed: %s {name} - %s {ex.Message}%s {AnsiColours.reset}"
163- | Pending (_, name) ->
164- context.Log $" %s {indentStr}%s {AnsiColours.grey} ❔ pending: %s {name}%s {AnsiColours.reset}"
214+ context.Reporter.ReportResult( result, context.Path.Length)
165215
166216 let childrenResults =
167- sb .Children
217+ suite .Children
168218 |> List.map ( fun child ->
169219 let childContext =
170220 { context with
@@ -177,28 +227,9 @@ let rec doRunTestSuite (sb: Describe) (context: TestContext) =
177227 testResults @ List.concat childrenResults
178228
179229let runTestSuite ( sb : Describe ) ( context : TestContext ) =
180- let sw = Stopwatch.StartNew()
181230 let testResults = doRunTestSuite sb { context with Path = Path ( context.Path.Value @ [ sb.Name]) }
182- context.Log $" got %d {List.length testResults} test results"
183- testResults |> List.iter ( function
184- // | Passed (path, name) ->
185- // let pathString = String.concat " / " path.Value
186- // context.Log $"Test passed: %s{AnsiColours.green}%s{pathString} - %s{name}%s{AnsiColours.reset}"
187- | Failed ( path, name, ex) ->
188- let pathString = String.concat " / " path.Value
189- context.Log $" Test failed: %s {AnsiColours.red}%s {pathString} / %s {name} - %s {ex.Message}%s {AnsiColours.reset}"
190- // | Pending (path, name) ->
191- // let pathString = String.concat " / " path.Value
192- // context.Log $"Test pending: %s{AnsiColours.grey}%s{pathString} / %s{name}%s{AnsiColours.reset}")
193- | _ -> ())
194-
195- // Count results
196- let passedCount = testResults |> List.filter ( function Passed _ -> true | _ -> false ) |> List.length
197- let failedCount = testResults |> List.filter ( function Failed _ -> true | _ -> false ) |> List.length
198- let pendingCount = testResults |> List.filter ( function Pending _ -> true | _ -> false ) |> List.length
199-
200- context.Log $" Summary: {passedCount} passed, {failedCount} failed, {pendingCount} pending"
201- context.Log $" Total time: %s {sw.Elapsed.ToString()}"
231+ context.Reporter.EndSuite( sb.Name, context.Path.Length)
232+ context.Reporter.End testResults
202233 ()
203234
204235[<AutoOpen>]
0 commit comments