Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions .github/workflows/DocPreviewsCleanup.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
name: Doc Previews Cleanup

on:
schedule:
- cron: "25 22 * * 2"
workflow_dispatch:

concurrency:
# Same group concurrency as the `Documentation.yml` workflow, because they both
# git-push to the same branch, so we want to avoid clashes.
group: docs-pushing

jobs:
doc-preview-cleanup:
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- name: Checkout gh-pages branch
uses: actions/checkout@v6
with:
ref: gh-pages
- name: Delete preview and history + push changes
run: |
if [[ -d previews ]]; then
git config user.name "${{github.actor}}"
git config user.email "${{github.actor_id}}+${{github.actor}}@users.noreply.github.com"
git rm -rf previews/
git commit -m 'Delete previews directory'
git branch gh-pages-new $(echo "Delete history" | git commit-tree HEAD^{tree})
git push --force-with-lease origin gh-pages-new:gh-pages
fi
108 changes: 108 additions & 0 deletions .github/workflows/Documentation.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
name: Documentation

on:
push:
branches:
- main
tags: "*"
paths:
- ".github/workflows/Documentation.yml"
- "docs/**"
- "src/**"
- "Project.toml"
pull_request:
paths:
- ".github/workflows/Documentation.yml"
- "docs/**"
- "src/**"
- "Project.toml"
release:

concurrency:
# Skip intermediate builds: always.
# Cancel intermediate builds: always.
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
build-docs:
permissions:
actions: write
contents: write
pull-requests: read
statuses: write
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- uses: actions/checkout@v6
- uses: julia-actions/setup-julia@v2
with:
version: "1"
- uses: julia-actions/cache@v2
id: julia-cache
with:
cache-name: Documentation
- name: Instantiate docs environment
shell: julia --color=yes --project=docs {0}
run: |
using Pkg
Pkg.instantiate()
- name: Build documentation
run:
julia --color=yes --project=docs docs/make.jl
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Save Julia depot cache on cancel or failure
id: julia-cache-save
if: cancelled() || failure()
uses: actions/cache/save@v4
with:
path: |
${{ steps.julia-cache.outputs.cache-paths }}
key: ${{ steps.julia-cache.outputs.cache-key }}
- uses: actions/upload-artifact@v5
with:
name: documentation-build
path: docs/build
retention-days: 10

deploy-docs:
# Deploy docs only if triggers is not a PR, or a PR not from a fork.
if: ${{ (github.event_name != 'pull_request') || (! github.event.pull_request.head.repo.fork) }}
needs: build-docs
permissions:
actions: write
contents: write
pull-requests: read
statuses: write
runs-on: ubuntu-latest
timeout-minutes: 30
concurrency:
# Have only one job pushing the docs at a time.
group: docs-pushing
steps:
- uses: actions/checkout@v6
- uses: julia-actions/setup-julia@v2
with:
version: "1"
- uses: julia-actions/cache@v2
with:
# Steal cache from the build job
cache-name: Documentation
- uses: actions/download-artifact@v6
with:
name: documentation-build
path: docs/build
- name: Instantiate docs environment
shell: julia --color=yes {0}
run: |
# We only need `Documenter` for publishing the docs, let's not
# reinstall the world all over again.
using Pkg
Pkg.add(; name="Documenter", version="1")
- name: Deploy documentation
run:
julia --color=yes docs/deploy.jl
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
DOCUMENTER_KEY: ${{ secrets.DOCUMENTER_KEY }}
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
Manifest.toml
Manifest.toml
/docs/build/
100 changes: 5 additions & 95 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# ParallelTestRunner.jl

