Skip to content

Commit 47b1f52

Browse files
authored
Merge branch 'exercism:main' into add-installation
2 parents 107e961 + 3605b3f commit 47b1f52

File tree

12 files changed

+201
-108
lines changed

12 files changed

+201
-108
lines changed

.github/workflows/test.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,13 @@ on:
2323

2424
jobs:
2525
ci:
26-
runs-on: ubuntu-22.04
26+
runs-on: ubuntu-24.04
2727
container:
2828
image: exercism/gdscript-test-runner
2929

3030
steps:
3131
- name: Checkout repository
32-
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11
32+
uses: actions/checkout@09d2acae674a48949e3602304ab46fd20ae0c42f
3333

3434
- name: Verify all exercises
35-
run: bin/verify-exercises
35+
run: godot --headless -s bin/verify-exercises.gd

README.md

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,15 @@ Exercism exercises in GDScript.
66

77
## Testing
88

9-
To test the exercises, run `./bin/verify-exercises`.
9+
To set up for testing, clone https://github.com/exercism/gdscript-test-runner and move its contents to `/opt/exercism/gdscript/test-runner`:
10+
11+
```sh
12+
git clone https://github.com/exercism/gdscript-test-runner.git
13+
sudo mkdir -p /opt/exercism/gdscript/
14+
sudo mv gdscript-test-runner/ /opt/exercism/gdscript/test-runner/
15+
```
16+
17+
To test the exercises, run `godot --headless -s bin/verify-exercises.gd`.
1018
This command will iterate over all exercises and check to see if their exemplar/example implementation passes all the tests.
1119

1220
### Track linting

bin/verify-exercises

Lines changed: 0 additions & 41 deletions
This file was deleted.

bin/verify-exercises.gd

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
extends SceneTree
2+
3+
# godot --headless -s bin/verify-exercises.gd
4+
5+
func _init():
6+
# Calling `quit(1)` doesn't stop the program immediately, so a `return` is necessary.
7+
# That's why errors are checked directly in `_init()`, instead of calling `quit(1)`
8+
# in each method.
9+
var temp_dir_base = DirAccess.create_temp("gdscript-verify-exercises")
10+
if temp_dir_base == null:
11+
push_error("Failed to create base temporary directory: %s", DirAccess.get_open_error())
12+
quit(1)
13+
return
14+
var temp_dir_base_path = temp_dir_base.get_current_dir()
15+
16+
for exercise_base in [
17+
"exercises/practice",
18+
"exercises/concept"
19+
]:
20+
if run_tests(exercise_base, temp_dir_base_path) != OK:
21+
quit(1)
22+
return
23+
quit()
24+
25+
func run_tests(exercise_base: String, temp_dir_base_path: String) -> Error:
26+
for slug in DirAccess.get_directories_at(exercise_base):
27+
var result = run_test(slug, exercise_base + "/" + slug, temp_dir_base_path)
28+
if result != OK:
29+
return result
30+
return OK
31+
32+
33+
func run_test(slug: String, exercise_dir: String, temp_dir_base_path: String) -> Error:
34+
var temp_dir: String = temp_dir_base_path + "/" + slug
35+
DirAccess.make_dir_recursive_absolute(temp_dir)
36+
37+
var config_path = exercise_dir + "/.meta/config.json"
38+
var config_file = FileAccess.open(config_path, FileAccess.READ)
39+
if not config_file:
40+
push_error("Failed to read config: " + config_path)
41+
return DirAccess.get_open_error()
42+
43+
var json = JSON.new()
44+
var parse_return_value = json.parse(config_file.get_as_text())
45+
var config
46+
if parse_return_value == OK:
47+
config = json.data
48+
if typeof(config) != TYPE_DICTIONARY:
49+
push_error("Expected TYPE_DICTIONARY for JSON in: " + config_path)
50+
return ERR_UNCONFIGURED
51+
else:
52+
push_error("JSON Parse Error: ", json.get_error_message(), " in ", config_path, " at line ", json.get_error_line())
53+
return parse_return_value
54+
55+
var solution_name: String = config.get("files", {}).get("solution", [])[0]
56+
var test_path = exercise_dir + "/" + config.get("files", {}).get("test", [])[0]
57+
var example_path = exercise_dir + "/" + config.get("files", {}).get("example", [])[0]
58+
var dest_solution = temp_dir + "/" + solution_name
59+
60+
# Copy test and example files into temp dir
61+
DirAccess.copy_absolute(test_path, temp_dir + "/" + test_path.get_file())
62+
DirAccess.copy_absolute(example_path, dest_solution)
63+
64+
# Run external test script
65+
var args = [slug, temp_dir, temp_dir]
66+
var output = []
67+
var exit_code = OS.execute("/opt/exercism/gdscript/test-runner/bin/run.sh", args, output, true)
68+
if exit_code != 0:
69+
push_error("Test runner failed for ", slug, " with ", output)
70+
return ERR_SCRIPT_FAILED
71+
print(output[0])
72+
73+
# Check test result
74+
var results_path = temp_dir + "/results.json"
75+
if not FileAccess.file_exists(results_path):
76+
push_error("Missing results.json for ", slug, " at ", results_path)
77+
return ERR_FILE_NOT_FOUND
78+
var results_file = FileAccess.open(results_path, FileAccess.READ)
79+
parse_return_value = json.parse(results_file.get_as_text())
80+
var results
81+
if parse_return_value == OK:
82+
results = json.data
83+
if results.get("status") != "pass":
84+
push_error("Tests for ", slug, " have failed:")
85+
push_error(JSON.stringify(results, "\t"))
86+
return FAILED
87+
else:
88+
push_error("JSON Parse Error: ", json.get_error_message(), " in ", config_path, " at line ", json.get_error_line())
89+
return parse_return_value
90+
return OK

