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
50 changes: 45 additions & 5 deletions addons/gut/error_tracker.gd
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,36 @@ func _is_error_failable(error : GutTrackedError):
is_it = treat_engine_errors_as == GutUtils.TREAT_AS.FAILURE
return is_it


# Returns the line number in the test script where the error occurred. This
# is only usable for engine and push errors.
func _get_line_number_in_test(test_id, error):
if(error.is_gut_error()):
return -1

# This is bad. It has to know too much. gut.gd is making up the test_id.
# This script just expects it to be unique. Now this is desconstructing
# it. test_id construction should be moved into this class.
var parts = test_id.split(":")
if(parts.size() != 2):
return -1
var test_name = test_id.split(":")[1]

# There might be some assumptions being made here that could return
# misleading line numbers. Maybe.
var to_return = -1
var i = 0
while(i < error.backtrace.size() and to_return == -1):
var bt = error.backtrace[i]
var y = 0
while(y < bt.get_frame_count() and to_return == -1):
if(bt.get_frame_function(y) == test_name):
to_return = bt.get_frame_line(y)
y += 1
i += 1
return to_return


# ----------------
#endregion
#region Godot's Logger Overrides
Expand All @@ -88,6 +118,7 @@ func _log_error(function: String, file: String, line: int,
code, rationale, editor_notify,
error_type, script_backtraces)


# Godot's Logger virtual method for any output?
# func _log_message(message: String, error: bool) -> void:
# pass
Expand All @@ -113,8 +144,8 @@ func get_current_test_errors():
return errors.items.get(_current_test_id, [])


# This should look through all the errors for a test and see if a failure
# should happen based off of flags.
# This looks through all the errors for a test and returns if it should fail
# based off of flags.
func should_test_fail_from_errors(test_id = _current_test_id):
var to_return = false
if(errors.items.has(test_id)):
Expand All @@ -135,15 +166,24 @@ func get_errors_for_test(test_id=_current_test_id):
return to_return


# Returns emtpy string or text for errors that occurred during the test that
# should cause failure based on this class' flags.
# Returns empty string or text for errors that occurred during the test that
# should cause failure based on this class' flags. It might be better to put
# most of this logic int gut_tracked_error.
func get_fail_text_for_errors(test_id=_current_test_id) -> String:
var error_texts = []

if(errors.items.has(test_id)):
for error in errors.items[test_id]:
if(_is_error_failable(error)):
error_texts.append(str('<', error.get_error_type_name(), '>', error.code))
var msg = str('<', error.get_error_type_name(), '>', error.rationale if error.rationale else error.code)
if error.file and error.file != GutUtils.NO_TEST and error.line >= 0:
if(error.is_engine_error()):
msg += str('\n at: ', error.function, ' (', error.file, ':', error.line, ')')

var test_line_number = _get_line_number_in_test(test_id, error)
if(test_line_number != -1):
msg += str('\n at line: ', test_line_number)
error_texts.append(msg)

var to_return = ""
for i in error_texts.size():
Expand Down
10 changes: 6 additions & 4 deletions addons/gut/gut.gd
Original file line number Diff line number Diff line change
Expand Up @@ -918,8 +918,10 @@ func get_call_count_text():
func _fail(text=''):
if(_current_test != null):
var line_number = _extract_line_number(_current_test)
var line_text = ' at line ' + str(line_number)
p(line_text, LOG_LEVEL_FAIL_ONLY)
var line_text = ''
if(line_number != -1):
line_text = ' at line ' + str(line_number)
p(line_text, LOG_LEVEL_FAIL_ONLY)
# format for summary
line_text = "\n " + line_text
var call_count_text = get_call_count_text()
Expand All @@ -935,11 +937,11 @@ func _pending(text=''):


# ------------------------------------------------------------------------------
# Extracts the line number from curren stacktrace by matching the test case name
# Extracts the line number from current stacktrace by matching the test case name
# ------------------------------------------------------------------------------
func _extract_line_number(current_test):
var line_number = -1
# if stack trace available than extraxt the test case line number
# if stack trace available than extract the test case line number
var stackTrace = get_stack()
if(stackTrace!=null):
for index in stackTrace.size():
Expand Down
8 changes: 5 additions & 3 deletions addons/gut/gut_tracked_error.gd
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ class_name GutTrackedError
## for GUT errors.

## This will be an [code]Array[ScriptBacktrace][/code] for engine/push errors.
## This will the result of [code]get_stack[/code] for GUT errors.
## This will be the result of [code]get_stack[/code] for GUT errors.
var backtrace = []
## Usually the description
var code = GutUtils.NO_TEST
Expand Down Expand Up @@ -85,8 +85,10 @@ func get_error_type_name():
return to_return


# this might not work in other languages, and feels falkey, but might be
# useful at some point.
# This might not work in other languages? Do they change words like "Assertion
# failed" when translating Godot? It feels flakey even if they don't, but might
# be useful at some point, or at least I know I thought about this already and
# didn't do it.
# func is_assert():
# return error_type == Logger.ERROR_TYPE_SCRIPT and \
# (code.find("Assertion failed.") == 0 or \
Expand Down
59 changes: 58 additions & 1 deletion test/output_tests/test_with_errors.gd
Original file line number Diff line number Diff line change
@@ -1,6 +1,63 @@
extends GutTest

func _generate_a_push_error():
push_error("hello push_error")

func test_with_push_error():
push_error('this is a push error')
assert_true(true, 'passing assert')
pass_test('has push_error')


func test_forced_engine_error() -> void:
OS.delay_usec(-10)
pass_test('has forced engine error')


func test_gut_error():
gut.get_logger().error("manual error")
pass_test('has a gut error')


func test_failing():
assert_false(true)


func test_with_two_push_error():
push_error('this is a push error')
_generate_a_push_error()
pass_test('has push_error')


func test_with_two_forced_engine_error() -> void:
OS.delay_usec(-10)
OS.delay_usec(-11)
pass_test('has forced engine error')


func test_with_two_gut_error():
gut.get_logger().error("manual error")
gut.get_logger().error("error again")
pass_test('has a gut error')



class TestInnerClassOutput:
extends GutTest

func test_with_push_error():
push_error('this is a push error')
pass_test('has push_error')


func test_forced_engine_error() -> void:
OS.delay_usec(-10)
pass_test('has forced engine error')


func test_gut_error():
gut.get_logger().error("manual error")
pass_test('has a gut error')


func test_failing():
assert_false(true)