1
0
mirror of https://github.com/Refactorio/RedMew.git synced 2025-02-11 13:39:17 +02:00

context improvements

This commit is contained in:
James Gillham 2020-09-28 20:40:47 +01:00
parent 0aff9aabdd
commit b4fa00ccdf
10 changed files with 188 additions and 124 deletions

View File

@ -13,8 +13,7 @@ Declare.module(
Declare.module_startup(
function(context)
local player = game.get_player(1)
teardown = Helper.startup_test_surface(context, player)
teardown = Helper.startup_test_surface(context)
end
)
@ -26,9 +25,9 @@ Declare.module(
Declare.test(
'can remove landfill',
function()
function(context)
-- Arrange
local player = game.get_player(1)
local player = context.player
local surface = player.surface
local position = {2, 2}
@ -65,9 +64,9 @@ Declare.module(
for _, item_name in pairs(items) do
Declare.test(
'can remove landfill when covered by ' .. item_name,
function()
function(context)
-- Arrange
local player = game.get_player(1)
local player = context.player
local surface = player.surface
local position = {2, 2}
surface.set_tiles({{name = 'landfill', position = position}})

View File

@ -15,8 +15,8 @@ Declare.module(
for _, name in pairs(Gui._top_elements) do
Declare.test(
'can toggle - ' .. Gui.names[name],
function(steps)
local player = game.get_player(1)
function(context)
local player = context.player
local element = player.gui.top[name]
local event = EventFactory.on_gui_click(element, player.index)
local click_action = function()
@ -34,7 +34,7 @@ Declare.module(
)
-- Close
steps:next(click_action):next(
context:next(click_action):next(
function()
local after_close_count = count_gui_elements(player.gui)
Assert.equal(

View File

@ -1,11 +1,18 @@
local ModuleStore = require 'utils.test.module_store'
local Steps = require 'utils.test.steps'
local Context = require 'utils.test.context'
local Public = {}
local is_init = false
local id_count = 0
local function get_id()
id_count = id_count + 1
return id_count
end
local function init_inner(module, depth)
module.id = get_id()
module.depth = depth
local count = 0
@ -14,10 +21,11 @@ local function init_inner(module, depth)
for name, func in pairs(module.test_funcs) do
count = count + 1
tests[#tests + 1] = {
id = get_id(),
name = name,
module = module,
func = func,
steps = nil,
context = nil,
current_step = nil,
passed = nil,
error = nil
@ -47,7 +55,7 @@ function Public.get_root_modules()
return ModuleStore.root_module
end
local function prepare_pre_module_hooks(module, runnables)
local function prepare_pre_module_hooks(module, runnables, player)
local startup_func = module.startup_func
if startup_func then
runnables[#runnables + 1] = {
@ -55,23 +63,23 @@ local function prepare_pre_module_hooks(module, runnables)
name = 'startup',
module = module,
func = startup_func,
steps = Steps.new(),
context = Context.new(player),
current_step = 0,
error = nil
}
end
end
local function build_pre_module_hooks(module, runnables)
local function build_pre_module_hooks(module, runnables, player)
if module == nil then
return
end
build_pre_module_hooks(module.parent, runnables)
prepare_pre_module_hooks(module, runnables)
build_pre_module_hooks(module.parent, runnables, player)
prepare_pre_module_hooks(module, runnables, player)
end
local function prepare_post_module_hooks(module, runnables)
local function prepare_post_module_hooks(module, runnables, player)
local teardown_func = module.teardown_func
if teardown_func then
runnables[#runnables + 1] = {
@ -79,66 +87,66 @@ local function prepare_post_module_hooks(module, runnables)
name = 'teardown',
module = module,
func = teardown_func,
steps = Steps.new(),
context = Context.new(player),
current_step = 0,
error = nil
}
end
end
local function build_post_module_hooks(module, runnables)
local function build_post_module_hooks(module, runnables, player)
if module == nil then
return
end
prepare_post_module_hooks(module, runnables)
build_post_module_hooks(module.parent, runnables)
prepare_post_module_hooks(module, runnables, player)
build_post_module_hooks(module.parent, runnables, player)
end
local function prepare_test(test)
test.steps = Steps.new()
local function prepare_test(test, player)
test.context = Context.new(player)
test.current_step = 0
test.passed = nil
test.error = nil
return test
end
local function prepare_module(module, runnables)
local function prepare_module(module, runnables, player)
module.passed = nil
prepare_pre_module_hooks(module, runnables)
prepare_pre_module_hooks(module, runnables, player)
for _, test in pairs(module.tests) do
prepare_test(test)
prepare_test(test, player)
runnables[#runnables + 1] = test
end
for _, child in pairs(module.children) do
prepare_module(child, runnables)
prepare_module(child, runnables, player)
end
prepare_post_module_hooks(module, runnables)
prepare_post_module_hooks(module, runnables, player)
end
function Public.build_test_for_run(test)
function Public.build_test_for_run(test, player)
Public.init()
local runnables = {}
build_pre_module_hooks(test.module, runnables)
runnables[#runnables + 1] = prepare_test(test)
build_post_module_hooks(test.module, runnables)
build_pre_module_hooks(test.module, runnables, player)
runnables[#runnables + 1] = prepare_test(test, player)
build_post_module_hooks(test.module, runnables, player)
return runnables
end
function Public.build_module_for_run(module)
function Public.build_module_for_run(module, player)
Public.init()
local runnables = {}
build_pre_module_hooks(module.parent, runnables)
prepare_module(module, runnables)
build_post_module_hooks(module.parent, runnables)
build_pre_module_hooks(module.parent, runnables, player)
prepare_module(module, runnables, player)
build_post_module_hooks(module.parent, runnables, player)
return runnables
end

View File

@ -12,10 +12,15 @@ Command.add(
function(args, player)
local open = args.open
if open == 'open' or open == 'o' then
if player == nil then
print('Can not open test runner from server console.')
return
end
Viewer.open(player)
return
end
Runner.run_module()
Runner.run_module(nil, player)
end
)

22
utils/test/context.lua Normal file
View File

@ -0,0 +1,22 @@
local Public = {}
Public.__index = Public
function Public.new(player)
return setmetatable({player = player, _steps = {}}, Public)
end
function Public.timeout(self, delay, func)
local steps = self._steps
steps[#steps + 1] = {func = func, delay = delay or 1}
return self
end
function Public.next(self, func)
return self:timeout(1, func)
end
function Public.get_step(self, index)
return self._steps[index]
end
return Public

View File

@ -65,11 +65,12 @@ local cliff_settings = {
name = 'cliff'
}
function Public.startup_test_surface(context, player, options)
function Public.startup_test_surface(context, options)
options = options or {}
local name = options.name or get_surface_name()
local area = options.area or {64, 64}
local player = context.player
local old_surface = player.surface
local old_position = player.position

View File

@ -2,6 +2,7 @@ local Public = {}
local function new_module(module_name)
return {
id = nil,
name = module_name,
parent = nil,
children = {},

View File

@ -12,7 +12,7 @@ Public.events = {
tests_run_finished = Event.generate_event_name('test_run_finished')
}
local run_tests_token
local run_runnables_token
local function print_summary(count, fail_count)
local pass_count = count - fail_count
@ -52,7 +52,7 @@ end
local function finish_test_run(data)
print_summary(data.count, data.fail_count)
mark_modules_for_passed()
script.raise_event(Public.events.tests_run_finished, {})
script.raise_event(Public.events.tests_run_finished, {player = data.player})
end
local function print_error(test_name, error_message)
@ -76,7 +76,8 @@ local function record_hook_error_in_module(hook)
end
local function run_hook(hook)
local steps = hook.steps
local context = hook.context
local steps = context._steps
local current_step = hook.current_step
local func
if current_step == 0 then
@ -84,7 +85,7 @@ local function run_hook(hook)
else
func = steps[current_step].func
end
local success, return_value = pcall(func, steps)
local success, return_value = pcall(func, context)
if not success then
hook.error = return_value
@ -104,19 +105,20 @@ local function do_hook(hook, data)
local hook_success = run_hook(hook)
if hook_success == nil then
local step_index = hook.current_step + 1
local step = hook.steps[step_index]
local step = hook.context._steps[step_index]
hook.current_step = step_index
Task.set_timeout_in_ticks(step.delay or 1, run_tests_token, data)
Task.set_timeout_in_ticks(step.delay or 1, run_runnables_token, data)
return
end
data.index = data.index + 1
Task.set_timeout_in_ticks(1, run_tests_token, data)
Task.set_timeout_in_ticks(1, run_runnables_token, data)
return
end
local function run_test(test)
local steps = test.steps
local context = test.context
local steps = context._steps
local current_step = test.current_step
local func
if current_step == 0 then
@ -124,7 +126,7 @@ local function run_test(test)
else
func = steps[current_step].func
end
local success, return_value = pcall(func, steps)
local success, return_value = pcall(func, context)
if not success then
print_error(test.name, return_value)
@ -149,24 +151,24 @@ local function do_test(test, data)
data.count = data.count + 1
data.fail_count = data.fail_count + 1
data.index = data.index + 1
Task.set_timeout_in_ticks(1, run_tests_token, data)
Task.set_timeout_in_ticks(1, run_runnables_token, data)
return
end
if success == true then
data.count = data.count + 1
data.index = data.index + 1
Task.set_timeout_in_ticks(1, run_tests_token, data)
Task.set_timeout_in_ticks(1, run_runnables_token, data)
return
end
local step_index = test.current_step + 1
test.current_step = step_index
local step = test.steps[step_index]
Task.set_timeout_in_ticks(step.delay or 1, run_tests_token, data)
local step = test.context._steps[step_index]
Task.set_timeout_in_ticks(step.delay or 1, run_runnables_token, data)
end
local function run_tests(data)
local function run_runnables(data)
local index = data.index
local runnable = data.runnables[index]
@ -183,20 +185,20 @@ local function run_tests(data)
do_test(runnable, data)
end
run_tests_token = Token.register(run_tests)
run_runnables_token = Token.register(run_runnables)
local function run(runnables)
run_tests({runnables = runnables, index = 1, count = 0, fail_count = 0})
local function run(runnables, player)
run_runnables({runnables = runnables, player = player, index = 1, count = 0, fail_count = 0})
end
function Public.run_module(module)
local runnables = Builder.build_module_for_run(module or ModuleStore.root_module)
run(runnables)
function Public.run_module(module, player)
local runnables = Builder.build_module_for_run(module or ModuleStore.root_module, player)
run(runnables, player)
end
function Public.run_test(test)
local runnables = Builder.build_test_for_run(test)
run(runnables)
function Public.run_test(test, player)
local runnables = Builder.build_test_for_run(test, player)
run(runnables, player)
end
return Public

View File

@ -1,17 +0,0 @@
local Public = {}
Public.__index = Public
function Public.new()
return setmetatable({}, Public)
end
function Public.timeout(self, delay, func)
self[#self + 1] = {func = func, delay = delay or 1}
return self
end
function Public.next(self, func)
return self:timeout(1, func)
end
return Public

View File

@ -5,11 +5,19 @@ local Color = require 'resources.color_presets'
local Token = require 'utils.token'
local Task = require 'utils.task'
local Event = require 'utils.event'
local Global = require 'utils.global'
local Public = {}
local info_type_test = {}
local info_type_module = {}
local down_arrow = ''
local right_arrow = ''
local color_success = {g = 1}
local color_failure = {r = 1}
local color_selected = Color.orange
local color_default = Color.white
local main_frame_name = Gui.uid_name()
local close_main_frame_name = Gui.uid_name()
@ -20,8 +28,16 @@ local run_all_button_name = Gui.uid_name()
local run_selected_button_name = Gui.uid_name()
local error_test_box_name = Gui.uid_name()
local selected_modules = {}
local selected_tests = {}
local selected_test_info_by_player_index = {}
Global.register(
{
selected_test_info_by_player_index = selected_test_info_by_player_index
},
function(tbl)
selected_test_info_by_player_index = tbl.selected_test_info_by_player_index
end
)
local function get_module_state(module)
local passed = module.passed
@ -51,45 +67,74 @@ local function get_module_error(module)
return table.concat(errors)
end
local function get_text_box_error()
local selected_test = next(selected_tests)
if selected_test then
return get_test_error(selected_test)
local function get_text_box_error(player_index)
local test_info = selected_test_info_by_player_index[player_index]
if test_info == nil then
return ''
end
local selected_module = next(selected_modules)
if selected_module then
return get_module_error(selected_module)
end
local info_type = test_info.type
return ''
if info_type == info_type_test then
return get_test_error(test_info.test)
elseif info_type == info_type_module then
return get_module_error(test_info.module)
end
end
local function set_selected_style(style, selected)
if selected then
style.font_color = Color.orange
style.font_color = color_selected
else
style.font_color = Color.white
style.font_color = color_default
end
end
local function set_passed_style(style, passed)
if passed == true then
style.font_color = Color.green
style.font_color = color_success
elseif passed == false then
style.font_color = Color.red
style.font_color = color_failure
else
style.font_color = Color.white
style.font_color = color_default
end
end
local function is_test_selected(test, player_index)
local info = selected_test_info_by_player_index[player_index]
if not info then
return false
end
local info_test = info.test
if not info_test then
return false
end
return info_test.id == test.id
end
local function is_module_selected(module, player_index)
local info = selected_test_info_by_player_index[player_index]
if not info then
return false
end
local info_module = info.module
if not info_module then
return false
end
return info_module.id == module.id
end
local function draw_tests_test(container, test, depth)
local flow = container.add {type = 'flow'}
local label = flow.add {type = 'label', name = test_label_name, caption = test.name}
local label_style = label.style
local is_selected = selected_tests[test]
local is_selected = is_test_selected(test, container.player_index)
set_selected_style(label_style, is_selected)
if not is_selected then
set_passed_style(label_style, test.passed)
@ -116,7 +161,7 @@ local function draw_tests_module(container, module)
local label = flow.add {type = 'label', name = module_label_name, caption = caption}
local label_style = label.style
local is_selected = selected_modules[module]
local is_selected = is_module_selected(module, container.player_index)
set_selected_style(label_style, is_selected)
if not is_selected then
set_passed_style(label_style, get_module_state(module))
@ -178,9 +223,8 @@ local function create_main_frame(center)
frame_style.height = 600
local top_flow = frame.add {type = 'flow', direction = 'horizontal'}
local run_all_button = top_flow.add {type = 'button', name = run_all_button_name, caption = 'Run All'}
local run_selected_button =
top_flow.add {
top_flow.add {type = 'button', name = run_all_button_name, caption = 'Run All'}
top_flow.add {
type = 'button',
name = run_selected_button_name,
caption = 'Run Selected'
@ -207,15 +251,15 @@ end
local run_module_token =
Token.register(
function(module)
Runner.run_module(module)
function(data)
Runner.run_module(data.module, data.player)
end
)
local run_test_token =
Token.register(
function(test)
Runner.run_test(test)
function(data)
Runner.run_test(data.test, data.player)
end
)
@ -248,14 +292,13 @@ Gui.on_click(
local data = Gui.get_data(element)
local module = data.module
local container = data.container
local player_index = event.player_index
local is_selected = not selected_modules[module]
table.clear_table(selected_modules)
table.clear_table(selected_tests)
local is_selected = not is_module_selected(module, player_index)
selected_test_info_by_player_index[player_index] = nil
if is_selected then
selected_modules[module] = is_selected
selected_test_info_by_player_index[player_index] = {type = info_type_module, module = module}
end
local error_text_box = get_error_text_box(event.player)
@ -276,14 +319,13 @@ Gui.on_click(
local data = Gui.get_data(element)
local test = data.test
local container = data.container
local player_index = event.player_index
local is_selected = not selected_tests[test]
table.clear_table(selected_modules)
table.clear_table(selected_tests)
local is_selected = not is_test_selected(test, player_index)
selected_test_info_by_player_index[player_index] = nil
if is_selected then
selected_tests[test] = is_selected
selected_test_info_by_player_index[player_index] = {type = info_type_test, test = test}
end
local error_text_box = get_error_text_box(event.player)
@ -302,20 +344,23 @@ Gui.on_click(
function(event)
local frame = event.player.gui.center[main_frame_name]
close_main_frame(frame)
Task.set_timeout_in_ticks(1, run_module_token, nil)
Task.set_timeout_in_ticks(1, run_module_token, {module = nil, player = event.player})
end
)
Gui.on_click(
run_selected_button_name,
function(event)
local selected_module = next(selected_modules)
local selected_test = next(selected_tests)
local test_info = selected_test_info_by_player_index[event.player_index]
if test_info == nil then
return
end
if selected_module then
Task.set_timeout_in_ticks(1, run_module_token, selected_module)
elseif selected_test then
Task.set_timeout_in_ticks(1, run_test_token, selected_test)
local info_type = test_info.type
if info_type == info_type_module then
Task.set_timeout_in_ticks(1, run_module_token, {module = test_info.module, player = event.player})
elseif info_type == info_type_test then
Task.set_timeout_in_ticks(1, run_test_token, {test = test_info.test, player = event.player})
else
return
end
@ -327,14 +372,12 @@ Gui.on_click(
Event.add(
Runner.events.tests_run_finished,
function()
local player = game.get_player(1)
Public.open(player)
function(event)
Public.open(event.player)
end
)
function Public.open(player)
player = player or game.player
local center = player.gui.center
local frame = center[main_frame_name]
if frame then