From f67b20284e0fe202fef6f046448947729785ff22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mos=C3=A8=20Giordano?= Date: Mon, 8 Dec 2025 11:58:29 +0000 Subject: [PATCH 1/3] [docs] Execute examples when building the docs --- docs/MyPackage/Project.toml | 12 +++++++ docs/MyPackage/src/MyPackage.jl | 2 ++ docs/MyPackage/test/advanced.jl | 3 ++ docs/MyPackage/test/basic.jl | 3 ++ docs/MyPackage/test/runtests.jl | 2 ++ docs/Project.toml | 9 ++++-- docs/src/advanced.md | 56 +++++++++++++++++++++++---------- docs/src/index.md | 19 +++++------ src/ParallelTestRunner.jl | 36 ++++++++++++++++----- 9 files changed, 105 insertions(+), 37 deletions(-) create mode 100644 docs/MyPackage/Project.toml create mode 100644 docs/MyPackage/src/MyPackage.jl create mode 100644 docs/MyPackage/test/advanced.jl create mode 100644 docs/MyPackage/test/basic.jl create mode 100644 docs/MyPackage/test/runtests.jl diff --git a/docs/MyPackage/Project.toml b/docs/MyPackage/Project.toml new file mode 100644 index 0000000..6587f84 --- /dev/null +++ b/docs/MyPackage/Project.toml @@ -0,0 +1,12 @@ +name = "MyPackage" +uuid = "0b48ad8b-a282-4514-80d9-bf0add6b76ed" + +[deps] +ParallelTestRunner = "d3525ed8-44d0-4b2c-a655-542cee43accc" +Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" + +[sources] +ParallelTestRunner = {path = ".."} + +[compat] +julia = "1.10" diff --git a/docs/MyPackage/src/MyPackage.jl b/docs/MyPackage/src/MyPackage.jl new file mode 100644 index 0000000..5db5ee2 --- /dev/null +++ b/docs/MyPackage/src/MyPackage.jl @@ -0,0 +1,2 @@ +module MyPackage +end # module MyPackage diff --git a/docs/MyPackage/test/advanced.jl b/docs/MyPackage/test/advanced.jl new file mode 100644 index 0000000..905985a --- /dev/null +++ b/docs/MyPackage/test/advanced.jl @@ -0,0 +1,3 @@ +using Test + +@test true diff --git a/docs/MyPackage/test/basic.jl b/docs/MyPackage/test/basic.jl new file mode 100644 index 0000000..905985a --- /dev/null +++ b/docs/MyPackage/test/basic.jl @@ -0,0 +1,3 @@ +using Test + +@test true diff --git a/docs/MyPackage/test/runtests.jl b/docs/MyPackage/test/runtests.jl new file mode 100644 index 0000000..a69cabd --- /dev/null +++ b/docs/MyPackage/test/runtests.jl @@ -0,0 +1,2 @@ +using MyPackage +using ParallelTestRunner diff --git a/docs/Project.toml b/docs/Project.toml index d5fab23..f07d875 100644 --- a/docs/Project.toml +++ b/docs/Project.toml @@ -1,9 +1,12 @@ [deps] Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4" +MyPackage = "0b48ad8b-a282-4514-80d9-bf0add6b76ed" ParallelTestRunner = "d3525ed8-44d0-4b2c-a655-542cee43accc" - -[compat] -Documenter = "1" +Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" [sources] +MyPackage = {path = "MyPackage"} ParallelTestRunner = {path = ".."} + +[compat] +Documenter = "1" diff --git a/docs/src/advanced.md b/docs/src/advanced.md index eef7ae8..69a751e 100644 --- a/docs/src/advanced.md +++ b/docs/src/advanced.md @@ -1,3 +1,10 @@ +```@setup mypackage +using ParallelTestRunner +mypackage_dir = joinpath(pkgdir(ParallelTestRunner), "docs", "MyPackage") +using MyPackage +test_dir = joinpath(mypackage_dir, "test") +``` + # Advanced Usage ```@meta @@ -14,7 +21,10 @@ This page covers advanced features of `ParallelTestRunner` for customizing test By default, [`runtests`](@ref) automatically discovers all `.jl` files in your `test/` directory (excluding `runtests.jl` itself) using the `find_tests` function. You can customize which tests to run by providing a custom `testsuite` dictionary: -```julia +```@example mypackage +using ParallelTestRunner +using MyPackage + # Manually define your test suite testsuite = Dict( "basic" => quote @@ -22,10 +32,13 @@ testsuite = Dict( end, "advanced" => quote include("advanced.jl") + @test 40 + 2 ≈ 42 end ) -runtests(MyModule, ARGS; testsuite) +cd(test_dir) do # hide +runtests(MyPackage, ARGS; testsuite) +end # hide ``` ## Filtering Test Files @@ -33,21 +46,26 @@ runtests(MyModule, ARGS; testsuite) You can also use [`find_tests`](@ref) to automatically discover test files and then filter or modify them. This requires manually parsing arguments so that filtering is only applied when the user did not request specific tests to run: -```julia +```@example mypackage +using ParallelTestRunner +using MyPackage + # Start with autodiscovered tests +cd(test_dir) do # hide testsuite = find_tests(pwd()) # Parse arguments args = parse_args(ARGS) if filter_tests!(testsuite, args) - # Remove tests that shouldn't run on Windows - if Sys.iswindows() - delete!(testsuite, "ext/specialfunctions") + # Remove tests that shouldn't run on non-Windows systems + if !Sys.iswindows() + delete!(testsuite, "advanced") end end -runtests(MyModule, args; testsuite) +runtests(MyPackage, args; testsuite) +end # hide ``` The [`filter_tests!`](@ref) function returns `true` if no positional arguments were provided (allowing additional filtering) and `false` if the user specified specific tests (preventing further filtering). @@ -60,20 +78,20 @@ This is useful for: - Defining constants, defaults or helper functions - Setting up test infrastructure -```julia +```@example mypackage using ParallelTestRunner +using MyPackage const init_code = quote - using Test - using MyPackage - # Define a helper function available to all tests function test_helper(x) return x * 2 end end +cd(test_dir) do # hide runtests(MyPackage, ARGS; init_code) +end # hide ``` The `init_code` is evaluated in each test's sandbox module, so all definitions are available to your test files. @@ -82,8 +100,9 @@ The `init_code` is evaluated in each test's sandbox module, so all definitions a For tests that require specific environment variables or Julia flags, you can use the `test_worker` keyword argument to [`runtests`](@ref) to assign tests to custom workers: -```julia +```@example mypackage using ParallelTestRunner +using MyPackage function test_worker(name) if name == "needs_env_var" @@ -120,8 +139,9 @@ The `test_worker` function receives the test name and should return either: If your package needs to accept its own command-line arguments in addition to `ParallelTestRunner`'s options, use [`parse_args`](@ref) with custom flags: -```julia +```@example mypackage using ParallelTestRunner +using MyPackage # Parse arguments with custom flags args = parse_args(ARGS; custom=["myflag", "another-flag"]) @@ -132,10 +152,12 @@ if args.custom["myflag"] !== nothing end # Pass parsed args to runtests +cd(test_dir) do # hide runtests(MyPackage, args) +end # hide ``` -Custom flags are stored in the `custom` field of the `ParsedArgs` object, with values of `nothing` (not set) or `Some(value)` (set, with optional value). +Custom flags are stored in the `custom` field of the [`ParsedArgs`](@ref) object, with values of `nothing` (not set) or `Some(value)` (set, with optional value). ## Interactive use @@ -146,11 +168,11 @@ For example, here is how we could run the subset of test files that start with t # Start julia in an environment where `MyPackage.jl` is available julia --project ``` -```julia-repl -julia> using Pkg +```@repl mypackage +using Pkg # No need to start a fresh session to change threading -julia> Pkg.test("MyModule"; test_args=`--verbose test_cool_feature`, julia_args=`--threads=auto`); +Pkg.test("MyPackage"; test_args=`--verbose advanced`, julia_args=`--threads=auto`); ``` Alternatively, arguments can be passed directly from the command line with a shell alias like the one below: diff --git a/docs/src/index.md b/docs/src/index.md index 35636cf..1db88e0 100644 --- a/docs/src/index.md +++ b/docs/src/index.md @@ -7,6 +7,13 @@ DocTestSetup = quote end ``` +```@setup mypackage +using ParallelTestRunner +mypackage_dir = joinpath(pkgdir(ParallelTestRunner), "docs", "MyPackage") +using MyPackage +test_dir = joinpath(mypackage_dir, "test") +``` + [ParallelTestRunner.jl](https://github.com/JuliaTesting/ParallelTestRunner.jl) is a simple parallel test runner for Julia tests with automatic test discovery. It runs each test file concurrently in isolated worker processes, providing real-time progress output and efficient resource management. @@ -19,11 +26,13 @@ It runs each test file concurrently in isolated worker processes, providing real 2. **Update your `test/runtests.jl`**: - ```julia + ```@example mypackage using MyPackage using ParallelTestRunner + cd(test_dir) do # hide runtests(MyPackage, ARGS) + end # hide ``` That's it! `ParallelTestRunner` will automatically: @@ -108,14 +117,6 @@ The test runner provides real-time output showing: - Memory allocation - RSS (Resident Set Size) memory usage -Example output: - -``` -Test | Time (s) | GC (s) | GC % | Alloc (MB) | RSS (MB) | -basic (1) | 0.12 | 0.01 | 8.3 | 5.23 | 125.45 | -integration (2) | 2.45 | 0.15 | 6.1 | 45.67 | 234.12 | -``` - ### Graceful Interruption Press `Ctrl+C` to interrupt the test run. The framework will: diff --git a/src/ParallelTestRunner.jl b/src/ParallelTestRunner.jl index c0d56f1..6d0c82e 100644 --- a/src/ParallelTestRunner.jl +++ b/src/ParallelTestRunner.jl @@ -679,29 +679,49 @@ Several keyword arguments are also supported: ## Examples +Run all tests with default settings (auto-discovers `.jl` files) + +```julia +using ParallelTestRunner +using MyPackage + +runtests(MyPackage, ARGS) +``` + +Run only tests matching "integration" (matched with `startswith`): ```julia -# Run all tests with default settings (auto-discovers .jl files) -runtests(MyModule, ARGS) +using ParallelTestRunner +using MyPackage + +runtests(MyPackage, ["integration"]) +``` -# Run only tests matching "integration" -runtests(MyModule, ["integration"]) +Define a custom test suite +```julia +using ParallelTestRunner +using MyPackage -# Define a custom test suite testsuite = Dict( "custom" => quote @test 1 + 1 == 2 end ) -runtests(MyModule, ARGS; testsuite) -# Customize the test suite +runtests(MyPackage, ARGS; testsuite) +``` + +Customize the test suite +```julia +using ParallelTestRunner +using MyPackage + testsuite = find_tests(pwd()) args = parse_args(ARGS) if filter_tests!(testsuite, args) # Remove a specific test delete!(testsuite, "slow_test") end -runtests(MyModule, args; testsuite) +runtests(MyPackage, args; testsuite) ``` ## Memory Management From ca0cb5e4032344c1270ef840ff56887193691262 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mos=C3=A8=20Giordano?= Date: Mon, 8 Dec 2025 12:12:38 +0000 Subject: [PATCH 2/3] [CI] Build documentation with `--check-bounds=yes` This hopefully avoids recompiling packages when running the tests --- .github/workflows/Documentation.yml | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/.github/workflows/Documentation.yml b/.github/workflows/Documentation.yml index a12d6cf..8b0e9c5 100644 --- a/.github/workflows/Documentation.yml +++ b/.github/workflows/Documentation.yml @@ -43,13 +43,15 @@ jobs: with: cache-name: Documentation - name: Instantiate docs environment - shell: julia --color=yes --project=docs {0} + # Use `--check-bounds=yes` so that when we run tests we don't need to + # precompile again all the packages. + shell: julia --color=yes --check-bounds=yes --project=docs {0} run: | using Pkg Pkg.instantiate() - name: Build documentation run: - julia --color=yes --project=docs docs/make.jl + julia --color=yes --project=docs --check-bounds=yes docs/make.jl env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Save Julia depot cache on cancel or failure @@ -94,7 +96,7 @@ jobs: name: documentation-build path: docs/build - name: Instantiate docs environment - shell: julia --color=yes {0} + shell: julia --color=yes --check-bounds=yes {0} run: | # We only need `Documenter` for publishing the docs, let's not # reinstall the world all over again. @@ -102,7 +104,7 @@ jobs: Pkg.add(; name="Documenter", version="1") - name: Deploy documentation run: - julia --color=yes docs/deploy.jl + julia --color=yes --check-bounds=yes docs/deploy.jl env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} DOCUMENTER_KEY: ${{ secrets.DOCUMENTER_KEY }} From 1b146355444a10b8bc365d1777de98e66b013bb0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mos=C3=A8=20Giordano?= Date: Mon, 8 Dec 2025 12:20:14 +0000 Subject: [PATCH 3/3] Simplify No need to define `mypackage_dir` anymore, it was only needed in an earlier iteration of my experiments. --- docs/src/advanced.md | 3 +-- docs/src/index.md | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/docs/src/advanced.md b/docs/src/advanced.md index 69a751e..1565402 100644 --- a/docs/src/advanced.md +++ b/docs/src/advanced.md @@ -1,8 +1,7 @@ ```@setup mypackage using ParallelTestRunner -mypackage_dir = joinpath(pkgdir(ParallelTestRunner), "docs", "MyPackage") using MyPackage -test_dir = joinpath(mypackage_dir, "test") +test_dir = joinpath(pkgdir(ParallelTestRunner), "docs", "MyPackage", "test") ``` # Advanced Usage diff --git a/docs/src/index.md b/docs/src/index.md index 1db88e0..ef28a84 100644 --- a/docs/src/index.md +++ b/docs/src/index.md @@ -9,9 +9,8 @@ end ```@setup mypackage using ParallelTestRunner -mypackage_dir = joinpath(pkgdir(ParallelTestRunner), "docs", "MyPackage") using MyPackage -test_dir = joinpath(mypackage_dir, "test") +test_dir = joinpath(pkgdir(ParallelTestRunner), "docs", "MyPackage", "test") ``` [ParallelTestRunner.jl](https://github.com/JuliaTesting/ParallelTestRunner.jl) is a simple parallel test runner for Julia tests with automatic test discovery.