mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-08-27 23:27:34 +01:00
Allows for offloaded tests to be focused (#71719)
Focusing a test through TEST_FOCUS allows you to only run that one test. It's very useful for developing. However, we have a bunch of offloaded tests in `#ifdef UNIT_TESTS` that would not be focused. This changes it so that those tests will now only run if either no test is focused, or if their specific "focus only" test is focused. This is done through a `PERFORM_ALL_TESTS` macro that replaces the `#ifdef UNIT_TESTS`. This is completely free because `if (FALSE)` constant folds. Hide whitespace mode recommended.
This commit is contained in:
@@ -24,10 +24,3 @@
|
||||
/// : because of the embedded typecheck
|
||||
#define text_ref(datum) (isdatum(datum) ? (datum:cached_ref ||= "\ref[datum]") : ("\ref[datum]"))
|
||||
|
||||
/// ASSERT(), but it only actually does anything during unit tests
|
||||
#ifdef UNIT_TESTS
|
||||
#define TEST_ONLY_ASSERT(test, explanation) if(!(test)) {CRASH(explanation)}
|
||||
#else
|
||||
#define TEST_ONLY_ASSERT(test, explanation)
|
||||
#endif
|
||||
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
/// Are tests enabled with no focus?
|
||||
/// Use this when performing test assertions outside of a unit test,
|
||||
/// since a focused test means that you're trying to run a test quickly.
|
||||
/// If a parameter is provided, will check if the focus is on that test name.
|
||||
/// For example, PERFORM_ALL_TESTS(log_mapping) will only run if either
|
||||
/// no test is focused, or the focus is log_mapping.
|
||||
#ifdef UNIT_TESTS
|
||||
// Bit of a trick here, if focus isn't passed in then it'll check for /datum/unit_test/, which is never the case.
|
||||
#define PERFORM_ALL_TESTS(focus...) (isnull(GLOB.focused_test) || GLOB.focused_test == /datum/unit_test/##focus)
|
||||
#else
|
||||
// UNLINT necessary here so that if (PERFORM_ALL_TESTS()) works
|
||||
#define PERFORM_ALL_TESTS(...) UNLINT(FALSE)
|
||||
#endif
|
||||
|
||||
/// ASSERT(), but it only actually does anything during unit tests
|
||||
#ifdef UNIT_TESTS
|
||||
#define TEST_ONLY_ASSERT(test, explanation) if(!(test)) {CRASH(explanation)}
|
||||
#else
|
||||
#define TEST_ONLY_ASSERT(test, explanation)
|
||||
#endif
|
||||
@@ -45,14 +45,14 @@ SUBSYSTEM_DEF(overlays)
|
||||
build_overlays -= overlay
|
||||
continue
|
||||
if (istext(overlay))
|
||||
#ifdef UNIT_TESTS
|
||||
// This is too expensive to run normally but running it during CI is a good test
|
||||
var/list/icon_states_available = icon_states(icon)
|
||||
if(!(overlay in icon_states_available))
|
||||
var/icon_file = "[icon]" || "Unknown Generated Icon"
|
||||
stack_trace("Invalid overlay: Icon object '[icon_file]' [REF(icon)] used in '[src]' [type] is missing icon state [overlay].")
|
||||
continue
|
||||
#endif
|
||||
if (PERFORM_ALL_TESTS(focus_only/invalid_overlays))
|
||||
var/list/icon_states_available = icon_states(icon)
|
||||
if(!(overlay in icon_states_available))
|
||||
var/icon_file = "[icon]" || "Unknown Generated Icon"
|
||||
stack_trace("Invalid overlay: Icon object '[icon_file]' [REF(icon)] used in '[src]' [type] is missing icon state [overlay].")
|
||||
continue
|
||||
|
||||
var/index = build_overlays.Find(overlay)
|
||||
build_overlays[index] = iconstate2appearance(icon, overlay)
|
||||
else if(isicon(overlay))
|
||||
|
||||
+4
-6
@@ -259,16 +259,14 @@
|
||||
update_light()
|
||||
|
||||
if (length(smoothing_groups))
|
||||
#ifdef UNIT_TESTS
|
||||
assert_sorted(smoothing_groups, "[type].smoothing_groups")
|
||||
#endif
|
||||
if (PERFORM_ALL_TESTS(focus_only/sorted_smoothing_groups))
|
||||
assert_sorted(smoothing_groups, "[type].smoothing_groups")
|
||||
|
||||
SET_BITFLAG_LIST(smoothing_groups)
|
||||
|
||||
if (length(canSmoothWith))
|
||||
#ifdef UNIT_TESTS
|
||||
assert_sorted(canSmoothWith, "[type].canSmoothWith")
|
||||
#endif
|
||||
if (PERFORM_ALL_TESTS(focus_only/sorted_smoothing_groups))
|
||||
assert_sorted(canSmoothWith, "[type].canSmoothWith")
|
||||
|
||||
if(canSmoothWith[length(canSmoothWith)] > MAX_S_TURF) //If the last element is higher than the maximum turf-only value, then it must scan turf contents for smoothing targets.
|
||||
smoothing_flags |= SMOOTH_OBJ
|
||||
|
||||
@@ -134,15 +134,13 @@ GLOBAL_LIST_EMPTY(station_turfs)
|
||||
levelupdate()
|
||||
|
||||
if (length(smoothing_groups))
|
||||
#ifdef UNIT_TESTS
|
||||
assert_sorted(smoothing_groups, "[type].smoothing_groups")
|
||||
#endif
|
||||
if (PERFORM_ALL_TESTS(focus_only/sorted_smoothing_groups))
|
||||
assert_sorted(smoothing_groups, "[type].smoothing_groups")
|
||||
|
||||
SET_BITFLAG_LIST(smoothing_groups)
|
||||
if (length(canSmoothWith))
|
||||
#ifdef UNIT_TESTS
|
||||
assert_sorted(canSmoothWith, "[type].canSmoothWith")
|
||||
#endif
|
||||
if (PERFORM_ALL_TESTS(focus_only/sorted_smoothing_groups))
|
||||
assert_sorted(canSmoothWith, "[type].canSmoothWith")
|
||||
|
||||
if(canSmoothWith[length(canSmoothWith)] > MAX_S_TURF) //If the last element is higher than the maximum turf-only value, then it must scan turf contents for smoothing targets.
|
||||
smoothing_flags |= SMOOTH_OBJ
|
||||
|
||||
@@ -13,11 +13,10 @@
|
||||
if(initial(D.research_icon) && initial(D.research_icon_state)) //If the design has an icon replacement skip the rest
|
||||
icon_file = initial(D.research_icon)
|
||||
icon_state = initial(D.research_icon_state)
|
||||
#ifdef UNIT_TESTS
|
||||
if(!(icon_state in icon_states(icon_file)))
|
||||
stack_trace("design [D] with icon '[icon_file]' missing state '[icon_state]'")
|
||||
continue
|
||||
#endif
|
||||
if (PERFORM_ALL_TESTS(focus_only/invalid_research_designs))
|
||||
if(!(icon_state in icon_states(icon_file)))
|
||||
stack_trace("design [D] with icon '[icon_file]' missing state '[icon_state]'")
|
||||
continue
|
||||
I = icon(icon_file, icon_state, SOUTH)
|
||||
|
||||
else
|
||||
@@ -46,11 +45,10 @@
|
||||
icon_file = initial(item.icon)
|
||||
|
||||
icon_state = initial(item.icon_state)
|
||||
#ifdef UNIT_TESTS
|
||||
if(!(icon_state in icon_states(icon_file)))
|
||||
stack_trace("design [D] with icon '[icon_file]' missing state '[icon_state]'")
|
||||
continue
|
||||
#endif
|
||||
if (PERFORM_ALL_TESTS(focus_only/invalid_research_designs))
|
||||
if(!(icon_state in icon_states(icon_file)))
|
||||
stack_trace("design [D] with icon '[icon_file]' missing state '[icon_state]'")
|
||||
continue
|
||||
I = icon(icon_file, icon_state, SOUTH)
|
||||
|
||||
// computers (and snowflakes) get their screen and keyboard sprites
|
||||
|
||||
@@ -14,19 +14,18 @@
|
||||
icon_file = initial(item.icon)
|
||||
var/icon_state = initial(item.icon_state)
|
||||
|
||||
#ifdef UNIT_TESTS
|
||||
var/icon_states_list = icon_states(icon_file)
|
||||
if (!(icon_state in icon_states_list))
|
||||
var/icon_states_string
|
||||
for (var/an_icon_state in icon_states_list)
|
||||
if (!icon_states_string)
|
||||
icon_states_string = "[json_encode(an_icon_state)]([text_ref(an_icon_state)])"
|
||||
else
|
||||
icon_states_string += ", [json_encode(an_icon_state)]([text_ref(an_icon_state)])"
|
||||
if (PERFORM_ALL_TESTS(focus_only/invalid_vending_machine_icon_states))
|
||||
var/icon_states_list = icon_states(icon_file)
|
||||
if (!(icon_state in icon_states_list))
|
||||
var/icon_states_string
|
||||
for (var/an_icon_state in icon_states_list)
|
||||
if (!icon_states_string)
|
||||
icon_states_string = "[json_encode(an_icon_state)]([text_ref(an_icon_state)])"
|
||||
else
|
||||
icon_states_string += ", [json_encode(an_icon_state)]([text_ref(an_icon_state)])"
|
||||
|
||||
stack_trace("[item] does not have a valid icon state, icon=[icon_file], icon_state=[json_encode(icon_state)]([text_ref(icon_state)]), icon_states=[icon_states_string]")
|
||||
continue
|
||||
#endif
|
||||
stack_trace("[item] does not have a valid icon state, icon=[icon_file], icon_state=[json_encode(icon_state)]([text_ref(icon_state)]), icon_states=[icon_states_string]")
|
||||
continue
|
||||
|
||||
var/icon/I = icon(icon_file, icon_state, SOUTH)
|
||||
var/c = initial(item.color)
|
||||
|
||||
@@ -105,6 +105,7 @@
|
||||
#include "dynamic_ruleset_sanity.dm"
|
||||
#include "egg_glands.dm"
|
||||
#include "emoting.dm"
|
||||
#include "focus_only_tests.dm"
|
||||
#include "food_edibility_check.dm"
|
||||
#include "gas_transfer.dm"
|
||||
#include "get_turf_pixel.dm"
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
/// These tests perform no behavior of their own, and have their tests offloaded onto other procs.
|
||||
/// This is useful in cases like in build_appearance_list where we want to know if any fail,
|
||||
/// but is not useful to right a test for.
|
||||
/// This file exists so that you can change any of these to TEST_FOCUS and only check for that test.
|
||||
/// For example, change /datum/unit_test/focus_only/invalid_overlays to TEST_FOCUS(/datum/unit_test/focus_only/invalid_overlays),
|
||||
/// and you will only test the check for invalid overlays in appearance building.
|
||||
/datum/unit_test/focus_only
|
||||
|
||||
/// Checks that every overlay passed into build_appearance_list exists in the icon
|
||||
/datum/unit_test/focus_only/invalid_overlays
|
||||
|
||||
/// Checks that every icon sent to the research_designs spritesheet is valid
|
||||
/datum/unit_test/focus_only/invalid_research_designs
|
||||
|
||||
/// Checks that every icon sent to vending machines is valid
|
||||
/datum/unit_test/focus_only/invalid_vending_machine_icon_states
|
||||
|
||||
/// Checks that smoothing_groups and canSmoothWith are properly sorted in /atom/Initialize
|
||||
/datum/unit_test/focus_only/sorted_smoothing_groups
|
||||
@@ -17,6 +17,16 @@ GLOBAL_VAR(test_log)
|
||||
/// When unit testing, all logs sent to log_mapping are stored here and retrieved in log_mapping unit test.
|
||||
GLOBAL_LIST_EMPTY(unit_test_mapping_logs)
|
||||
|
||||
/// The name of the test that is currently focused.
|
||||
/// Use the PERFORM_ALL_TESTS macro instead.
|
||||
GLOBAL_VAR_INIT(focused_test, focused_test())
|
||||
|
||||
/proc/focused_test()
|
||||
for (var/datum/unit_test/unit_test as anything in subtypesof(/datum/unit_test))
|
||||
if (initial(unit_test.focus))
|
||||
return unit_test
|
||||
return null
|
||||
|
||||
/datum/unit_test
|
||||
//Bit of metadata for the future maybe
|
||||
var/list/procs_tested
|
||||
@@ -125,6 +135,9 @@ GLOBAL_LIST_EMPTY(unit_test_mapping_logs)
|
||||
log_world("::[priority] file=[file],line=[line],title=[map_name]: [type]::[annotation_text]")
|
||||
|
||||
/proc/RunUnitTest(test_path, list/test_results)
|
||||
if (ispath(test_path, /datum/unit_test/focus_only))
|
||||
return
|
||||
|
||||
var/datum/unit_test/test = new test_path
|
||||
|
||||
GLOB.current_test = test
|
||||
|
||||
@@ -205,6 +205,7 @@
|
||||
#include "code\__DEFINES\turbine_defines.dm"
|
||||
#include "code\__DEFINES\turfs.dm"
|
||||
#include "code\__DEFINES\typeids.dm"
|
||||
#include "code\__DEFINES\unit_tests.dm"
|
||||
#include "code\__DEFINES\uplink.dm"
|
||||
#include "code\__DEFINES\vehicles.dm"
|
||||
#include "code\__DEFINES\verb_manager.dm"
|
||||
|
||||
Reference in New Issue
Block a user