config.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@
9393
},
9494
{
9595
"slug": "triangle",
96-
"name": "triangle",
96+
"name": "Triangle",
9797
"uuid": "9762dd20-acef-4e3e-b304-8ae2a351d866",
9898
"practices": [],
9999
"prerequisites": [],
@@ -254,6 +254,8 @@
254254
"platform/mac",
255255
"platform/linux",
256256
"platform/android",
257+
"platform/ios",
258+
"platform/web",
257259
"used_for/games"
258260
]
259261
}

docs/ABOUT.md

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,13 @@
11
# About
22

3-
<!-- TODO: write document
3+
GDScript is a gradually typed, object-oriented, imperative scripting language created for (and is generally used only with) [Godot Engine][godot-engine], an open-source 2D and 3D game engine and IDE.
4+
As such, it's heavily optimized around Godot's scene-based architecture, and has native support for data types like
45

5-
This document contains a short introduction to the language.
6+
Since GDScript shares a number with popular languages (for example, its syntax resembles Python), learning GDScript can be a fun gateway to both Godot game programming and to learning other programming languages.
7+
If you're already interested in Godot and not sure which of its supported languages to learn, you might be interested to read [What is GDScript and why should I use it?][why-use-gdscript].
68

7-
The introduction should be relatively brief and touch upon what
8-
makes the language interesting (and possibly unique). The goal
9-
is to help students decide if they want to join this track.
9+
If you're curious why Godot created their own language, you can read more at [What were the motivations behind creating GDScript?][why-create-gdscript].
1010

11-
The contents of this document are displayed on the track page,
12-
provided the student has not joined the track.
13-
14-
See https://exercism.org/docs/building/tracks/docs for more information. -->
11+
[godot-engine]: https://godotengine.org/
12+
[why-use-gdscript]: https://docs.godotengine.org/en/stable/about/faq.html#what-is-gdscript-and-why-should-i-use-it
13+
[why-create-gdscript]: https://docs.godotengine.org/en/stable/about/faq.html#what-were-the-motivations-behind-creating-gdscript

docs/LEARNING.md

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
1-
# Learning
1+
# Learning GDScript
22

3-
<!-- TODO: write document
3+
## Websites
44

5-
This document should link to learning resources.
5+
* [GDScript.com][gdscript-dot-com]
6+
* [Learn to Code From Zero with Godot][code-from-zero]
67

7-
Feel free to link to any good learning resources you know, whether they
8-
be websites, blogs, books, videos or courses.
8+
## Courses
99

10-
The contents of this document are displayed on the track's documentation
11-
page at `https://exercism.org/docs/tracks/<track>/learning`.
10+
* [Learn GDScript on Udemy][udemy]
1211

13-
See https://exercism.org/docs/building/tracks/docs for more information. -->
12+
[gdscript-dot-com]: https://gdscript.com/
13+
[code-from-zero]: https://gdquest.github.io/learn-gdscript/
14+
[udemy]: https://www.udemy.com/course/learn-the-gdscript-programming-language/

