Unit test for f()=print("something")

I would like to write unit tests like the following

f() = print("something")
@test print_to_string(f) == "something" 

I’m not able to successfully define the function print_to_string. I’m getting lost while searching the internet including this Julia discourse forum for solutions. There is talk of “redirecting_stdout”, “blocking”, “tasks”, “channels”, etc.

Any suggestions for how to define the function print_to_string?

1 Like

Try @capture_out from https://github.com/JuliaIO/Suppressor.jl

3 Likes

I looked at that, but I couldn’t figure out what block should contain, or how to get my hands on the thing that is being captured. I got the impression that the output of block was simply being thrown in the “bit bucket”, that is, being suppressed. Did I misunderstand how @capture_out actually works?

@capture_out just returns whatever was printed by the captured expression, e.g.:

julia> using Suppressor

julia> f() = print("something")
f (generic function with 1 method)

julia> result = @capture_out f()
"something"

julia> result
"something"

2 Likes

aha. Thank you.

Also, if you are testing show methods, repr may be useful.

5 Likes

You can look at the @test_warn macro in Base and do something similar except for stdout instead of stderr.

Alternatively, consider whether it makes sense to pass an io argument to your function(s) so that you can direct your output to an arbitrary stream.

Update for those who run into similar issues:

julia> versioninfo()
Julia Version 0.6.2
Commit d386e40c17* (2017-12-13 18:08 UTC)
Platform Info:
  OS: Windows (x86_64-w64-mingw32)
julia> @test_warn "something" error("something")
unlink: resource busy or locked (EBUSY)

This is caused by the rm(fname, force=true) statement in macro test_warn. A web search tells me that it happens on Windows 10 and is either caused by the anti-virus program or by not running Jupyter as adminstrator. I don’t want to turn off the anti-virus program nor do I want to run Julia as administrator

Therefore I tried

julia> using Suppressor
julia> f() = print("something")
julia> result = @capture_out f()
MethodError: no method matching redirect_stdout(::IJulia.IJuliaStdio{Base.PipeEndpoint})

No good either. So the solution that works for me is the following.

print_to_string(f::Function, args...) = begin
    io = IOBuffer()
    f(io,args...)
    String(take!(io))
end

f(io::IO) = print(io, "something")

julia>  print_to_string(f) == "something"
true

The issue you’re seeing with Suppressor on IJulia should hopefully be resolved by https://github.com/JuliaLang/IJulia.jl/pull/641