Stream: helpdesk (published)

Topic: Unit test that specific method is called


view this post on Zulip Rasmus Henningsson (Jun 04 2021 at 11:05):

Is there any convenient way to unit test whether a specific method is called?
The context is ThreadedSparseArrays.jl, that adds threading for sparse*dense multiplications.
I would like to make a unit test to check that a multiplication: A*B ends up calling the correct mul! method down the line.

view this post on Zulip Mosè Giordano (Jun 04 2021 at 13:28):

Code coverage?

view this post on Zulip Mosè Giordano (Jun 04 2021 at 13:29):

With code coverage you see whether a line of your package was hit at all during the tests, but you don't see the code path

view this post on Zulip Rasmus Henningsson (Jun 04 2021 at 14:07):

That's a good point! Don't make it harder than it is. :grinning_face_with_smiling_eyes::grinning_face_with_smiling_eyes:

view this post on Zulip Rasmus Henningsson (Jun 04 2021 at 17:48):

Actually, I couldn't help but making it a bit harder. :wink: Because not everyone really pays attention to read coverage changes, it might be covered by some test code but not in every situation I want it to, and it's nice to get a clear error message.

So I exploit that the function I want to check will throw an Exception for incorrect matrix sizes and check which function and file the exception is thrown from.
With this:

function match_exception(f, ::Type{T}=DimensionMismatch, func=:mul!, path="ThreadedSparseArrays.jl") where T
    try
        f()
    catch ex
        st = stacktrace(catch_backtrace())[1]
        p = splitpath(path)
        p2 = splitpath(string(st.file))
        return ex isa T && st.func == func && p==p2[max(1,end-length(p)+1):end]
    end
    false
end

I can test it like this:

A = ThreadedSparseMatrixCSC(spzeros(2,3))
B = zeros(4,1)
@test match_exception(()->A*B)
@test match_exception(()->A'B)
...

view this post on Zulip Patrick Toche (Jun 04 2021 at 21:35):

I'm no expert and I mostly read these threads to learn, but one thing I've read lately is that try/catch is expensive.

view this post on Zulip Rasmus Henningsson (Jun 06 2021 at 17:25):

I think you are right that it can be expensive, and I wouldn't use throwin performance critical code like an inner loop. But this is just for a couple of unit tests so it should be fine. And the code that might throw the exception needs to be there because we want the exact same behavior as the corresponding methods in SparseArrays.


Last updated: Oct 02 2023 at 04:34 UTC