Is there any way to run unit tests on methods/types defined in a package extension (but not exposed by the main package) ?
As an example, say that our package exposes only one function: sample(model, rng ....)
We write an extension to define sample on a different model type, but for that to work we need to wrap the model and run a few pre-processing steps before running sample(wrapped(model), rng...).
I’d like to write some tests on the intermediate functions defined in the extension without exposing them in the main package.
If you extend a function by definitions (i.e. import something and add new signatures to it) then loading both solves the problem
If you define new functions in the extension, these might not even be in global scope – ever, if I understand extensions correctly for now.
So how would you normally call these functions then? The same way you would do the test.
edit: Sorry I was not careful enough in reading – you import the sample function in your extension so you add method definitions to it, these are actually available when loading both packages as @mkitti already wrote.
Example: Manifolds.jl has an NLSolve extension, that also does the same as yours, it extends a method by further signatures… and here Manifolds.jl/approx_inverse_retraction.jl at master · JuliaManifolds/Manifolds.jl · GitHub is the test – Manifolds.jl is loaded either before or through utils.jl, so with NLSolve together the extension and its functionality is loaded and afterwards tested.
Thanks for the help, that explains half of my problem. Should have given a bit more details, in my case the sample function is quite complicated and I split it in a few smaller functions, something like this
module MainPackage
function sample end
export sample
end
module MainPackageExt
function subfn() end
function wrapper() end
function sample()
subfn(...)
wrapper(...)
end
end
Just wondering if there’s a way to unit test subfn instead of just testing MainPackageExt.sample
if you use import MainPackage: sample
as the first line within MainPackageExt you can call both sample functions with just sample() (if you happen to have a default implementation without the extension).
For subfn directly I am not aware how that could directly be tested, but can you issue sample-calls that end up covering all cases of subfn?
PS: I just saw atop the topic here – Welcome to the Julia Discourse!
PPS: In naming, the extension Names I saw until now are MainPackageSecondPackageExt when you main package gets extended once the second package is loaded.
I encountered a similar issue. My workaround was to define a stub in MainPackage:
module MainPackage
function sample end
function subfun end
export sample
end
In the extension module, I imported subfn:
module MainPackageExt
import MainPackage: subfn
function subfn() end
function wrapper() end
function sample()
subfn(...)
wrapper(...)
end
end
In my test block, I did the following:
@testset "subfn" begin
using MainPackage
using WeakDependency
using MainPackage: subfn
...
end
That seemed to accomplish both goals: keeping subfn hidden from the user, but allowing it to be explicitly loaded for the purpose of testing. I don’t know if there is a better approach but this seems to check the boxes.
I’d avoid introducing names in the package if you are only doing it to test extensions, a user absolutely can access it. I would also avoid testing subfunctions so finely, I prefer tests for public names or longlasting code. But since there are always good exceptions, Base.get_extension gets you the module instance of a loaded extension. You still can’t import any names from it (that’s what packages are for, not extensions), but it’ll let you examine it like any module, and you can assign it or its properties to a variable for convenience. Obviously don’t abuse this to make extensions act like hampered packages if new names warrant a true package.