[![Stable Documentation](https://img.shields.io/badge/docs-stable-blue.svg)](https://juliatesting.github.io/ParallelTestRunner.jl/)
[![Latest Documentation](https://img.shields.io/badge/docs-latest-blue.svg)](https://juliatesting.github.io/ParallelTestRunner.jl/dev)

Simple parallel test runner for Julia tests with autodiscovery.

## Usage
Expand Down Expand Up @@ -40,102 +43,9 @@ using ParallelTestRunner
runtests(MyModule, ARGS)
```

### Customizing the test suite

By default, `runtests` 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
# Manually define your test suite
testsuite = Dict(
"basic" => quote
include("basic.jl")
end,
"advanced" => quote
include("advanced.jl")
end
)

runtests(MyModule, ARGS; testsuite)
```

You can also use `find_tests` to automatically discover tests 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
# Start with autodiscovered tests
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")
end
end

runtests(MyModule, args; testsuite)
```

### Provide defaults

`runtests` takes a keyword argument that one can use to provide default definitions to be loaded before each testfile.
As an example one could always load `Test` and the package under test.

```julia
const init_code = quote
using Test
using MyPackage
end

runtests(MyModule, ARGS; init_code)
```

### Interactive use

Arguments can also be passed via the standard `Pkg.test` interface for interactive control. For example, here is how we could run the subset of tests that start with the testset name "MyTestsetA" in i) verbose mode, and ii) with default threading enabled:

```julia-repl
# In an environment where `MyPackage.jl` is available
julia --proj

julia> using Pkg

# No need to start a fresh session to change threading
julia> Pkg.test("MyModule"; test_args=`--verbose MyTestsetA`, julia_args=`--threads=auto`);
```
Alternatively, arguments can be passed directly from the command line with a shell alias like the one below:

```julia-repl
jltest --threads=auto -- --verbose MyTestsetA
```

<details><summary>Shell alias</summary>

```shell
function jltest {
julia=(julia)

# certain arguments (like those beginnning with a +) need to come first
if [[ $# -gt 0 && "$1" = +* ]]; then
julia+=("$1")
shift
fi

"${julia[@]}" --startup-file=no --project -e "using Pkg; Pkg.API.test(; test_args=ARGS)" "$@"
}
```

</details>

## Packages using ParallelTestRunner.jl

There are a few packages already using `ParallelTestRunner.jl` to parallelize their tests, you can look at their setups if you need inspiration to move your packages as well:
## Documentation

* [`Enzyme.jl`](https://github.com/EnzymeAD/Enzyme.jl/blob/main/test/runtests.jl)
* [`GPUArrays.jl`](https://github.com/JuliaGPU/GPUArrays.jl/blob/master/test/runtests.jl)
* [`GPUCompiler.jl`](https://github.com/JuliaGPU/GPUCompiler.jl/blob/master/test/runtests.jl)
* [`Metal.jl`](https://github.com/JuliaGPU/Metal.jl/blob/main/test/runtests.jl)
For more details about the use of this package, read the [documentation](https://juliatesting.github.io/ParallelTestRunner.jl/).

## Inspiration
Based on [@maleadt](https://github.com/maleadt) test infrastructure for [CUDA.jl](https://github.com/JuliaGPU/CUDA.jl).
9 changes: 9 additions & 0 deletions docs/Project.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
[deps]
Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4"
ParallelTestRunner = "d3525ed8-44d0-4b2c-a655-542cee43accc"

[compat]
Documenter = "1"

[sources]
ParallelTestRunner = {path = ".."}
9 changes: 9 additions & 0 deletions docs/deploy.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
using Documenter

deploydocs(;
repo="github.com/JuliaTesting/ParallelTestRunner.jl",
devbranch="main",
# Only push previews if all the relevant environment variables are non-empty. This is an
# attempt to work around https://github.com/JuliaDocs/Documenter.jl/issues/2048.
push_preview = all(!isempty, (get(ENV, "GITHUB_TOKEN", ""), get(ENV, "DOCUMENTER_KEY", ""))),
)
19 changes: 19 additions & 0 deletions docs/make.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
using Documenter
using ParallelTestRunner

makedocs(;
modules=[ParallelTestRunner],
authors="Valentin Churavy <v.churavy@gmail.com> and contributors",
repo="https://github.com/JuliaTesting/ParallelTestRunner.jl/blob/{commit}{path}#{line}",
sitename="ParallelTestRunner.jl",
format=Documenter.HTML(;
prettyurls=get(ENV, "CI", "false") == "true",
canonical="https://juliatesting.github.io/ParallelTestRunner.jl",
assets=String[],
),
pages=[
"Home" => "index.md",
"Advanced Usage" => "advanced.md",
"API Reference" => "api.md",
],
)
Loading