docs/RESOURCES.md

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,20 @@
1-
# Resources
2-
* [Official Godot Homepage](https://godotengine.org/)
3-
* [Official Godot Documentation](https://docs.godotengine.org/en/stable/)
4-
* [Official Godot Q&A Platform](https://ask.godotengine.org/)
5-
* [Official Godot Discord](https://discord.com/invite/4JBkykG)
6-
* [r/godot on Reddit](https://www.reddit.com/r/godot/)
7-
* [Godot on Steam](https://steamcommunity.com/app/404790)
8-
* [Godot on itch.io](https://godotengine.itch.io/godot)
9-
* [Godot Forums](https://godotforums.org/)
1+
# Recommended Learning Resources
2+
3+
## Documentation
4+
5+
* [Official GDScript Reference][gdscript-ref]
6+
7+
## Communication Channels
8+
9+
* [GDScript Discussions on Official Godot Forum][official-forum]
10+
* [GDScript Discussions on (Unofficial) Godot Forums][unofficial-forums]
11+
* [StackOverflow questions tagged [gdscript]][stack-overflow] can be used to search for your problem and see if it has been answered already. You can also ask and answer questions.
12+
* [r/godot on Reddit][subreddit] is a subreddit where GDScript questions are relevant.
13+
* [Official Godot Discord][discord]
14+
15+
[gdscript-ref]: https://docs.godotengine.org/en/stable/tutorials/scripting/gdscript/index.html
16+
[official-forum]: https://forum.godotengine.org/tag/gdscript
17+
[unofficial-forums]: https://godotforums.org/t/gdscript
18+
[stack-overflow]: https://stackoverflow.com/questions/tagged/gdscript
19+
[subreddit]: https://www.reddit.com/r/godot/
20+
[discord]: https://discord.com/invite/4JBkykG

docs/TESTS.md

Lines changed: 33 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,40 @@
11
# Tests
22

3-
<!-- TODO: write document
3+
## Installing the Exercism GDScript track test runner
44

5-
This document should describe everything related to running tests in the track.
5+
You'll need [Godot installed][installation] correctly to use the test runner.
66

7-
If your track uses skipped tests, this document can explain why thet is used and
8-
how to unskip tests.
7+
To build and test GDScript scripts for Exercism, Godot will be run in "headless" mode from the CLI.
8+
These instructions currently require Linux and bash.
99

10-
This document can also link to the testing framework documentation.
10+
### Step 1: Installing the overall test runner infrastructure
1111

12-
The contents of this document are displayed on the track's documentation
13-
page at `https://exercism.org/docs/tracks/<track>/tests`.
12+
To set up for testing, clone [https://github.com/exercism/gdscript-test-runner][gdscript-test-runner] and move its contents to `/opt/exercism/gdscript/test-runner/`:
1413

15-
See https://exercism.org/docs/building/tracks/docs for more information. -->
14+
```sh
15+
git clone https://github.com/exercism/gdscript-test-runner.git
16+
sudo mkdir -p /opt/exercism/gdscript/
17+
sudo mv gdscript-test-runner/ /opt/exercism/gdscript/test-runner/
18+
```
19+
20+
### Step 2: Downloading the single-exercise test runner script
21+
22+
Assuming you have the `exercism` tool set up and have downloaded at least one GDScript exercise, it should have created an `exercism/gdscript` folder to house the exercises.
23+
Save [the test runner][test-local-gdscript-solution] in this folder and mark the file executable, or just create a link to it:
24+
25+
```sh
26+
cd ~/exercism/gdscript # replace with your exercism/gdscript directory
27+
ln /opt/exercism/gdscript/test-runner/bin/test-local-gdscript-solution.sh
28+
```
29+
30+
## Running tests
31+
32+
With the installation steps done, you should be able start from any exercise directory (e.g., `~/exercism/gdscript/two-fer`) and run the script (living one level up, in `../`) to test your local solution to that exercise:
33+
34+
```sh
35+
../test-local-gdscript-solution.sh
36+
```
37+
38+
[installation]: https://exercism.org/docs/tracks/gdscript/installation
39+
[gdscript-test-runner]: https://github.com/exercism/gdscript-test-runner
40+
[test-local-gdscript-solution]: https://raw.githubusercontent.com/exercism/gdscript-test-runner/refs/heads/main/bin/test-local-gdscript-solution.sh

exercises/practice/reverse-string/.meta/config.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
".meta/example.gd"
1414
]
1515
},
16-
"blurb": "Reverse a string.",
16+
"blurb": "Reverse a given string.",
1717
"source": "Introductory challenge to reverse an input string",
1818
"source_url": "https://medium.freecodecamp.org/how-to-reverse-a-string-in-javascript-in-3-different-ways-75e4763c68cb"
1919
}

0 commit comments

Comments
 (0)