ReTestItems.TestContext
— TypeTestContext()
A context for test setups. Used to keep track of @testsetup
-expanded TestSetup
s and a TestSetupModules
for a given process; used in runtestitem
to ensure any setups relied upon by the @testitem
are evaluated on the process that will run the test item.
ReTestItems.TestItem
— TypeTestItem
A single, independently runnable group of tests. Used to wrap tests that must be run together, similar to a @testset
, but encapsulating those test in their own module. Should only be created via the @testitem
macro.
ReTestItems.TestSetup
— TypeTestSetup(name, code)
A module that a TestItem
can require to be run before that TestItem
is run. Used for declaring code that multiple TestItem
s rely on. Should only be created via the @testsetup
macro.
ReTestItems.TestSetupModules
— TypeTestSetupModules()
A set of test setups. Used to keep track of which test setups have been evaluated on a given process.
ReTestItems._redirect_logs
— Method_redirect_logs(f, target::Union{IO,String})
Redirects stdout and stderr while f
is evaluated to target
. If target is String it is assumed it is a file path.
ReTestItems.print_errors_and_captured_logs
— Methodprint_errors_and_captured_logs(ti::TestItem, run_number::Int; logs=:batched, errors_first=false)
When a testitem doesn't succeed, we print the corresponding error/failure reports from the testset and any logs that we captured while the testitem was eval()'d.
For :eager
mode of logs
we don't print any logs as they bypass log capture. :batched
means we print logs even for passing test items, whereas :issues
means we are only printing captured logs if there were any errors or failures.
If errors_first=true
, then the test errors are printed first and the logs second. The default errors_first=false
, prints the logs firsts.
Nothing is printed when no logs were captures and no failures or errors occured.
ReTestItems.runtests
— FunctionReTestItems.runtests()
ReTestItems.runtests(mod::Module)
ReTestItems.runtests(paths::AbstractString...)
Execute @testitem
tests.
Only files ending in _test.jl
or _tests.jl
will be searched for test items.
If directory or file paths are passed, only those directories and files are searched. If no arguments are passed, the src/
and test/
directories of the current project are searched for @testitem
s.
Keywords
Filtering @testitem
s
name::Union{Regex,AbstractString,Nothing}=nothing
: Used to filter@testitem
s by their name.AbstractString
input will only keep the@testitem
that exactly matchesname
,Regex
can be used to partially match multiple@testitem
s. By default, no filtering is applied.tags::Union{Symbol,AbstractVector{Symbol},Nothing}=nothing
: Used to filter@testitem
s by their tags. A single tag can be used to match any@testitem
that contains it, when multiple tags are provided, only@testitem
s that contain all of the tags will be run. By default, no filtering is applied.
name
and tags
filters are applied together and only those @testitem
s that pass both filters will be run.
Configuring runtests
testitem_timeout::Real
: The number of seconds to wait until a@testitem
is marked as failed. Defaults to 30 minutes. Can also be set using theRETESTITEMS_TESTITEM_TIMEOUT
environment variable. If a@testitem
sets its owntimeout
keyword, then that takes precedence. Fractional values are rounded up to the nearest second. Note timeouts are currently only applied whennworkers > 0
.retries::Int=0
: The number of times to retry a@testitem
if either tests do not pass or, if running with multiple worker processes, the worker fails or hits the timeout limit while running the tests. Can also be set using theRETESTITEMS_RETRIES
environment variable. If a@testitem
sets its ownretries
keyword, then the maximum of these two retry numbers will be used as the retry limit for that@testitem
. Whenreport=true
, the report will contain information for all runs of a@testitem
that was retried.nworkers::Int
: The number of worker processes to use for running@testitem
s. Default 0. Can also be set using theRETESTITEMS_NWORKERS
environment variable.nworker_threads::Union{String,Int}
: The number of threads to use for each worker process. Defaults to 2. Can also be set using theRETESTITEMS_NWORKER_THREADS
environment variable. Interactive threads are supported through a string (e.g. "auto,2").worker_init_expr::Expr
: an expression that will be run on each worker process before any tests are run. Can be used to load packages or set up the environment. Must be a:block
expression.test_end_expr::Expr
: an expression that will be run after each testitem is run. Can be used to verify that global state is unchanged after running a test. Must be a:block
expression.memory_threshold::Real
: Sets the fraction of memory that can be in use before a worker processes are restarted to free memory. Defaults to 0.99. Only supported withnworkers > 0
. For example, if set to 0.8, then when >80% of the available memory is in use, a worker process will be killed and replaced with a new worker before the next testitem is run. The testitem will then be run on the new worker process, regardless of if memory pressure dropped below the threshold. If the memory pressure remains above the threshold, then a worker process will again be replaced before the next testitem is run. Can also be set using theRETESTITEMS_MEMORY_THRESHOLD
environment variable. Note: thememory_threshold
keyword is experimental and may be removed in future versions.report::Bool=false
: Iftrue
, write a JUnit-format XML file summarising the test results. Can also be set using theRETESTITEMS_REPORT
environment variable. The location at which the XML report is saved can be set using theRETESTITEMS_REPORT_LOCATION
environment variable. By default the report will be written at the root of the project being tested.logs::Symbol
: Handles how and when we display messages produced during test evaluation. Can be one of::eager
: Everything is printed tostdout
immediately, like in a regular Julia session.:batched
: Logs are saved to a file and then printed when the test item is finished.:issues
: Logs are saved to a file and only printed if there were any errors or failures.
:eager
is the default when running with 0 or 1 worker processes,:batched
otherwise. For non-interactive sessions,:issues
is used by default.verbose_results::Bool
: Iftrue
, the final test report will list each@testitem
, otherwise the results are aggregated. Default isfalse
for non-interactive sessions or whenlogs=:issues
,true
otherwise.validate_paths::Bool=false
: Iftrue
,runtests
will throw an error if any of thepaths
passed to it cannot contain test files, either because the path doesn't exist or the path points to a file which is not a test file. Default isfalse
. Can also be set using theRETESTITEMS_VALIDATE_PATHS
environment variable.timeout_profile_wait::Real=0
: When non-zero, a worker that times-out will trigger a CPU profile for which we will waittimeout_profile_wait
seconds before terminating the worker. Zero means no profile will be taken. Can also be set using theRETESTITEMS_TIMEOUT_PROFILE_WAIT
environment variable. See the Profile documentation for more information on triggered profiles. Note you can useworker_init_expr
to tweak the profile settings on workers.
ReTestItems.@testitem
— Macro@testitem "name" [tags=[] setup=[] retries=0 skip=false default_imports=true] begin
# code that will be run as tests
end
A single, independently runnable group of tests.
A test item is a standalone block of tests, and cannot access names from the surrounding scope. Multiple test items may run in parallel, executing on distributed processes.
A @testitem
can contain a single test:
@tesitem "Arithmetic" begin
@test 1 + 1 == 2
end
Or it can contain many tests, which can be arranged in @testsets
:
@testitem "Arithmetic" begin
@testset "addition" begin
@test 1 + 2 == 3
@test 1 + 0 == 1
end
@testset "multiplication" begin
@test 1 * 2 == 2
@test 1 * 0 == 0
end
@test 1 + 2 * 2 == 5
end
A @testitem
is wrapped into a module when run, so must import any additional packages:
@testitem "Arithmetic" begin
using LinearAlgebra
@testset "multiplication" begin
@test dot(1, 2) == 2
end
end
The test item's code is run as top-level code in a new module, so it can include imports, define new structs or helper functions, and declare tests and testsets.
@testitem "DoCoolStuff" begin
function do_really_cool_stuff()
# ...
end
@testset "cool stuff doing" begin
@test do_really_cool_stuff()
end
end
By default, Test
and the package being tested will be loaded into the @testitem
. This can be disabled by passing default_imports=false
.
A @testitem
can use test-specific setup code declared with @testsetup
, by passing the name of the test setup module with the setup
keyword:
@testsetup module TestIrrationals
const PI = 3.14159
const INV_PI = 0.31831
area(radius) = PI * radius^2
export PI, INV_PI, area
end
@testitem "Arithmetic" setup=[TestIrrationals] begin
@test 1 / PI ≈ INV_PI atol=1e-6
end
@testitem "Geometry" setup=[TestIrrationals] begin
@test area(1) ≈ PI
end
If a @testitem
is known to be flaky, i.e. contains tests that sometimes don't pass, then you can set it to automatically retry by passing the retries
keyword. If a @testitem
passes on retry, then it will be recorded as passing in the test summary.
@testitem "Flaky test" retries=1 begin
@test rand() < 1e-4
end
If a @testitem
should be aborted after a certain period of time, e.g. the test is known to occassionally hang, then you can set a timeout (in seconds) by passing the timeout
keyword. Note that timeout
currently only works when tests are run with multiple workers.
@testitem "Sometimes too slow" timeout=10 begin
@test sleep(rand(1:100))
end
If a @testitem
needs to be skipped, then you can set the skip
keyword. Either pass skip=true
to unconditionally skip the test item, or pass skip
an expression that returns a Bool
to determine if the testitem should be skipped.
@testitem "Skip on old Julia" skip=(VERSION < v"1.9") begin
v = [1]
@test 0 == @allocations sum(v)
end
The skip
expression is run in its own module, just like a test-item. No code inside a @testitem
is run when a test-item is skipped.
ReTestItems.@testsetup
— Macro@testsetup module MyTestSetup
# code that can be shared between @testitems
end
A module only used for tests, and which @testitem
s can depend on.
Useful for setup logic that is used across multiple test items. The setup will run once, before any @testitem
that requires it is executed. If running with multiple processes, each test-setup with be run once on each process.
Each test-setup module will live for the lifetime of the tests. Mutable state should be avoided, since the order in which test items run is non-deterministic, and test items may access the same test-setup module concurrently in the same process.
Other than being declared with the @testsetup
macro, to make then knowable to @testitem
s, test-setup modules are just like other modules and can import dependencies and export names.
A @testitem
depends on a @testsetup
via the setup
keyword e.g
@testitem "MyTests1" setup=[MyTestSetup]
# tests that require MyTestSetup
end