Skip to content
This repository was archived by the owner on Jul 24, 2024. It is now read-only.

Commit 7b9db99

Browse files
committed
fix(test/*): make sure tests produce no output (#3947)
Modify tests so that they produce no output. This also means removing all uses of `sorry`/`admit`. Replace `#eval` by `run_cmd` consistently. Tests that produced output before are modified so that it is checked that they roughly produce the right output Add a trace option to the `#simp` command that turns the message of only if the expression is simplified to `true`. All tests are modified so that they simplify to `true`. The randomized tests can produce output when they find a false positive, but that should basically never happen. Add some docstings to `src/tactic/interactive`.
1 parent 9d42f6c commit 7b9db99

28 files changed

+168
-94
lines changed

src/tactic/interactive.lean

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -391,7 +391,6 @@ We use this tactic for writing tests.
391391
meta def guard_target_strict (p : parse texpr) : tactic unit :=
392392
do t ← target, guard_expr_strict t p
393393

394-
395394
/--
396395
`guard_hyp_strict h : t` fails if the hypothesis `h` does not have type syntactically equal
397396
to `t`.
@@ -400,19 +399,33 @@ We use this tactic for writing tests.
400399
meta def guard_hyp_strict (n : parse ident) (p : parse $ tk ":" *> texpr) : tactic unit :=
401400
do h ← get_local n >>= infer_type >>= instantiate_mvars, guard_expr_strict h p
402401

402+
/-- Tests that there are `n` hypotheses in the current context. -/
403403
meta def guard_hyp_nums (n : ℕ) : tactic unit :=
404404
do k ← local_context,
405405
guard (n = k.length) <|> fail format!"{k.length} hypotheses found"
406406

407+
/-- Test that `t` is the tag of the main goal. -/
407408
meta def guard_tags (tags : parse ident*) : tactic unit :=
408409
do (t : list name) ← get_main_tag,
409410
guard (t = tags)
410411

412+
/-- `guard_proof_term { t } e` applies tactic `t` and tests whether the resulting proof term
413+
unifies with `p`. -/
414+
meta def guard_proof_term (t : itactic) (p : parse texpr) : itactic :=
415+
do
416+
g :: _ ← get_goals,
417+
e ← to_expr p,
418+
t,
419+
g ← instantiate_mvars g,
420+
unify e g
421+
422+
411423
/-- `success_if_fail_with_msg { tac } msg` succeeds if the interactive tactic `tac` fails with
412424
error message `msg` (for test writing purposes). -/
413425
meta def success_if_fail_with_msg (tac : tactic.interactive.itactic) :=
414426
tactic.success_if_fail_with_msg tac
415427

428+
/-- Get the field of the current goal. -/
416429
meta def get_current_field : tactic name :=
417430
do [_,field,str] ← get_main_tag,
418431
expr.const_name <$> resolve_name (field.update_prefix str)
@@ -649,12 +662,16 @@ add_tactic_doc
649662
decl_names := [`tactic.interactive.field_simp],
650663
tags := ["simplification", "arithmetic"] }
651664

665+
/-- Tests whether `t` is definitionally equal to `p`. The difference with `guard_expr_eq` is that
666+
this uses definitional equality instead of alpha-equivalence. -/
652667
meta def guard_expr_eq' (t : expr) (p : parse $ tk ":=" *> texpr) : tactic unit :=
653668
do e ← to_expr p, is_def_eq t e
654669

655670
/--
656-
`guard_target t` fails if the target of the main goal is not `t`.
671+
`guard_target' t` fails if the target of the main goal is not definitionally equal to `t`.
657672
We use this tactic for writing tests.
673+
The difference with `guard_target` is that this uses definitional equality instead of
674+
alpha-equivalence.
658675
-/
659676
meta def guard_target' (p : parse texpr) : tactic unit :=
660677
do t ← target, guard_expr_eq' t p

src/tactic/simp_command.lean

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,9 @@ meta def simp_arg_type.replace_subexprs : simp_arg_type → list (expr × expr)
4646

4747
setup_tactic_parser
4848

49+
/- Turn off the messages if the result is exactly `true` with this option. -/
50+
declare_trace silence_simp_if_true
51+
4952
/--
5053
The basic usage is `#simp e`, where `e` is an expression,
5154
which will print the simplified form of `e`.
@@ -100,7 +103,8 @@ do
100103
} ts,
101104

102105
/- Trace the result. -/
103-
trace simp_result
106+
when (¬ is_trace_enabled_for `silence_simp_if_true ∨ simp_result ≠ expr.const `true [])
107+
(trace simp_result)
104108

105109
add_tactic_doc
106110
{ name := "#simp",

src/tactic/squeeze.lean

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,15 @@ namespace interactive
185185

186186
attribute [derive decidable_eq] simp_arg_type
187187

188+
/-- Turn a `simp_arg_type` into a string. -/
189+
meta instance simp_arg_type.has_to_string : has_to_string simp_arg_type :=
190+
⟨λ a, match a with
191+
| simp_arg_type.all_hyps := "*"
192+
| (simp_arg_type.except n) := "-" ++ to_string n
193+
| (simp_arg_type.expr e) := to_string e
194+
| (simp_arg_type.symm_expr e) := "" ++ to_string e
195+
end
196+
188197
/-- combinator meant to aggregate the suggestions issued by multiple calls
189198
of `squeeze_simp` (due, for instance, to `;`).
190199

test/README.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# The Mathlib Test Directory
2+
3+
In this directory we collect various tests for the commands, tactics and metaprograms written in
4+
mathlib (see [the tactic folder](../src/tactic)).
5+
6+
Tests for all tactics are highly encouraged, especially if they are used sparingly in mathlib.
7+
Here are some guidelines for writing a test:
8+
9+
* Make sure that the test fails if something unexpected happens. Use `guard`, `guard_target`, `guard_hyp`, `get_decl` or similar tactics that fail if the tactic state is incorrect.
10+
* Make sure that the test is silent, i.e. produces no output when it succeeds. This makes it easy to spot the tests that actually failed. Furthermore, it is unlikely that anyone will notice the output changing if the test keeps succeeding.
11+
12+
Some tips to make a test silent:
13+
* Instead of `trace e`, write `guard (e = expected_expression)`.
14+
* If you write a tactic/command that normally produces output, consider adding an option that silences it. See for example the uses of `set_option trace.silence_library_search true` in the [library_search](library_search) folder.
15+
* Do not prove a lemma using `admit` or `sorry`. Instead make sure that the lemma is provable, and prove it by `assumption` or `trivial` or similar.

test/continuity.lean

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,28 +6,27 @@ import analysis.special_functions.trigonometric
66
example {X Y : Type*} [topological_space X] [topological_space Y]
77
(f₁ f₂ : X → Y) (hf₁ : continuous f₁) (hf₂ : continuous f₂)
88
(g : Y → ℝ) (hg : continuous g) : continuous (λ x, (max (g (f₁ x)) (g (f₂ x))) + 1) :=
9-
by show_term { continuity }
10-
-- prints `refine ((continuous.comp hg hf₁).max (continuous.comp hg hf₂)).add continuous_const`
9+
by guard_proof_term { continuity } ((hg.comp hf₁).max (hg.comp hf₂)).add continuous_const
1110

1211
example {κ ι : Type}
1312
(K : κ → Type) [∀ k, topological_space (K k)] (I : ι → Type) [∀ i, topological_space (I i)]
1413
(e : κ ≃ ι) (F : Π k, homeomorph (K k) (I (e k))) :
1514
continuous (λ (f : Π k, K k) (i : ι), F (e.symm i) (f (e.symm i))) :=
16-
by show_term { continuity }
17-
-- prints, modulo a little bit of cleaning up the pretty printer:
18-
-- `exact continuous_pi i, ((F (e.symm i)).continuous).comp (continuous_apply (e.symm i)))`
15+
by guard_proof_term { continuity }
16+
@continuous_pi _ _ _ _ _ (λ (f : Π k, K k) i, (F (e.symm i)) (f (e.symm i)))
17+
(i : ι), ((F (e.symm i)).continuous).comp (continuous_apply (e.symm i)))
1918

2019
open real
2120

2221
local attribute [continuity] continuous_exp continuous_sin continuous_cos
2322

2423
example : continuous (λ x : ℝ, exp ((max x (-x)) + sin x)^2) :=
25-
by show_term { continuity }
26-
-- prints
27-
-- `exact (continuous_exp.comp ((continuous_id.max continuous_id.neg).add continuous_sin)).pow 2`
24+
by guard_proof_term { continuity }
25+
(continuous_exp.comp ((continuous_id.max continuous_id.neg).add continuous_sin)).pow 2
2826

2927
example : continuous (λ x : ℝ, exp ((max x (-x)) + sin (cos x))^2) :=
30-
by show_term { continuity }
28+
by guard_proof_term { continuity }
29+
(continuous_exp.comp ((continuous_id'.max continuous_id'.neg).add (continuous_sin.comp continuous_cos))).pow 2
3130

3231
-- Without `md := semireducible` in the call to `apply_rules` in `continuity`,
3332
-- this last example would have run off the rails:

test/doc_commands.lean

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ def foo := 5
99
/-- ok -/
1010
add_decl_doc foo
1111

12-
#eval do
12+
run_cmd do
1313
ds ← doc_string ``foo,
1414
guard $ ds = "ok"
1515

test/general_recursion.lean

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -195,8 +195,7 @@ by rw roption.dom_iff_mem; apply exists_imp_exists _ (f91_spec n); simp
195195

196196
def f91' (n : ℕ) : ℕ := (f91 n).get (f91_dom n)
197197

198-
#eval f91' 109
199-
-- 99
198+
run_cmd guard (f91' 109 = 99)
200199

201200
lemma f91_spec' (n : ℕ) : f91' n = if n > 100 then n - 10 else 91 :=
202201
begin

test/library_search/exp_le_exp.lean

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,7 @@ import analysis.special_functions.exp_log
33

44
open real
55

6+
/- Turn off trace messages so they don't pollute the test build: -/
7+
set_option trace.silence_library_search true
8+
69
example {a b : ℝ} (h: a ≤ b) : exp a ≤ exp b := by library_search

test/library_search/filter.lean

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@ import order.filter.basic
22

33
open filter
44

5+
/- Turn off trace messages so they don't pollute the test build: -/
6+
set_option trace.silence_library_search true
7+
58
example {α β γ : Type*} {A : filter α} {B : filter β} {C : filter γ} {f : α → β} {g : β → γ}
69
(hf : tendsto f A B) (hg : tendsto g B C) : tendsto (g ∘ f) A C :=
710
calc

test/library_search/nat.lean

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import data.nat.basic
88

99
namespace test.library_search
1010

11-
1211
/- Turn off trace messages so they don't pollute the test build: -/
1312
set_option trace.silence_library_search true
1413
/- For debugging purposes, we can display the list of lemmas: -/

0 commit comments

Comments
 (0)