I’m developing a private package and I’m curious what the recommend process is. I started with the idea of using Pkg.develop(path=“path to my package”) but I’ve noticed that with this method I often need to restart the REPL because Revise is unable to revise the package in memory. With changes to the package and restarting the REPL I then get a package pre-compilation which takes some time. Therefore in development, specially in early stages, I’m wasting a lot of time in pre-compilation.
Another idea then is to not use Pkg.develop() but instead just use include(“path to my main module”). Then in my test script I use the following (name of main module being AM2App)
if !haskey(Pkg.installed(),"AM2App")
include("../src/AM2App.jl")
using .AM2App
else
using AM2App
end
using Test
In development mode using the include(“module path”) seems to be a much faster because I can skip the pre-compilation step. Also the Module is easily replaced each time I run which means I don’t need to restart the REPL.
Rather than trying to develop the package in your global package environment, you can instead activate the package’s own environment. That has a few advantages:
No need to modify your global package environment at all
Less potential confusion about what dependencies you are using (whatever is in your package’s Project.toml will be used)
Any packages you install during development will automatically be added to your package’s Project.toml and Manifest.toml, making it easy to reproduce your state later.
Activating your package’s environment just requires that you Pkg.activate("/path/to/your/package/folder") or cd into that folder and do julia --project. I’ve also found Revise to be pretty reliable in this setup. The only thing it can’t do is manage changing type definitions, which is indeed unfortunate. I usually just restart Julia in that case (or restart my Jupyter kernel) which I agree is rather annoyingly slow sometimes.
Thanks, that’s a good point about the dependencies.
This method still requires package pre-compilation though, right?
Also, is it possible to somehow check which active environment Julia is using? My if block using !haskey(Pkg.installed(),“AM2App”) no longer works when I run in project mode. It would be cool if I could write my test scripts so they can work in Project mode or in include() mode.
Base.active_project() will give you the path to the Project.tomlPkg is currently using.
Pkg.installed(), which I think is now being deprecated, do not returns the project package as installed.
Well, if your tests are located in the default test/runtests.jl file you should be able to just do:
# test/runtests.jl
using MyPackage
using Test
# My tests ...
If you run the tests using Pkg.test("MyPackage") it will run the test in “project mode”, always using the version of MyPackage that the current active project refers to.
What I’ve found is working best for me is to have a run.jl and runtests.jl files in my test folder.
TestApp
src
TestApp.jl
test
run.jl
runtests.jl
runtests_test1.jl
runtests_test2.jl
Then I break up my actual testing into files like runtests_test1.jl, runtests_test2.jl, etc.
For runtests.jl I have
using TestApp
include("runtests_test1.jl")
include("runtests_test2.jl")
And for run.jl I have
include("../src/TestApp.jl")
using .TestApp
# include("runtests_test1.jl") #skip this test for now...
include("runtests_test2.jl")
The advantages are:
I can quickly execute run.jl and I don’t need to wait for pre-compilation. The module is simply replaced in Main and I can quickly develop new functions and sort out simple bugs
I can toggle which tests I want to run by simply commenting out include statements
When I’m ready to test the full package or generate coverage info I can run Pkg.test() to run the same test scripts properly
I can generate trace-compile statements for PackageCompiler using:
julia --startup-file=no --trace-compile=precompiles.jl TestApp/test/run.jl
Whereas I have found the following does not work, even though it executes the same test scripts
julia --project=TestApp --startup-file=no --trace-compile=precompiles.jl -e "using Pkg; Pkg.test()"
This puts Revise into Project.toml, but my package doesn’t really depend on it. Is it possible to not make my package depend on Revise, but still use it during development?
Yeah, you just need to install Revise in your global package environment. You do that by starting Julia (without a --project argument) and then doing ]add Revise.