@@ -37,7 +37,7 @@ import InlineTest: retest, @testset_macro
37
37
38
38
abstract type Pattern end
39
39
function matches end
40
- function setresult end
40
+ function setresult! end
41
41
42
42
43
43
# * includes
@@ -116,7 +116,7 @@ function pastresult(marks::Dict, subject)
116
116
sym === _pass ? true : sym === _fail ? false : nothing
117
117
end
118
118
119
- function setresult (marks:: Dict , subject, success:: Bool )
119
+ function setresult! (marks:: Dict , subject, success:: Bool )
120
120
ms = get (marks, subject, Symbol ())
121
121
res = success ? _pass : _fail
122
122
if ms isa Symbol
@@ -136,6 +136,43 @@ function setresult(marks::Dict, subject, success::Bool)
136
136
end
137
137
end
138
138
139
+ function markiter (marks, subject, skipres:: Bool )
140
+ ms = get (marks, subject, Symbol ())
141
+ if ms isa Symbol
142
+ if ms === Symbol () || skipres && ms ∈ (_pass, _fail)
143
+ ()
144
+ else
145
+ (ms,)
146
+ end
147
+ else
148
+ if skipres
149
+ Iterators. filter (m -> m ∉ (_pass, _fail), ms)
150
+ else
151
+ ms
152
+ end
153
+ end
154
+ end
155
+
156
+ function addmark! (marks, subject, m:: Symbol )
157
+ ms = get (marks, subject, Symbol ())
158
+ if ms isa Symbol
159
+ if ms === m
160
+ false
161
+ elseif ms === Symbol ()
162
+ marks[subject] = m
163
+ true
164
+ else
165
+ marks[subject] = [ms, m]
166
+ true
167
+ end
168
+ elseif findfirst (== (m), ms) === nothing
169
+ push! (ms, m)
170
+ true
171
+ else
172
+ false
173
+ end
174
+ end
175
+
139
176
function delmark! (marks, subject, m:: Symbol )
140
177
ms = get (marks, subject, Symbol ())
141
178
if ms isa Symbol
@@ -553,6 +590,7 @@ const retest_defaults = (
553
590
load = false ,
554
591
seed = false ,
555
592
marks = true ,
593
+ tag = Symbol[],
556
594
spin = true ,
557
595
clear = false ,
558
596
)
@@ -572,7 +610,7 @@ def(kw::Symbol) =
572
610
[id::Bool], shuffle::Bool=false, recursive::Bool=true,
573
611
static::Union{Bool,Nothing}=nothing, dup::Bool=false,
574
612
load::Bool=false, seed::Union{Integer,Bool}=false,
575
- marks::Bool=true, spin::Bool=true)
613
+ marks::Bool=true, tag=[], spin::Bool=true)
576
614
577
615
Run tests declared with [`@testset`](@ref) blocks, within modules `mod` if specified,
578
616
or within all currently loaded modules otherwise.
@@ -615,7 +653,11 @@ Filtering `pattern`s can be specified to run only a subset of the tests.
615
653
the tests. As a special case, if `seed === false` (the default), no seeding
616
654
is performed, and if `seed === true`, a seed is chosen randomly.
617
655
* When `marks` and `dry` are `true`, "check marks" are printed next to testsets
618
- which passed or failed in previous runs.
656
+ which passed or failed in previous runs, as well as labels.
657
+ * The `tag` keyword allows to tag a testset with labels, encoded as symbols.
658
+ When `tag` is a list of symbols, tag all matching testsets with these.
659
+ When `tag` is a symbol, tag all matching testsets with it.
660
+ Currently, `tag` has an effect only if `dry` is `true`.
619
661
* When `spin` is `true`, the description of the testset being currently executed
620
662
is shown (if there is only one), as well as a "spinner". This is disabled when
621
663
all the available threads/workers are used to run tests (i.e. typically
@@ -714,6 +756,7 @@ function retest(@nospecialize(args::ArgType...);
714
756
load:: Bool = def (:load ),
715
757
seed:: Integer = def (:seed ),
716
758
marks:: Bool = def (:marks ),
759
+ tag = def (:tag ),
717
760
spin:: Bool = def (:spin ),
718
761
# clear: clear marks for matching tests, only active if dry=true
719
762
clear:: Bool = def (:clear ),
@@ -760,6 +803,15 @@ function retest(@nospecialize(args::ArgType...);
760
803
761
804
maxidw[] = id ? maxidw[] : 0
762
805
806
+ if tag isa Symbol
807
+ tag = [tag]
808
+ elseif ! (tag isa Vector{Symbol})
809
+ tag = vec (collect (Symbol, tag))
810
+ end
811
+ if ! dry && ! isempty (tag)
812
+ @warn " tag keyword: labels can be added only in dry mode"
813
+ end
814
+
763
815
for imod in eachindex (modules)
764
816
mod, pat = modules[imod]
765
817
tests = alltests[imod]
@@ -776,7 +828,8 @@ function retest(@nospecialize(args::ArgType...);
776
828
end
777
829
if verbose > 0
778
830
foreach (ts -> dryrun (mod, ts, pat, id ? 0 : module_header* 2 ,
779
- maxidw = id ? maxidw[] : 0 , marks= marks, clear= clear),
831
+ maxidw = id ? maxidw[] : 0 , marks= marks, tag= tag,
832
+ clear= clear),
780
833
tests)
781
834
end
782
835
continue
@@ -1454,7 +1507,8 @@ hasmany(tests) = length(tests) > 1 || isfor(tests[1])
1454
1507
1455
1508
function dryrun (mod:: Module , ts:: TestsetExpr , pat:: Pattern , align:: Int = 0 ,
1456
1509
parentsubj:: Union{Missing, String} = " "
1457
- ; maxidw:: Int , marks:: Bool , clear:: Bool , # external calls
1510
+ # external calls:
1511
+ ; maxidw:: Int , marks:: Bool , tag:: Vector{Symbol} , clear:: Bool ,
1458
1512
# only recursive calls:
1459
1513
evaldesc= true , repeated= nothing , show:: Bool = true )
1460
1514
@assert ts. run
@@ -1470,13 +1524,24 @@ function dryrun(mod::Module, ts::TestsetExpr, pat::Pattern, align::Int=0,
1470
1524
1471
1525
subject = desc isa String ? parentsubj * " /" * desc :
1472
1526
missing
1473
- if isfinal (ts) && false === matches (pat, subject, ts)
1527
+ final = isfinal (ts)
1528
+ if final || ! isempty (tag)
1529
+ ismatch = matches (pat, subject, ts)
1530
+ end
1531
+ if final && false === ismatch
1474
1532
return false , false , false
1475
1533
end
1476
1534
1477
1535
res = pastresult (ts. marks, subject)
1478
1536
if clear && res != = nothing
1479
1537
delmark! (ts. marks, subject, res ? _pass : _fail)
1538
+ # should we set res=nothing here ? not doing it might be confusing,
1539
+ # but it gives an idea about which marks are being deleted
1540
+ end
1541
+ if subject != = missing
1542
+ for mark= tag
1543
+ ismatch && addmark! (ts. marks, subject, mark)
1544
+ end
1480
1545
end
1481
1546
1482
1547
if show
@@ -1489,9 +1554,14 @@ function dryrun(mod::Module, ts::TestsetExpr, pat::Pattern, align::Int=0,
1489
1554
color= :light_black )
1490
1555
end
1491
1556
1492
- if marks && res != = nothing
1493
- printstyled (res ? " ✔" : " ✘" , color = res ? :green : Base. error_color (),
1494
- bold= true )
1557
+ if marks
1558
+ for mark in markiter (ts. marks, subject, true )
1559
+ printstyled (" " , mark, color= :cyan , bold= false )
1560
+ end
1561
+ if res != = nothing
1562
+ printstyled (res ? " ✔" : " ✘" , color = res ? :green : Base. error_color (),
1563
+ bold= true )
1564
+ end
1495
1565
end
1496
1566
end
1497
1567
@@ -1501,7 +1571,7 @@ function dryrun(mod::Module, ts::TestsetExpr, pat::Pattern, align::Int=0,
1501
1571
for tsc in ts. children
1502
1572
tsc. run || continue
1503
1573
dryrun (mod, tsc, pat, align + 2 , subject,
1504
- maxidw= maxidw, marks= marks, clear= clear, show= true )
1574
+ maxidw= maxidw, marks= marks, tag = tag, clear= clear, show= true )
1505
1575
end
1506
1576
false , false , false # meaningless unused triple
1507
1577
elseif marks
@@ -1518,7 +1588,8 @@ function dryrun(mod::Module, ts::TestsetExpr, pat::Pattern, align::Int=0,
1518
1588
for tsc in ts. children
1519
1589
tsc. run || continue
1520
1590
cp, cf, cu = dryrun (mod, tsc, pat, align + 2 , subject,
1521
- maxidw= maxidw, marks= marks, clear= clear, show= false )
1591
+ maxidw= maxidw, marks= marks, tag= tag, clear= clear,
1592
+ show= false )
1522
1593
passes |= cp
1523
1594
fails |= cf
1524
1595
unrun |= cu
@@ -1567,7 +1638,8 @@ function dryrun(mod::Module, ts::TestsetExpr, pat::Pattern, align::Int=0,
1567
1638
ts. iter = iter # necessary when reachable is used
1568
1639
beginend. marks = ts. marks
1569
1640
dryrun (mod, beginend, pat, align, parentsubj; evaldesc= false ,
1570
- repeated= repeated, maxidw= maxidw, marks= marks, clear= clear, show= show)
1641
+ repeated= repeated, maxidw= maxidw, marks= marks, tag= tag,
1642
+ clear= clear, show= show)
1571
1643
end
1572
1644
1573
1645
loopvalues = ts. loopvalues
0 commit comments