As a starting point,
I typically mirror the folder structure of src in test.
So if i have files: src/foo.jl and src/bar.jl I will also have test/foo.jl and test/bar.jl.
then i might also add seperate files on top for integration testing,
or i might not.
Depending on the project
I’ve had a look at UnPack.jl and am still confused. Under UnPack.jl, the test directory has a file called runtests.jl, which begins with
using UnPack
When I execute that file (julia runtests.jl), I get
[Alans-MacBook-Air test]$ julia runtests.jl
ERROR: LoadError: ArgumentError: Package UnPack not found in current path:
- Run `import Pkg; Pkg.add("UnPack")` to install the UnPack package.
Stacktrace:
[1] require(::Module, ::Symbol) at ./loading.jl:892
[2] include(::Module, ::String) at ./Base.jl:377
[3] exec_options(::Base.JLOptions) at ./client.jl:288
[4] _start() at ./client.jl:484
in expression starting at /Users/rogers/distrib/UnPack/test/runtests.jl:2
Clearly, the Project.toml file is not enough to tell Julia how to find the source code. Do I need to install or activate this package using the package manager? If I do that, how can I be sure I’m testing the local code (in …/src) rather than a version installed elsewhere by Pkg?
Also, most people use an interactive REPL for Julia, usually from some editor/IDE. If you want to run things from the command line, you will face the cost of compilation each time, so it will be frustrating way of using Julia.
The manual section Code Loading · The Julia Language describes how name conflicts can occur when you use a private name that ends up being in the public space created by other popular packages.
I would suggest a useful convention is calling private modules MyData, MyTest etc, these modules would not have name conflicts and you wouldn’t have to carefully manage the coding loading environment.
Next I cd into the project and create some tests. Then do julia --project, add the Test package itself as a dependency (you only have to do this once), then run ]test which should automatically do all the tests in your runtests.jl:
max@opt ~/sandbox> cd MyNewJuliaProject/
max@opt ~/s/MyNewJuliaProject> mkdir test
max@opt ~/s/MyNewJuliaProject> echo "using Test; @test true" > test/runtests.jl
max@opt ~/s/MyNewJuliaProject> julia --project
_
_ _ _(_)_ | Documentation: https://docs.julialang.org
(_) | (_) (_) |
_ _ _| |_ __ _ | Type "?" for help, "]?" for Pkg help.
| | | | | | |/ _` | |
| | |_| | | | (_| | | Version 1.8.0-beta1 (2022-02-23)
_/ |\__'_|_|_|\__'_| | Official https://julialang.org/ release
|__/ |
(MyNewJuliaProject) pkg> add Test
Updating registry at `~/.julia/registries/General.toml`
Resolving package versions...
Updating `~/sandbox/MyNewJuliaProject/Project.toml`
[8dfed614] + Test
Updating `~/sandbox/MyNewJuliaProject/Manifest.toml`
[2a0f44e3] + Base64
[b77e0a4c] + InteractiveUtils
[56ddb016] + Logging
[d6f4376e] + Markdown
[9a3f8284] + Random
[ea8e919c] + SHA v0.7.0
[9e88b42a] + Serialization
[8dfed614] + Test
(MyNewJuliaProject) pkg> test
Testing MyNewJuliaProject
Status `/tmp/jl_6ouu8z/Project.toml`
[a2f463a9] MyNewJuliaProject v0.1.0 `~/sandbox/MyNewJuliaProject`
[8dfed614] Test `@stdlib/Test`
Status `/tmp/jl_6ouu8z/Manifest.toml`
[a2f463a9] MyNewJuliaProject v0.1.0 `~/sandbox/MyNewJuliaProject`
[2a0f44e3] Base64 `@stdlib/Base64`
[b77e0a4c] InteractiveUtils `@stdlib/InteractiveUtils`
[56ddb016] Logging `@stdlib/Logging`
[d6f4376e] Markdown `@stdlib/Markdown`
[9a3f8284] Random `@stdlib/Random`
[ea8e919c] SHA v0.7.0 `@stdlib/SHA`
[9e88b42a] Serialization `@stdlib/Serialization`
[8dfed614] Test `@stdlib/Test`
Testing Running tests...
Testing MyNewJuliaProject tests passed
(MyNewJuliaProject) pkg>
julia> exit()
Another way is to ]develop your package on your “main” Julia environment. This lets you use plain-old julia (without the --project flag) and you can use packages you have on your Julia environment without adding them as dependencies.
I still cannot figure out how to use both versioned public packages, and my own unversioned modules in the same project. When I add a Project.toml file to my directory, I can no longer load my own modules, unless I create a package with UUID for every single module.
I looked at packaged like PyCall, PythonCall, DataFrames, they all have just one massive module and include a bunch of source files. They don’t even use the module feature to separate program logic, within their own project.