Creating my first package/ How to test my simple function

Hi!

I decided to create my very first package. This “baby” package contains only one function (I give an example):

using Plots
using Distributions
function easy(x::Vector{Float64})
a = print("The mean is:", mean(x)) 
b = print("\nThe variance is:", var(x))
c = plot(x)
end

The user gives

a=[1,5,4,7.6]
easy(a)

Then, the function prints the mean of a, the variance of a and a simple plot of a. I get some functions from the Distributions.jl package and the plot from the Plots.jl package. I have followed all the needed steps to create my package and it’s time to test it.

I found a simple function test example:

using MyPackage 
using Test
@testset "MyPackage" begin
x = 2
y = 2
@test MyPackage.sum(x,y) = = 4
end

This is true, so the test is passed. In this case, it’s logical to test this.

In my case, I didn’t create any mathematical or new complex structured functions to test; only a function that prints some statistical results and an output of a plot (this might help a student).

In my case, though, what do I need to test my function? Does it make any sense?

3 Likes

I don’t know of a way to do this with the standard library, but there are two packages that can help by capturing the output of your function to a string which you can then test against an expected result:

https://github.com/JuliaDocs/IOCapture.jl

https://github.com/JuliaIO/Suppressor.jl

2 Likes

Thank you! But what do I test here? My easy() function or every print separately? The type of easy(a) is Plots.Plot{Plots.GRBackend} because the prints are only prints. See the screenshot below:
image

It is probably worth looking at the tests for plots.jl https://github.com/JuliaPlots/Plots.jl/tree/master/test to see what you can query about a plot once it has been created. Then you can decide which of those attributes are important to your function and ensure they match the expected value.

3 Likes

If you return the values in the function, can can test them. Here is an example:

function easy(x::Vector{Float64})
    μ = mean(x)
    σ = std(x)
    print("The mean is:", μ) 
    print("\nThe variance is:", σ)
    c = plot(x)
    return μ,σ,c
end

x = [1.0,2.0,3.0]

μ,σ,p = easy(x)

@test μ ≈ 2.0
@test σ ≈ 1.0
@test p[1][1][:y] == x

I’m not sure how to test the print statements and plot further.

3 Likes

As contradict suggested, you can test the print statement like so:

using IOCapture

c = IOCapture.capture() do
    easy(x)
end

@test c.output == "The mean is:2.0\nThe variance is:1.0"
4 Likes

Thanks to both of you! It worked like a charm! :star_struck:

Can’t you just use redirect_stdout for this?

Extra credit: Functions that print things to stdout typically define two methods like this

function myfun(io::IO, x)
    println(io, 3x)
end

myfun(x) = myfun(stdout, x)

Testing this function is easier, because we can use our own IOBuffer instead of stdout.

4 Likes