Zulip Chat Archive

Stream: lean4

Topic: Testing commands help


Josh Clune (Oct 11 2022 at 18:51):

Hello,

I'm trying to figure out the best approach for testing a command that I've been working on. Specifically, I'm interested in measuring speed and viewing the outputs of the command on a large number of tests. The two main approaches I'm considering are compiling an executable that will run the command or writing a lake script that will run/test the command. But I've been having trouble figuring out how to get either approach to work.

For the first approach, I just can't seem to figure out how to invoke the command from IO. I know that for testing TacticM, TermElabM, MetaM, and CoreM functions, there are .run and .run' functions that let me do things like:

import Lean

open Lean
open Lean.Elab.Tactic

def metaMFunction : Lean.MetaM String := return "hi"

def main : List String  IO UInt32 := fun args => do
  let env : Lean.Environment  Lean.mkEmptyEnvironment
  let fileName : String := sorry
  let fileMap : FileMap := sorry
  let (s, _)  metaMFunction.run'.toIO {fileName, fileMap} {env}
  IO.println s
  return 0

Is there anything analogous for CommandElabM? Likewise, if I'm defining a command via a macro, is there anything analogous for MacroM?

For the second approach, I've had a bit more success writing a script in my lakefile:

import Lake

open Lake DSL

package Duper {
  precompileModules := true
}

lean_lib Duper

@[defaultTarget]
lean_exe defaultExe {
  root := `Main
}

open Std
open System

def runTest (lean : FilePath) (leanPath : SearchPath)
  (test : FilePath) : IO UInt32 := do
  IO.println s!"Start : {test}"
  let out  IO.Process.output {
    cmd := lean.toString
    args := #[test.toString],
    env := #[("LEAN_PATH", leanPath.toString)]
  }
  -- I can run whatever tests I want to check that out.stderr and out.stdout are as I want
  return 0

/--
Run tests.
USAGE:
  lake script run test
Run tests.
-/
script test args do
  let lean  getLean
  let leanPath  getAugmentedLeanPath
  let task  IO.asTask (runTest lean leanPath args[0]!)
  let code  IO.ofExcept task.get
  return code

Although this mostly works in that lake script run test does basically what I want, I've found that with my current setup, the script test does not appear to be using precompiled modules. Since I'm interested in measuring speed (and since my command is sensitive to the heartbeat differences that arise when using or not using precompiled modules), this code doesn't quite do what I need it to. Is there some way to modify this code/approach to make sure that the precompiled modules are used?

Alternatively, if there's some other better way of testing commands, I would be totally open to that as well. Thanks!

Arthur Paulino (Oct 11 2022 at 20:10):

Sorry, what do you mean by "test commands"?
#xy: have you seen LSpec? https://github.com/yatima-inc/LSpec

Josh Clune (Oct 11 2022 at 21:04):

Ah, sorry I wasn't really clear. I'm working on a command that takes a filepath and proof as input, parses the corresponding file, builds a goal, tries to prove said goal with the input proof, and then uses Lean.logInfo to print some stuff.

If I write this command in some file ex.lean, then I can see the output either by viewing it in VSCode or by running lake env lean ex.lean. However, viewing output in VSCode doesn't let me easily run the command many times and see all the outputs/timings at once, and lake env lean ex.lean currently has the same issue my script file does that it will run the command without precompiled modules turned on.

So at the end of the day, when I say test my command I mean I want to be able to run my command a bunch of times on various inputs and see the resulting outputs, and I want to do this in such a way that when the command is run, it is run with precompiled modules.

I haven't seen LSpec before, and it seems interesting (thanks for the link), but I think the problem it's trying to solve is different from the problem I'm currently having.

Edit: Also, if possible, I'm trying to do this in such a way that I not only can see the outputs, but I can run various tests/checks on the outputs in Lean automatically (e.g. at the end of runTest in the lakefile I provided) rather than having to do that separately.


Last updated: Dec 20 2023 at 11:08 UTC