-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Allow @test_nothrow to catch 'no error' for simple smoke tests #18780
Comments
I've spent far too much time thinking about this, a few weeks back. You can readily approximate that by doing something like After a fair bit of thought on that, getting into the semantics of what is an
I think preferable would be the syntax One thing to note, is that this is not present in most testing frameworks.
The only framework I've fount that has it is nUnit, which as DoesNotThrow in classic mode, and ThrowsNothing in constraint mode. |
I know it's not the same, but rspec for ruby uses the syntax:
which came from: |
I don't really get the application. Why do you need a testing construct for this at all? Every statement is implicitly |
I see where you're coming from.
Feel free to close issue at your own discretion |
FWIW I feel like this problem can be addressed by commenting the tests more aggressively than we currently do. I often look at the base Julia tests and think "it sure would be nice to know what this is trying to show works!" Even a simple "test that X doesn't explode immediately" comment block would be good. |
@test_no_error Foo(42) "Foo can be constructed with integer value" |
I agree with the others that I don't think such a construct is that generally useful. Though for the sake of completeness, you can obtain what you're looking for relatively easily using existing machinery, it's just a little hacky and ugly: using Base.Test
f(x::Int) = 1
@test !isa(try f(1) catch ex ex end, Exception) # Passes
@test !isa(try f(1.0) catch ex ex end, Exception) # Fails Assuming you know the value of |
Ok, I see where this is coming from. You could do this: macro no_error(ex)
quote
try
$(esc(ex))
true
catch
false
end
end
end
julia> @no_error 1 + 2
true
julia> @no_error error()
false
julia> @test @no_error 1 + 2
Test Passed
Expression: @no_error 1 + 2
julia> @test @no_error error()
Test Failed
Expression: @no_error error()
ERROR: There was an error during testing
in record(::Base.Test.FallbackTestSet, ::Base.Test.Fail) at ./test.jl:397
in do_test(::Base.Test.Returned, ::Expr) at ./test.jl:281 The main issue with using this is that no hint is given as to what error is thrown on failure. Hmm. I'm a bit ambivalent about whether this warrants a whole new |
I would find this construct useful for testing functions which (mainly) have side effects. Eg when I implement a method for |
Currently we have Here is a possible use case. Suppose you want to test a method that returns no results. But you know it throws an exception if some condition is not met. If you know in a certain context the condition should hold, the only way to test it would be to make sure that the method doesn't throw the exception. I don't agree with a generic
|
Sure, I guess if someone wants to put together a |
FWIW, I found myself searching for this functionality, too. I ended up hacking together this solution (amusingly, with the same macro name):
Of course, I'm not suggesting this implementation. But I agree with @tpapp that it would be nice to have an explicit, self-documenting test that just says "this code should run without issues" as a kind of sanity check. |
Why not |
Yes those would surely work for my case, though I do feel that But more generally I think the proposal of @cossio above would be useful. My example would then be a special case: |
That proposal does seem reasonable. The fail/error distinction makes sense to me. |
I wonder if we could shove this functionality into @test_throws Union{Nothing,DomainError} maybe_domain_error(a, b)
@test_throws Nothing this_should_just_run(c, d) |
I just had the same which for a I came up with the following definition, which is more or less just the code by @test_throws with different return objects. module TestNoThrows
export @test_nothrows
using Test: Returned, Threw, Fail, Error, Pass, record, get_testset, ExecutionResult
"""
@test_nothrows exception expr
Tests that the expression `expr` does not throw `exception`.
"""
macro test_nothrows(extype, ex)
orig_ex = Expr(:inert, ex)
result = quote
try
Returned($(esc(ex)), nothing, $(QuoteNode(__source__)))
catch _e
if $(esc(extype)) != InterruptException && _e isa InterruptException
rethrow()
end
Threw(_e, Base.current_exceptions(), $(QuoteNode(__source__)))
end
end
Base.remove_linenums!(result)
:(do_test_nothrows($result, $orig_ex, $(esc(extype))))
end
# An internal function, called by the code generated by @test_throws
# to evaluate and catch the thrown exception - if it exists
function do_test_nothrows(result::ExecutionResult, orig_expr, extype)
if isa(result, Threw)
# Check that the right type of exception was thrown
success = false
message_only = false
exc = result.exception
if isa(extype, Type)
success = isa(exc, extype)
elseif isa(extype, Exception) || !isa(exc, Exception)
if extype isa LoadError && !(exc isa LoadError) && typeof(extype.error) == typeof(exc)
extype = extype.error # deprecated
end
if isa(exc, typeof(extype))
success = true
for fld in 1:nfields(extype)
if !isequal(getfield(extype, fld), getfield(exc, fld))
success = false
break
end
end
end
else
message_only = true
exc = sprint(showerror, exc)
success = contains_warn(exc, extype)
exc = repr(exc)
if isa(extype, AbstractString)
extype = repr(extype)
elseif isa(extype, Function)
extype = "< match function >"
end
end
if success
# the semantics is exactly the opposite of test_throws
testres = Fail(:test_throws, orig_expr, extype, exc, result.source, message_only)
else
testres = Error(:test_error, orig_expr, exc, result.backtrace::Vector{Any}, result.source)
end
else
testres = Pass(:test_throws_nothing, orig_expr, extype, nothing, result.source)
end
record(get_testset(), testres)
end
end # module TestNoThrows I never did an addition to Julia Test or any core Julia package. |
I've now visited this thread for the second time and still can't really figure out what the argument is against In my case: I'm trying to remove some method ambiguities and all I want to confirm is that a particular function can be called with particular arguments without throwing a MethodError. I don't want to test anything about the output because is simply besides the point of the test. |
Here's a real-life example for wanting I was looking at a test in our codebase which was written as
for some particular So the test, as written, communicated the wrong thing to me about what the test was really for, whereas if it had been
I would have understood its purpose immediately, saved half an hour of my morning, and understood our code base better. |
I think that this issue is just waiting for someone to create a PR. |
I want to be able to do a quick
@test_throws nothing Foo(42)
to run a simple smoke test.The current documentation makes it look like this is not an option
The text was updated successfully, but these errors were encountered: