Skip to content

Commit 210dc4c

Browse files
authored
Merge pull request #54 from exercism/remove-jq-dep-from-local-test-runner
Remove jq dep from local test runner
2 parents f74a497 + f92f11e commit 210dc4c

14 files changed

Lines changed: 78 additions & 47 deletions

File tree

Dockerfile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,6 @@ RUN wget https://github.com/godotengine/godot/releases/download/4.4.1-stable/God
1212
mv Godot_v4.4.1-stable_linux.x86_64 /usr/bin/godot && \
1313
rm Godot_v4.4.1-stable_linux.x86_64.zip
1414

15-
WORKDIR /opt/test-runner
15+
WORKDIR /opt/exercism/gdscript/test-runner
1616
COPY . .
17-
ENTRYPOINT ["/opt/test-runner/bin/run.sh"]
17+
ENTRYPOINT ["/opt/exercism/gdscript/test-runner/bin/run.sh"]

bin/run-tests-in-docker.sh

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,9 @@ docker run \
2323
--rm \
2424
--network none \
2525
--read-only \
26-
--mount type=bind,src="${PWD}/tests",dst=/opt/test-runner/tests \
26+
--mount type=bind,src="${PWD}/tests",dst=/opt/exercism/gdscript/test-runner/tests \
2727
--mount type=tmpfs,dst=/tmp \
28-
--volume "${PWD}/bin/run-tests.sh:/opt/test-runner/bin/run-tests.sh" \
29-
--workdir /opt/test-runner \
30-
--entrypoint /opt/test-runner/bin/run-tests.sh \
28+
--volume "${PWD}/bin/run-tests.sh:/opt/exercism/gdscript/test-runner/bin/run-tests.sh" \
29+
--workdir /opt/exercism/gdscript/test-runner \
30+
--entrypoint /opt/exercism/gdscript/test-runner/bin/run-tests.sh \
3131
exercism/test-runner

bin/run.sh

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,15 @@ mkdir -p "$XDG_CONFIG_HOME" "$XDG_DATA_HOME" "$XDG_CACHE_HOME"
3838

3939
echo "${slug}: testing..."
4040

41+
# Switch to where the script lives in case called from elsewhere
42+
OLD_DIR=$(pwd)
43+
SCRIPT_DIR=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)
44+
cd "$SCRIPT_DIR" || exit 1
45+
4146
# Run the tests for the provided implementation file
42-
godot --headless -s bin/test_runner.gd 2>/tmp/stderr -- "${slug}" "${solution_dir}" "${output_dir}"
47+
godot --headless -s ./test_runner.gd 2>/tmp/stderr -- "${slug}" "${solution_dir}" "${output_dir}"
48+
49+
# Switch back to calling dir
50+
cd "$OLD_DIR" || exit 1
4351

4452
echo "${slug}: done"

bin/test-local-gdscript-solution.sh

Lines changed: 9 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -12,38 +12,25 @@ missing_gd_msg="Normally, the exercise subdirectory created by the exercism down
1212
general_help_msg="Please see https://exercism.org/docs/tracks/gdscript/installation for details."
1313
if [ ! -f "${slug//-/_}_test.gd" ]; then
1414
echo "Missing test file: ${slug//-/_}_test.gd"
15-
echo $missing_gd_msg
16-
echo $general_help_msg
15+
echo "$missing_gd_msg"
16+
echo "$general_help_msg"
1717
exit 1
1818
fi
1919
if [ ! -f "${slug//-/_}.gd" ]; then
2020
echo "Missing solution file: ${slug//-/_}.gd"
21-
echo $missing_gd_msg
22-
echo $general_help_msg
21+
echo "$missing_gd_msg"
22+
echo "$general_help_msg"
2323
exit 1
2424
fi
25-
if [ ! -f "/opt/exercism/gdscript/test-runner/bin/run.sh" ]; then
26-
echo "Missing test runner file: /opt/exercism/gdscript/test-runner/bin/run.sh"
27-
echo $general_help_msg
25+
if [ ! -f "/opt/exercism/gdscript/test-runner/bin/test_runner.gd" ]; then
26+
echo "Missing test runner file: /opt/exercism/gdscript/test-runner/bin/test_runner.gd"
27+
echo "$general_help_msg"
2828
exit 1
2929
fi
3030

3131
solution_dir="$(pwd)"
32-
output_dir="${solution_dir}/.test-output"
33-
results_file="${output_dir}/results.json"
34-
mkdir -p "${output_dir}"
3532

36-
(cd /opt/exercism/gdscript/test-runner && bin/run.sh "$slug" "$solution_dir" "$output_dir") || {
33+
(cd /opt/exercism/gdscript/test-runner && godot --headless -s bin/test_runner.gd -- "$slug" "$solution_dir") || {
3734
echo "Test runner script failed."
3835
exit 1
39-
}
40-
41-
test_status="$(jq -r '.status' "${results_file}")"
42-
if [ "$test_status" != "pass" ]; then
43-
echo "Tests for $slug have failed:"
44-
cat "${results_file}"
45-
exit 1
46-
else
47-
echo
48-
echo "Tests for $slug passed!"
49-
fi
36+
}

bin/test_runner.gd

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -63,21 +63,26 @@ func parse_args() -> Error:
6363
global variables, based on the given args:
6464
* `solution_script_path`
6565
* `test_suite_script_path`
66-
* `output_dir_path`
66+
* `output_dir_path` (optional for local test runner, required for standard JSON test runner behaviour)
6767
"""
6868
var args = OS.get_cmdline_user_args()
6969

70-
if len(args) != 3:
70+
# This script still conforms to [1] but allows 2 arguments for a local test
71+
# runner with non-JSON output to eliminate dependence on 'jq'
72+
#
73+
# [1] https://github.com/exercism/docs/blob/main/building/tooling/test-runners/interface.md#execution
74+
if len(args) not in [2,3]:
7175
push_error(
72-
"The scrips needs exactly 3 arguments, was called with %s: %s" % [
76+
"The script needs exactly 2 or exactly 3 arguments, was called with %s: %s" % [
7377
len(args), str(args)
7478
]
7579
)
7680
return ERR_INVALID_PARAMETER
7781

7882
var slug = args[0]
7983
var solution_dir_path = args[1]
80-
output_dir_path = args[2]
84+
if len(args) == 3:
85+
output_dir_path = args[2]
8186

8287
# Test folders use dashes, but test files use underscores
8388
var gdscript_path = solution_dir_path.path_join(slug.replace("-", "_"))
@@ -127,7 +132,7 @@ func load_solution_script() -> Error:
127132
"message": "The solution file could not be parsed.",
128133
"tests": [],
129134
}
130-
file_utils.write_results_file(results, output_dir_path)
135+
file_utils.output_results(results, output_dir_path)
131136
return ERR_PARSE_ERROR
132137

133138
return OK
@@ -170,4 +175,4 @@ func run_tests() -> void:
170175
results["status"] = "fail"
171176
break
172177

173-
file_utils.write_results_file(results, output_dir_path)
178+
file_utils.output_results(results, output_dir_path)

bin/utils/file_utils.gd

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,37 @@ func load_script(script_path: String) -> Object:
8989
return script
9090

9191

92+
func output_results(results: Dictionary, output_dir_path: String) -> Error:
93+
"""
94+
If output_dir_path is empty, outputs friendly-formatted test results to
95+
stdout.
96+
97+
Otherwise, writes JSON results to results.json in the given path.
98+
"""
99+
if output_dir_path == "":
100+
return print_friendly_results(results)
101+
else:
102+
return write_results_file(results, output_dir_path)
103+
104+
105+
func print_friendly_results(results: Dictionary) -> Error:
106+
"""
107+
Prints rich results to stdout.
108+
"""
109+
var rich_results = [""]
110+
if results.status == "pass":
111+
rich_results.push_back("[color=yellow]Exercise passed! Nicely done![/color]")
112+
else:
113+
rich_results.push_back("Exercise has at least one failed test:")
114+
for test in results.tests:
115+
if test.status == "pass":
116+
rich_results.push_back(" %s [color=yellow]passed ✔[/color]" % test.name)
117+
else:
118+
rich_results.push_back(" %s [color=pink]failed: %s[/color]" % [test.name, test.message])
119+
print_rich("\n".join(rich_results))
120+
return OK
121+
122+
92123
func write_results_file(results: Dictionary, output_dir_path: String) -> Error:
93124
"""
94125
Saves a dictionary as a `results.json` file in the output directory. The file

tests/example-empty-file/expected_results.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,12 @@
55
{
66
"name": "test_add_1_and_2",
77
"status": "error",
8-
"message": "SCRIPT ERROR: Invalid call. Nonexistent function 'add_2_numbers' in base 'RefCounted (example_empty_file.gd)'.\n at: test_add_1_and_2 (res://tests/example-empty-file/example_empty_file_test.gd:2)\n"
8+
"message": "SCRIPT ERROR: Invalid call. Nonexistent function 'add_2_numbers' in base 'RefCounted (example_empty_file.gd)'.\n at: test_add_1_and_2 (/opt/exercism/gdscript/test-runner/tests/example-empty-file/example_empty_file_test.gd:2)\n"
99
},
1010
{
1111
"name": "test_add_10_and_20",
1212
"status": "error",
13-
"message": "SCRIPT ERROR: Invalid call. Nonexistent function 'add_2_numbers' in base 'RefCounted (example_empty_file.gd)'.\n at: test_add_10_and_20 (res://tests/example-empty-file/example_empty_file_test.gd:6)\n"
13+
"message": "SCRIPT ERROR: Invalid call. Nonexistent function 'add_2_numbers' in base 'RefCounted (example_empty_file.gd)'.\n at: test_add_10_and_20 (/opt/exercism/gdscript/test-runner/tests/example-empty-file/example_empty_file_test.gd:6)\n"
1414
}
1515
]
1616
}

tests/example-execution-error/expected_results.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
{
1111
"name": "test_0",
1212
"status": "error",
13-
"message": "SCRIPT ERROR: Division by zero error in operator '/'.\n at: divide (res://tests/example-execution-error/example_execution_error.gd:2)\n"
13+
"message": "SCRIPT ERROR: Division by zero error in operator '/'.\n at: divide (/opt/exercism/gdscript/test-runner/tests/example-execution-error/example_execution_error.gd:2)\n"
1414
}
1515
]
1616
}

tests/example-incorrect-number-of-arguments/expected_results.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,12 @@
55
{
66
"name": "test_too_few_args",
77
"status": "error",
8-
"message": "SCRIPT ERROR: Invalid call to function 'add_numbers' in base 'RefCounted (example_incorrect_number_of_arguments.gd)'. Expected 2 arguments.\n at: test_too_few_args (res://tests/example-incorrect-number-of-arguments/example_incorrect_number_of_arguments_test.gd:2)\n"
8+
"message": "SCRIPT ERROR: Invalid call to function 'add_numbers' in base 'RefCounted (example_incorrect_number_of_arguments.gd)'. Expected 2 arguments.\n at: test_too_few_args (/opt/exercism/gdscript/test-runner/tests/example-incorrect-number-of-arguments/example_incorrect_number_of_arguments_test.gd:2)\n"
99
},
1010
{
1111
"name": "test_too_many_args",
1212
"status": "error",
13-
"message": "SCRIPT ERROR: Invalid call to function 'add_numbers' in base 'RefCounted (example_incorrect_number_of_arguments.gd)'. Expected 2 arguments.\n at: test_too_many_args (res://tests/example-incorrect-number-of-arguments/example_incorrect_number_of_arguments_test.gd:6)\n"
13+
"message": "SCRIPT ERROR: Invalid call to function 'add_numbers' in base 'RefCounted (example_incorrect_number_of_arguments.gd)'. Expected 2 arguments.\n at: test_too_many_args (/opt/exercism/gdscript/test-runner/tests/example-incorrect-number-of-arguments/example_incorrect_number_of_arguments_test.gd:6)\n"
1414
}
1515
]
1616
}

tests/example-invalid-argument-type/expected_results.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
{
1616
"name": "test_integer",
1717
"status": "error",
18-
"message": "SCRIPT ERROR: Invalid call. Nonexistent function 'ends_with' in base 'int'.\n at: check_something (res://tests/example-invalid-argument-type/example_invalid_argument_type.gd:3)\n"
18+
"message": "SCRIPT ERROR: Invalid call. Nonexistent function 'ends_with' in base 'int'.\n at: check_something (/opt/exercism/gdscript/test-runner/tests/example-invalid-argument-type/example_invalid_argument_type.gd:3)\n"
1919
}
2020
]
2121
}

0 commit comments

Comments
 (0)