@@ -69,6 +69,7 @@ mutable struct TestsetExpr
69
69
parent:: Maybe{TestsetExpr}
70
70
children:: Vector{TestsetExpr}
71
71
strings:: Vector{Union{String,Missing}}
72
+ results:: Dict{String,Bool}
72
73
# loopvalues & loopiters: when successful in evaluating loop values in resolve!,
73
74
# we "flatten" the nested for loops into a single loop, with loopvalues
74
75
# containing tuples of values, and loopiters the tuples of variables to which the
@@ -82,7 +83,8 @@ mutable struct TestsetExpr
82
83
body:: Expr
83
84
84
85
TestsetExpr (source, mod, desc, options, loops, parent, children= TestsetExpr[]) =
85
- new (0 , source, mod, desc, options, loops, parent, children, String[])
86
+ new (0 , source, mod, desc, options, loops, parent, children, String[],
87
+ Dict {String,Bool} ())
86
88
end
87
89
88
90
isfor (ts:: TestsetExpr ) = ts. loops != = nothing
@@ -255,8 +257,8 @@ function resolve!(mod::Module, ts::TestsetExpr, pat::Pattern;
255
257
256
258
function decide (subj)
257
259
m = matches (pat, subj, ids)
258
- # For the curious, setting `s = something(static, missing)`, there are few
259
- # "formulas" to compute the result without `if`, but using only
260
+ # For the curious reader , setting `s = something(static, missing)`, there
261
+ # are few "formulas" to compute the result without `if`, but using only
260
262
# `coalesce, |, &, ==, !=, ===, !==, (a,b) -> a, (a,b) -> b, (a,b) -> !a,
261
263
# (a,b) -> !b`. The shortest formulas involve 5 such
262
264
# functions `fi` and are of the form
@@ -372,6 +374,7 @@ function resolve!(mod::Module, ts::TestsetExpr, pat::Pattern;
372
374
ts. hasbrokenrec |= tsc. hasbrokenrec
373
375
end
374
376
end
377
+
375
378
pop! (ids)
376
379
if ! run || ! shown
377
380
ts. descwidth = 0
@@ -407,7 +410,8 @@ function make_ts(ts::TestsetExpr, pat::Pattern, stats, chan)
407
410
408
411
if ts. loops === nothing
409
412
quote
410
- @testset $ (ts. mod) $ (isfinal (ts)) $ pat $ (ts. id) $ (ts. desc) $ (ts. options) $ stats $ chan $ body
413
+ @testset $ (ts. mod) $ (isfinal (ts)) $ pat $ (ts. id) $ (ts. desc) $ (ts. options) #=
414
+ =# $ (ts. results) $ stats $ chan $ body
411
415
end
412
416
else
413
417
c = count (x -> x === nothing , (ts. loopvalues, ts. loopiters))
@@ -418,7 +422,8 @@ function make_ts(ts::TestsetExpr, pat::Pattern, stats, chan)
418
422
loops = ts. loops
419
423
end
420
424
quote
421
- @testset $ (ts. mod) $ (isfinal (ts)) $ pat $ (ts. id) $ (ts. desc) $ (ts. options) $ stats $ chan $ loops $ body
425
+ @testset $ (ts. mod) $ (isfinal (ts)) $ pat $ (ts. id) $ (ts. desc) $ (ts. options) #=
426
+ =# $ (ts. results) $ stats $ chan $ loops $ body
422
427
end
423
428
end
424
429
end
@@ -471,7 +476,7 @@ const ArgType = Union{Module,PatternX,AbstractString,AbstractArray,Tuple,Symbol,
471
476
dry::Bool=false, stats::Bool=false, verbose::Real=true,
472
477
[id::Bool], shuffle::Bool=false, recursive::Bool=true,
473
478
static::Union{Bool,Nothing}=nothing, dup::Bool=false,
474
- load::Bool=false, [seed::Integer])
479
+ load::Bool=false, [seed::Integer], marks::Bool=true )
475
480
476
481
Run tests declared with [`@testset`](@ref) blocks, within modules `mod` if specified,
477
482
or within all currently loaded modules otherwise.
@@ -512,7 +517,8 @@ Filtering `pattern`s can be specified to run only a subset of the tests.
512
517
above), and are cached and used again on subsequent invocations.
513
518
* If `seed` is provided, it is used to seed the global RNG before running
514
519
the tests.
515
-
520
+ * When `marks` and `dry` are `true`, "check marks" are printed next to testsets
521
+ which passed or failed in previous runs.
516
522
517
523
### Filtering
518
524
@@ -599,10 +605,11 @@ function retest(@nospecialize(args::ArgType...);
599
605
static:: Maybe{Bool} = nothing ,
600
606
load:: Bool = false ,
601
607
seed:: Maybe{Integer} = nothing ,
608
+ marks:: Bool = true ,
602
609
)
603
610
604
- dry, stats, shuffle, group, verbose, recursive, id, strict, dup, static =
605
- update_keywords (args, dry, stats, shuffle, group, verbose, recursive, id, strict, dup, static)
611
+ dry, stats, shuffle, group, verbose, recursive, id, strict, dup, static, marks =
612
+ update_keywords (args, dry, stats, shuffle, group, verbose, recursive, id, strict, dup, static, marks )
606
613
607
614
implicitmodules, modules, verbose = process_args (args; verbose= verbose, shuffle= shuffle,
608
615
recursive= recursive, load= load)
@@ -661,7 +668,7 @@ function retest(@nospecialize(args::ArgType...);
661
668
end
662
669
if verbose > 0
663
670
foreach (ts -> dryrun (mod, ts, pat, id ? 0 : module_header* 2 ,
664
- maxidw = id ? maxidw[] : 0 ),
671
+ maxidw = id ? maxidw[] : 0 , marks = marks ),
665
672
tests)
666
673
end
667
674
continue
@@ -1025,7 +1032,7 @@ end
1025
1032
1026
1033
# hidden feature, shortcuts for passing kwargs to retest
1027
1034
function update_keywords (@nospecialize (args), dry, stats, shuffle, group, verbose,
1028
- recursive, id, strict, dup, static)
1035
+ recursive, id, strict, dup, static, marks )
1029
1036
for arg in args
1030
1037
if arg isa Symbol
1031
1038
for c in string (arg)
@@ -1052,13 +1059,15 @@ function update_keywords(@nospecialize(args), dry, stats, shuffle, group, verbos
1052
1059
dup = val
1053
1060
elseif c == ' c'
1054
1061
static = val
1062
+ elseif c == ' m'
1063
+ marks = val
1055
1064
else
1056
1065
error (" bad keyword shortcut" )
1057
1066
end
1058
1067
end
1059
1068
end
1060
1069
end
1061
- dry, stats, shuffle, group, verbose, recursive, id, strict, dup, static
1070
+ dry, stats, shuffle, group, verbose, recursive, id, strict, dup, static, marks
1062
1071
end
1063
1072
1064
1073
function process_args (@nospecialize (args);
@@ -1307,7 +1316,7 @@ isindented(verbose, module_header, many) = (verbose > 0) & module_header
1307
1316
module_summary (verbose, many) = many | iszero (verbose)
1308
1317
1309
1318
function dryrun (mod:: Module , ts:: TestsetExpr , pat:: Pattern , align:: Int = 0 , parentsubj= " "
1310
- ; maxidw:: Int , # external calls
1319
+ ; maxidw:: Int , marks :: Bool , # external calls
1311
1320
# only recursive calls:
1312
1321
evaldesc= true , repeated= nothing , ids:: Vector{Int64} = Int64[])
1313
1322
@assert ts. run
@@ -1334,19 +1343,26 @@ function dryrun(mod::Module, ts::TestsetExpr, pat::Pattern, align::Int=0, parent
1334
1343
if maxidw > 0 # width (ndigits) of max id; <= 0 means ids not printed
1335
1344
printstyled (lpad (ts. id, maxidw), " | " , color = :light_black , bold= true )
1336
1345
end
1346
+
1337
1347
printstyled (' ' ^ align, desc, color = desc isa String ? :normal : Base. warn_color ())
1338
1348
1339
1349
if repeated != = nothing
1340
1350
printstyled (" (repeated" ,
1341
- repeated == - 1 ? " )" : " $repeated times)" , ' \n ' ,
1351
+ repeated == - 1 ? " )" : " $repeated times)" ,
1342
1352
color= :light_black )
1343
- else
1344
- println ()
1345
1353
end
1354
+
1355
+ res = get (ts. results, subject, nothing )
1356
+ if marks && res != = nothing
1357
+ printstyled (res ? " ✅" : " ✘" , color = res ? :green : Base. error_color (),
1358
+ bold= true )
1359
+ end
1360
+ println ()
1361
+
1346
1362
if ts. options. transient_verbose
1347
1363
for tsc in ts. children
1348
1364
tsc. run || continue
1349
- dryrun (mod, tsc, pat, align + 2 , subject, maxidw= maxidw, ids= ids)
1365
+ dryrun (mod, tsc, pat, align + 2 , subject, maxidw= maxidw, marks = marks, ids= ids)
1350
1366
end
1351
1367
end
1352
1368
pop! (ids)
@@ -1372,8 +1388,9 @@ function dryrun(mod::Module, ts::TestsetExpr, pat::Pattern, align::Int=0, parent
1372
1388
ts. parent, ts. children)
1373
1389
beginend. run = true
1374
1390
beginend. id = ts. id
1391
+ beginend. results = ts. results
1375
1392
dryrun (mod, beginend, pat, align, parentsubj; evaldesc= false ,
1376
- repeated= repeated, maxidw= maxidw, ids= ids)
1393
+ repeated= repeated, maxidw= maxidw, marks = marks, ids= ids)
1377
1394
end
1378
1395
1379
1396
loopvalues = ts. loopvalues
0 commit comments