Skip to content
Open
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
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@ changes in `julia`.

## Supported features

* `@include_files` is a clone of Test.jl's `@include_files` that was added in Julia 1.13.

* `@__FUNCTION__` is a macro that returns the innermost enclosing function ([#58940]) (since Compat 4.18.0).
* *Note: the Compat version of this macro does not work in callable structs.*

Expand Down
91 changes: 90 additions & 1 deletion src/Compat.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1160,7 +1160,7 @@ if VERSION < v"1.12.0-DEV.974" # contrib/commit-name.sh 2635dea
else
using Base: insertdims, _insertdims
end

# https://github.com/JuliaLang/julia/pull/54653: add Fix
@static if !isdefined(Base, :Fix) # VERSION < v"1.12.0-DEV.981"
@static if !isdefined(Base, :_stable_typeof)
Expand Down Expand Up @@ -1283,6 +1283,95 @@ end
export @__FUNCTION__
end

# https://github.com/JuliaLang/julia/pull/59951
@static if VERSION < v"1.13.0-0"
function filter_test_files(files::Vector, args::Vector)
# Parse args to extract file filters
filter_args = String[]
use_regex = false

# Check for --files-regex= argument (takes precedence)
regex_idx = findfirst(arg -> startswith(arg, "--files-regex="), args)
if regex_idx !== nothing
# Extract comma-separated list from --files-regex=
pattern_str = args[regex_idx][15:end] # Skip "--files-regex="
append!(filter_args, split(pattern_str, ','))
use_regex = true
else
# Check for --files= argument
files_idx = findfirst(arg -> startswith(arg, "--files="), args)
if files_idx !== nothing
# Extract comma-separated list from --files=
files_str = args[files_idx][9:end] # Skip "--files="
append!(filter_args, split(files_str, ','))
end
end

# Return all files if no filters
isempty(filter_args) && return files

# Filter files based on basename matching
return filter(files) do file
name = basename(file)
if use_regex
any(arg -> occursin(Regex(arg), name), filter_args)
else
any(arg -> occursin(arg, name), filter_args)
end
end
end

"""
@include_files(files)

Include test files from a list, optionally filtered by command-line test arguments.

When running tests via `Pkg.test()`, files can be filtered by passing `test_args`
with the `--files=` or `--files-regex=` flag. If no test args are provided, all files are included.

This macro is part of `Test` in Julia 1.13+. In earlier versions, it's provided
by Compat in the `Compat` module (not re-exported into `Test`).

# Example
```julia
using Test
using Compat

# Include common utilities
include("utils.jl")

@include_files [
"foo.jl",
"bar.jl",
"baz.jl",
]
```

## Usage patterns:

- `Pkg.test()` → includes all files
- `Pkg.test(test_args=["--files=foo"])` → includes only "foo.jl"
- `Pkg.test(test_args=["--files=foo,bar"])` → includes "foo.jl" and "bar.jl"
- `Pkg.test(test_args=["--files-regex=^test_.*\\.jl\$"])` → uses regex pattern matching
- `Pkg.test(test_args=["--files-regex=foo|bar"])` → includes files matching "foo" or "bar"
"""
macro include_files(files)
quote
let test_files = $(esc(files))
# Filter files based on ARGS
filtered_files = Compat.filter_test_files(test_files, ARGS)

# Include filtered files
for file in filtered_files
include(file)
end
end
end
end

export @include_files
end

include("deprecated.jl")

end # module Compat
3 changes: 3 additions & 0 deletions test/include_test/runtests.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
using Compat

@include_files ["test_foo.jl", "test_bar.jl", "test_baz.jl"]
1 change: 1 addition & 0 deletions test/include_test/test_bar.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
println("BAR_RAN")
1 change: 1 addition & 0 deletions test/include_test/test_baz.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
println("BAZ_RAN")
1 change: 1 addition & 0 deletions test/include_test/test_foo.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
println("FOO_RAN")
71 changes: 70 additions & 1 deletion test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -940,7 +940,7 @@ end
@test insertdims(dropdims(b; dims); dims) == b
end
end

# https://github.com/JuliaLang/julia/pull/54653: add Fix
@testset "Fix" begin
function test_fix1(Fix1=Compat.Fix1)
Expand Down Expand Up @@ -1260,3 +1260,72 @@ end
end
end
end

if VERSION < v"1.13.0-0"
# https://github.com/JuliaLang/julia/pull/59951
@testset "@include_files" begin
files = ["test_foo.jl", "test_bar.jl", "test_baz.jl"]

@test Compat.filter_test_files(files, String[]) == files
@test Compat.filter_test_files(files, ["--files=foo"]) == ["test_foo.jl"]
@test Compat.filter_test_files(files, ["--files=foo,bar"]) == ["test_foo.jl", "test_bar.jl"]
@test Compat.filter_test_files(files, ["--files=ba"]) == ["test_bar.jl", "test_baz.jl"]
@test Compat.filter_test_files(files, ["--files=nomatch"]) == String[]
@test Compat.filter_test_files(files, ["--files=foo", "bar"]) == ["test_foo.jl"] # Other args ignored
@test Compat.filter_test_files(files, ["foo"]) == files # No --files= means no filtering
@test Compat.filter_test_files(files, ["bar", "baz"]) == files # No --files= means no filtering

# Test regex patterns
@test Compat.filter_test_files(files, ["--files-regex=^test_foo"]) == ["test_foo.jl"]
@test Compat.filter_test_files(files, ["--files-regex=foo|bar"]) == ["test_foo.jl", "test_bar.jl"]
@test Compat.filter_test_files(files, ["--files-regex=ba[rz]"]) == ["test_bar.jl", "test_baz.jl"]
@test Compat.filter_test_files(files, ["--files-regex=^test_.*\\.jl\$"]) == files
@test Compat.filter_test_files(files, ["--files-regex=nomatch"]) == String[]
@test Compat.filter_test_files(files, ["--files-regex=foo", "--files=bar"]) == ["test_foo.jl"] # --files-regex takes precedence

# Test @include_files macro in subprocess
test_file = joinpath(@__DIR__, "include_test", "runtests.jl")

# Test 1: No args - all files included
output = read(`$(Base.julia_cmd()) --startup-file=no $test_file`, String)
@test occursin("FOO_RAN", output)
@test occursin("BAR_RAN", output)
@test occursin("BAZ_RAN", output)

# Test 2: --files= with single filter
output = read(`$(Base.julia_cmd()) --startup-file=no $test_file --files=foo`, String)
@test occursin("FOO_RAN", output)
@test !occursin("BAR_RAN", output)
@test !occursin("BAZ_RAN", output)

# Test 3: --files= with multiple filters
output = read(`$(Base.julia_cmd()) --startup-file=no $test_file --files=bar,baz`, String)
@test !occursin("FOO_RAN", output)
@test occursin("BAR_RAN", output)
@test occursin("BAZ_RAN", output)

# Test 4: --files= with comma-separated list
output = read(`$(Base.julia_cmd()) --startup-file=no $test_file --files=foo,bar`, String)
@test occursin("FOO_RAN", output)
@test occursin("BAR_RAN", output)
@test !occursin("BAZ_RAN", output)

# Test 5: Bare args without --files= should include all files
output = read(`$(Base.julia_cmd()) --startup-file=no $test_file foo bar`, String)
@test occursin("FOO_RAN", output)
@test occursin("BAR_RAN", output)
@test occursin("BAZ_RAN", output)

# Test 6: --files-regex= with pattern
output = read(`$(Base.julia_cmd()) --startup-file=no $test_file --files-regex=foo\|bar`, String)
@test occursin("FOO_RAN", output)
@test occursin("BAR_RAN", output)
@test !occursin("BAZ_RAN", output)

# Test 7: --files-regex= with anchored pattern
output = read(`$(Base.julia_cmd()) --startup-file=no $test_file --files-regex=^test_foo`, String)
@test occursin("FOO_RAN", output)
@test !occursin("BAR_RAN", output)
@test !occursin("BAZ_RAN", output)
end
end
Loading