Skip to content

Commit

Permalink
6.8.1 (#141)
Browse files Browse the repository at this point in the history
* Add assert_freed method

Asserts object has been freed from memory. We pass in a title (since if it is freed, we lost all identity data)

* Add assert_not_freed (inc tests)

Adds assert_not_freed to compliement assert_freed which can check
if an obj has or has not been deleted for memory.

Unlikely to work with reference-counted items.

* fixed indent issues and some doubling issues

* Fix 130 (#131)

* fixing script parse error: Spaces used for indentation in tab-indented file

* Use stacktrace to determine line number for failing test case

* create failing test for doubling static methdos

* created simple one-to-many datastructure in prep for ignoring methods when doubling

* ignoring methods implemented in doubler

* added ignore_method_when_doubling to test.gd

* changes

* refactor detecting scenes and scripts in test.gd

* comments and move DoubleInfo

* doubler can double native classes

* stubber supports native classes.  switched doubler to always use FULL strat for native

* test spying on native doubles

* smart double now supports native classes

* print  version info in help

* fix issue 136

* Issue 139 (#140)

* implements issue 139

* summary documentation

* abort and exit code pre/post script features

Co-authored-by: CodeDarigan <code@darigan.ie>
Co-authored-by: Mike Schulze <55910239+mschulzeLpz@users.noreply.github.com>
  • Loading branch information
3 people authored Jan 20, 2020
1 parent acde6f3 commit cfe68b3
Showing 32 changed files with 830 additions and 121 deletions.
4 changes: 2 additions & 2 deletions .gutconfig.json
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
{
"dirs":["res://test/unit/", "res://test/integration/"],
"should_maximize":true,
"should_exit":false,
"should_exit":true,
"ignore_pause":true,
"log_level": 1,
"log_level": 3,
"opacity":100,
"double_strategy":"partial",
"include_subdirs":true,
13 changes: 13 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,19 @@
# Release notes
All notable changes to this project will be documented in this file.
This project adheres to [Semantic Versioning](http://semver.org/).

# 6.8.1
## Features
* Godot 3.2 compatible.
* __Issue 124__ CodeDarigan added the `assert_freed` and `assert_not_freed` methods.
* __Issue 130__ GUT now lists the exact line number of a failing test in all cases instead of just the method number in non-inner classes. Thanks to mschulzeLpz for adding `get_stack` magic.
* __Issue 133__ You can now double/partial_double/stub/spy Native classes like `Node2D` and `Raycast2D`. Syntax is the same.
* __Issue 139__ There are now `pre` and `post` run script hooks that allow you to run your own code before any tests are run and after all tests are run. This can be useful in setting global values before a run or investigating the results of the run for CICD pipelines and the like. [Check the wiki for more info](https://github.com/bitwes/Gut/wiki/Hooks)

## Bug Fixes
* __Issue 127__ The method `ignore_method_when_doubling` was added as a workaround for doubling scripts that have static methods. The "Doubles" wiki page has more info about this method.
* __Issue 136__ Bug can happen when yielding where a `attempt to disconnect signal...while emitting` can occur. Disconnecting from signals is now done via `call_deferred`.

# 6.8.0
## Features
* __Issue 98__ Added Stubbing method `to_call_super` so that you can force a doubled object to call its super method instead of being stubbed out.
19 changes: 3 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,16 +1,8 @@
# Godot 3.2
There is the `godot_3_2` branch which is now working with 3.2 alpha 2. Any 3.2 related bugs will be fixed here then double checked for backwards compatibility with 3.1. I'll merge the branch into master when 3.2 is live.

# 6.6.0 has a potentially bad bug
__Please upgrade to the latest version.__

6.6.0 has a bug that can, if everything goes wrong just right, delete files in the root of the project. I only saw it happen when running the test suite for Gut and only the `test_doubler.gd` test script. I don't recall ever seeing it happen in my own game, but just to be safe you should upgrade.

# Gut 6.8.0
# Gut 6.8.1
GUT (Godot Unit Test) is a utility for writing tests for your Godot Engine game. It allows you to write tests for your gdscript in gdscript.

## Features
* Godot 3.0 and 3.1 compatible (There are some minor issues with 3.1 though, [check them out here](https://github.com/bitwes/Gut/wiki/Godot-3.1-Issues).
* Godot 3.0, 3.1 and 3.2 compatible (There are some minor issues with 3.1/2 though, [check them out here](https://github.com/bitwes/Gut/wiki/Godot-3.1-Issues).
* [Simple install via the Asset Library.](https://github.com/bitwes/Gut/wiki/Install)
* [A plethora of asserts and utility methods to help make your tests simple and concise.](https://github.com/bitwes/Gut/wiki/Methods)
* [Support for Inner Test Classes to give your tests some extra context and maintainability.](https://github.com/bitwes/Gut/wiki/Inner-Test-Classes)
@@ -23,10 +15,6 @@ GUT (Godot Unit Test) is a utility for writing tests for your Godot Engine game.

More info can be found in the [wiki](https://github.com/bitwes/Gut/wiki).

## Upgrading to 6.8.0 from any 6.6.x version
* It is not required, but you should remove the existing Gut node for any scenes you have that use it and then re-add it and re-configure it. Re-adding will get rid of the caution symbol next to the control (this is due to changes in inheritance, Gut changed from a `WindowDialog` to a `Control`)
* For the command line, note that the `log` option in the `.gutconfig.json` file has changed to `log_level` for consistency.

# License
Gut is provided under the MIT license. License is in `addons/gut/LICENSE.md`

@@ -39,5 +27,4 @@ Gut is provided under the MIT license. License is in `addons/gut/LICENSE.md`

## [Tutorials](https://github.com/bitwes/Gut/wiki/Tutorials)
* [Here's a short setup tutorial provided by Rainware](https://www.youtube.com/watch?v=vBbqlfmcAlc)
* [TDD and P O N G Episode 1](https://www.youtube.com/watch?v=nF2gPF69Dc4&t=3s)
* [TDD and P O N G Episode 2](https://www.youtube.com/watch?v=rNN0Xw1R_1E&t=2s)
* [TDD and P O N G Series](https://www.youtube.com/channel/UCkGO6guRt_5fOh3oDHbfg9w/playlists)
82 changes: 74 additions & 8 deletions addons/gut/doubler.gd
Original file line number Diff line number Diff line change
@@ -24,6 +24,8 @@ class ScriptMethods:
'_set',
'_get', # probably
'emit_signal', # can't handle extra parameters to be sent with signal.
'draw_mesh', # issue with one parameter, value is `Null((..), (..), (..))``
'_to_string', # nonexistant function ._to_string
]

var built_ins = []
@@ -68,6 +70,8 @@ class ObjectInfo:
var _method_strategy = null
var make_partial_double = false
var scene_path = null
var _native_class = null
var _native_class_instance = null

func _init(path, subpath=null):
_path = path
@@ -76,7 +80,12 @@ class ObjectInfo:

# Returns an instance of the class/inner class
func instantiate():
return get_loaded_class().new()
var to_return = null
if(is_native()):
to_return = _native_class.new()
else:
to_return = get_loaded_class().new()
return to_return

# Can't call it get_class because that is reserved so it gets this ugly name.
# Loads up the class and then any inner classes to give back a reference to
@@ -100,9 +109,15 @@ class ObjectInfo:
return _subpaths.size() != 0

func get_extends_text():
var extend = str("extends '", get_path(), '\'')
var extend = null
if(is_native()):
extend = str("extends ", get_native_class_name())
else:
extend = str("extends '", get_path(), '\'')

if(has_subpath()):
extend += str('.', get_subpath().replace('/', '.'))

return extend

func get_method_strategy():
@@ -111,15 +126,28 @@ class ObjectInfo:
func set_method_strategy(method_strategy):
_method_strategy = method_strategy

func is_native():
return _native_class != null

func set_native_class(native_class):
_native_class = native_class
_native_class_instance = native_class.new()
_path = _native_class_instance.get_class()

func get_native_class_name():
return _native_class_instance.get_class()

# ------------------------------------------------------------------------------
# START Doubler
# ------------------------------------------------------------------------------
var _utils = load('res://addons/gut/utils.gd').new()

var _output_dir = null
var _double_count = 0 # used in making files names unique
var _use_unique_names = true
var _spy = null
var _ignored_methods = _utils.OneToMany.new()

var _utils = load('res://addons/gut/utils.gd').new()
var _stubber = _utils.Stubber.new()
var _lgr = _utils.get_logger()
var _method_maker = _utils.MethodMaker.new()
@@ -158,7 +186,12 @@ func _write_file(obj_info, dest_path, override_path=null):
metadata = _get_stubber_metadata_text(obj_info, override_path)

var f = File.new()
f.open(dest_path, f.WRITE)
var f_result = f.open(dest_path, f.WRITE)

if(f_result != OK):
print('Error creating file ', dest_path)
print('Could not create double for :', obj_info.to_s())
return

f.store_string(str(obj_info.get_extends_text(), "\n"))
f.store_string(metadata)
@@ -216,7 +249,7 @@ func _get_methods(object_info):
for i in range(methods.size()):
# 65 is a magic number for methods in script, though documentation
# says 64. This picks up local overloads of base class methods too.
if(methods[i].flags == 65):
if(methods[i].flags == 65 and !_ignored_methods.has(object_info.get_path(), methods[i]['name'])):
script_methods.add_local_method(methods[i])


@@ -225,7 +258,7 @@ func _get_methods(object_info):
for i in range(methods.size()):
# 65 is a magic number for methods in script, though documentation
# says 64. This picks up local overloads of base class methods too.
if(methods[i].flags != 65):
if(methods[i].flags != 65 and !_ignored_methods.has(object_info.get_path(), methods[i]['name'])):
script_methods.add_built_in_method(methods[i])

return script_methods
@@ -285,8 +318,14 @@ func _get_super_func_text(method_hash):

# returns the path to write the double file to
func _get_temp_path(object_info):
var file_name = object_info.get_path().get_file().get_basename()
var extension = object_info.get_path().get_extension()
var file_name = null
var extension = null
if(object_info.is_native()):
file_name = object_info.get_native_class_name()
extension = 'gd'
else:
file_name = object_info.get_path().get_file().get_basename()
extension = object_info.get_path().get_extension()

if(object_info.has_subpath()):
file_name += '__' + object_info.get_subpath().replace('/', '__')
@@ -331,6 +370,17 @@ func _double_scene(path, make_partial, strategy):

return load(temp_path)

func _double_gdnative(native_class, make_partial, strategy):
var oi = ObjectInfo.new(null)
oi.set_native_class(native_class)
oi.set_method_strategy(strategy)
oi.make_partial_double = make_partial
var to_return = load(_double(oi))

return to_return



# ###############
# Public
# ###############
@@ -388,6 +438,16 @@ func partial_double_inner(path, subpath, strategy=_strategy):
func double_inner(path, subpath, strategy=_strategy):
return _double_inner(path, subpath, false, strategy)

# must always use FULL strategy since this is a native class and you won't get
# any methods if you don't use FULL
func double_gdnative(native_class):
return _double_gdnative(native_class, false, _utils.DOUBLE_STRATEGY.FULL)

# must always use FULL strategy since this is a native class and you won't get
# any methods if you don't use FULL
func partial_double_gdnative(native_class):
return _double_gdnative(native_class, true, _utils.DOUBLE_STRATEGY.FULL)

func clear_output_directory():
var did = false
if(_output_dir.find('user://') == 0):
@@ -419,3 +479,9 @@ func delete_output_directory():
# weird, hard to track down problems.
func set_use_unique_names(should):
_use_unique_names = should

func add_ignored_method(path, method_name):
_ignored_methods.add(path, method_name)

func get_ignored_methods():
return _ignored_methods
Loading

0 comments on commit cfe68b3

Please sign in to comment.