julia-vscode / TestItemRunner.jl

Run Julia test items
MIT License
76 stars 11 forks source link

Doctests as testitem? #49

Open gdalle opened 1 year ago

gdalle commented 1 year ago

I'm not sure how to run doctests as a testitem:

gdalle commented 1 year ago

By digging around in the output I found some more information. It probably has to do with the execution of the testitems in a new module:

[ Info: Doctest: running doctests.
┌ Warning: Failed to evaluate `CurrentModule = MyPackage` in `@meta` block.
│   exception = UndefVarError: `MyPackage` not defined
└ @ Documenter.DocTests ~/.julia/packages/Documenter/H5y27/src/Utilities/Utilities.jl:34
┌ Error: Doctesting failed
│   exception =
│    `makedocs` encountered a doctest error. Terminating build
davidanthoff commented 1 year ago

We should probably just try to detect doc tests statically and then treat them as a special kind of test item, or something like that...

ORBAT commented 1 year ago

This is the workaround I've been using to run doctests in a @testitem. It temporarily adds the standard environment "@v#.#" to the load path so that my package doesn't have to have Documenter in its dependencies (ie. it assumes that Documenter can be found in that environment), loads Documenter and then runs the actual function that calls doctest. Fooling with the load path while "live" is probably not a great idea, but I haven't personally run into any surprises yet.

I feel like there's got to be better ways to do this, but I'm a Julia beginner so this is the best I could come up with 😅

using TestItems

@testitem "doctests" begin
  function with_documenter(fn)
    env = "@v#.#"

    if !(env in Base.LOAD_PATH)
      insert!(Base.LOAD_PATH, 2, env)
      @info "changed LOAD_PATH" Base.LOAD_PATH
    end

    __mod = @__MODULE__()
    @eval __mod using Documenter

    try
      @info "running test fn"
      @eval __mod $fn()
      @info "test fn done"
    catch e
      rethrow(e)
    finally
      let idx = findfirst(isequal(env), Base.LOAD_PATH)
        if idx == nothing
          return
        end
        deleteat!(Base.LOAD_PATH, idx)
        @info "reset LOAD_PATH" Base.LOAD_PATH
      end
    end
  end

  with_documenter() do
    DocMeta.setdocmeta!(Musica, :DocTestSetup, :(using Musica); recursive=true)
    doctest(Musica; manual=false)
  end
end