Skip to content

Instantly share code, notes, and snippets.

@ExpandingMan
Last active December 21, 2017 17:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ExpandingMan/1db7b6038135eb8fffc9c0810c2e298b to your computer and use it in GitHub Desktop.
Save ExpandingMan/1db7b6038135eb8fffc9c0810c2e298b to your computer and use it in GitHub Desktop.
rough, primitive proof-of-concept for automated random unit testing in Julia
using Base.Test
using MacroTools
"""
argnametype(arg::Expr)
Given an argument of the form `x::DType` extracts the argument name (`x`) and
data type (`DType`) as a tuple.
"""
function argnametype(arg::Expr)
if @capture(arg, x_::T_)
return x, T
end
throw(ArgumentError("Malformed argument $arg"))
end
"""
randex(dtype::Symbol)
Generates an expression creating a random instance of the type `dtype`.
**TODO** Would have to implement `rand` for every possible argument type.
"""
randex(dtype::Union{Symbol, <:Type}) = :(rand($dtype))
"""
gentest(fname::Symbol, args::Vector)
Generate an expression for testing the function of name `fname` on argument expressions.
"""
function gentest(fname::Symbol, types::Vector{Symbol})
ex = :(@test ($fname($(randex.(types)...)); true))
Expr(:quote, ex)
end
gentest(fname::Symbol, args::Vector) = gentest(fname, Symbol[x[2] for x ∈ argnametype.(args)])
"""
@gentest function f(x::DT1, y::DT2, z::DT3)
# body
end tests
Declares the function provided and appends an expression with a random unit tests to the container
`tests`.
"""
macro gentest(func, tests)
@capture(func, function f_(args__) body_ end)
esc(quote
$func
push!($tests, $(gentest(f, args)))
end)
end
"""
runtests(expr::Expr, N::Integer)
Runs test given in the expression `expr` `N` times. This is for cases in which
`expr` contains calls to an RNG so that the tests are different each time.
"""
function runtests(expr::Expr, N::Integer)
for i ∈ 1:N
eval(expr)
end
end
#===============================================================================================
**EXAMPLE**
Here we have an example of our very simple proof-of-concept for automated random unit
testing. We declare a function `f` and test that it executes without errors 5 times.
Distinct random inputs are generated on each test run.
===============================================================================================#
tests = Vector{Expr}()
@gentest function f(x::Float64, y::Int64)
x + y
end tests
@testset begin
runtests.(tests, 5)
end
#===============================================================================================#
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment