Skip to content

Commit afc6071

Browse files
Run tests using java-test-runner (exercism#2559)
* ci: run tests using java-test-runner * Store test output * Fix script to handle exercises with multiple solution files * Sync example files in practice exercises config * Fix script to handle example-only files * Only store artifacts on job failure * Fix compilation error in mazy-mice * Pin Ubuntu version in workflows * Pin actions/upload-artifact to SHA
1 parent 261a3f7 commit afc6071

15 files changed

Lines changed: 177 additions & 74 deletions

File tree

.github/workflows/gradle.yml

Lines changed: 6 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
name: Java CI with Gradle
1+
name: Gradle
22

33
on:
44
pull_request:
@@ -13,38 +13,25 @@ defaults:
1313

1414
jobs:
1515
build:
16-
runs-on: ubuntu-latest
17-
16+
runs-on: ubuntu-22.04
1817
steps:
1918
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11
2019
- name: Set up JDK 1.17
2120
uses: actions/setup-java@0ab4596768b603586c0de567f2430c30f5b0d2b0
2221
with:
2322
java-version: 17
2423
distribution: "temurin"
25-
- name: Grant execute permission for gradlew
26-
run: chmod +x gradlew
2724
- name: Check if tests compile cleanly with starter sources
2825
run: ./gradlew compileStarterTestJava --continue
29-
- name: Run checkstyle
30-
run: ./gradlew check --exclude-task test --continue
31-
32-
test:
33-
runs-on: ubuntu-latest
3426

27+
lint:
28+
runs-on: ubuntu-22.04
3529
steps:
3630
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11
3731
- name: Set up JDK 1.17
3832
uses: actions/setup-java@0ab4596768b603586c0de567f2430c30f5b0d2b0
3933
with:
4034
java-version: 17
4135
distribution: "temurin"
42-
- name: Grant execute permission for gradlew
43-
run: chmod +x gradlew
44-
- name: Test all reference implementations with Gradle
45-
run: ./gradlew test --continue
46-
- name: Create test summary
47-
uses: test-summary/action@62bc5c68de2a6a0d02039763b8c754569df99e3f
48-
with:
49-
paths: "**/build/test-results/test/*.xml"
50-
if: always()
36+
- name: Run checkstyle
37+
run: ./gradlew check --exclude-task test --continue

.github/workflows/test.yml

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
name: Test
2+
3+
on:
4+
pull_request:
5+
push:
6+
branches:
7+
- main
8+
workflow_dispatch:
9+
10+
jobs:
11+
test:
12+
runs-on: ubuntu-22.04
13+
steps:
14+
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11
15+
- name: Test all exercises using java-test-runner
16+
run: bin/test-with-test-runner
17+
- name: Archive test results
18+
uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32
19+
with:
20+
name: test-results
21+
path: exercises/**/build/results.json
22+
if: failure()

bin/test-with-test-runner

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
#!/usr/bin/env bash
2+
3+
# Test if the example/exemplar solution of each
4+
# Practice/Concept Exercise passes the exercise's tests.
5+
6+
# Example:
7+
# ./bin/test-with-test-runner
8+
9+
set -eo pipefail
10+
11+
docker pull exercism/java-test-runner
12+
13+
exit_code=0
14+
15+
function run_test_runner() {
16+
local slug=$1
17+
local solution_dir=$2
18+
local output_dir=$3
19+
20+
docker run \
21+
--rm \
22+
--network none \
23+
--mount type=bind,src="${solution_dir}",dst=/solution \
24+
--mount type=bind,src="${output_dir}",dst=/output \
25+
--tmpfs /tmp:rw \
26+
exercism/java-test-runner "${slug}" "/solution" "/output"
27+
}
28+
29+
function verify_exercise() {
30+
local dir=$(realpath $1)
31+
local slug=$(basename "${dir}")
32+
local output_dir="${dir}/build"
33+
local implementation_file_key=$2
34+
local implementation_files=($(jq -r --arg d "${dir}" --arg k "${implementation_file_key}" '$d + "/" + .files[$k][]' "${dir}/.meta/config.json"))
35+
local stub_files=($(jq -r --arg d "${dir}" '$d + "/" + .files.solution[]' "${dir}/.meta/config.json"))
36+
local results_file="${output_dir}/results.json"
37+
38+
mkdir -p "${output_dir}"
39+
40+
for stub_file in "${stub_files[@]}"; do
41+
cp "${stub_file}" "${stub_file}.bak"
42+
done
43+
44+
for impl_file in "${implementation_files[@]}"; do
45+
cp "${impl_file}" "${dir}/src/main/java/$(basename ${impl_file})"
46+
done
47+
48+
run_test_runner "${slug}" "${dir}" "${output_dir}"
49+
50+
if [[ $(jq -r '.status' "${results_file}") != "pass" ]]; then
51+
echo "${slug}: ${implementation_file_key} solution did not pass the tests"
52+
exit_code=1
53+
fi
54+
55+
for impl_file in "${implementation_files[@]}"; do
56+
rm "${dir}/src/main/java/$(basename ${impl_file})"
57+
done
58+
59+
for stub_file in "${stub_files[@]}"; do
60+
mv "${stub_file}.bak" "${stub_file}"
61+
done
62+
}
63+
64+
# Verify the Concept Exercises
65+
for concept_exercise_dir in ./exercises/concept/*/; do
66+
if [ -d $concept_exercise_dir ]; then
67+
echo "Checking $(basename "${concept_exercise_dir}") exercise..."
68+
verify_exercise $concept_exercise_dir "exemplar"
69+
fi
70+
done
71+
72+
# Verify the Practice Exercises
73+
for practice_exercise_dir in ./exercises/practice/*/; do
74+
if [ -d $practice_exercise_dir ]; then
75+
echo "Checking $(basename "${practice_exercise_dir}") exercise..."
76+
verify_exercise $practice_exercise_dir "example"
77+
fi
78+
done
79+
80+
exit ${exit_code}

exercises/practice/bowling/.meta/config.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@
2626
"src/test/java/BowlingGameTest.java"
2727
],
2828
"example": [
29-
".meta/src/reference/java/BowlingGame.java"
29+
".meta/src/reference/java/BowlingGame.java",
30+
".meta/src/reference/java/Frame.java"
3031
],
3132
"invalidator": [
3233
"build.gradle"

exercises/practice/error-handling/.meta/config.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,9 @@
2424
"src/test/java/ErrorHandlingTest.java"
2525
],
2626
"example": [
27-
".meta/src/reference/java/ErrorHandling.java"
27+
".meta/src/reference/java/ErrorHandling.java",
28+
".meta/src/reference/java/CustomCheckedException.java",
29+
".meta/src/reference/java/CustomUncheckedException.java"
2830
],
2931
"invalidator": [
3032
"build.gradle"

exercises/practice/forth/.meta/config.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@
2424
"src/test/java/ForthEvaluatorTest.java"
2525
],
2626
"example": [
27-
".meta/src/reference/java/ForthEvaluator.java"
27+
".meta/src/reference/java/ForthEvaluator.java",
28+
".meta/src/reference/java/Token.java"
2829
],
2930
"invalidator": [
3031
"build.gradle"

exercises/practice/hangman/.meta/config.json

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,17 @@
99
],
1010
"files": {
1111
"solution": [
12-
"src/main/java/Hangman.java"
12+
"src/main/java/Hangman.java",
13+
"src/main/java/Output.java"
1314
],
1415
"test": [
1516
"src/test/java/HangmanTest.java"
1617
],
1718
"example": [
18-
".meta/src/reference/java/Hangman.java"
19+
".meta/src/reference/java/Hangman.java",
20+
".meta/src/reference/java/Output.java"
1921
],
2022
"editor": [
21-
"src/main/java/Output.java",
2223
"src/main/java/Part.java",
2324
"src/main/java/Status.java"
2425
],

exercises/practice/mazy-mice/.meta/src/reference/java/MazeGenerator.java

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -31,28 +31,6 @@ private void validateDimensions(int rows, int columns) {
3131
}
3232
}
3333

34-
enum Direction {
35-
NORTH(0, 1),
36-
EAST(1, 0),
37-
SOUTH(0, -1),
38-
WEST(-1, 0);
39-
private final int dx;
40-
private final int dy;
41-
42-
Direction(int dx, int dy) {
43-
this.dx = dx;
44-
this.dy = dy;
45-
}
46-
47-
public int dx() {
48-
return dx;
49-
}
50-
51-
public int dy() {
52-
return dy;
53-
}
54-
}
55-
5634
final class Grid {
5735
private final Dimensions dimensions;
5836
private final BitSet grid;
@@ -182,4 +160,26 @@ char symbol() {
182160
};
183161
}
184162
}
163+
164+
private enum Direction {
165+
NORTH(0, 1),
166+
EAST(1, 0),
167+
SOUTH(0, -1),
168+
WEST(-1, 0);
169+
private final int dx;
170+
private final int dy;
171+
172+
Direction(int dx, int dy) {
173+
this.dx = dx;
174+
this.dy = dy;
175+
}
176+
177+
public int dx() {
178+
return dx;
179+
}
180+
181+
public int dy() {
182+
return dy;
183+
}
184+
}
185185
}

exercises/practice/mazy-mice/src/test/java/MazeGeneratorTest.java

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -8,28 +8,6 @@
88
import static org.assertj.core.api.Assertions.assertThat;
99
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
1010

11-
enum Direction {
12-
NORTH(0, 1),
13-
EAST(1, 0),
14-
SOUTH(0, -1),
15-
WEST(-1, 0);
16-
private final int dx;
17-
private final int dy;
18-
19-
Direction(int dx, int dy) {
20-
this.dx = dx;
21-
this.dy = dy;
22-
}
23-
24-
public int dx() {
25-
return dx;
26-
}
27-
28-
public int dy() {
29-
return dy;
30-
}
31-
}
32-
3311
public class MazeGeneratorTest {
3412
private static final char EMPTY_CELL = ' ';
3513
private static final Set<Character> ALLOWED_SYMBOLS = Set.of(
@@ -243,4 +221,26 @@ private int countEntrances(char[][] maze) {
243221
}
244222
return entranceCount;
245223
}
224+
225+
private enum Direction {
226+
NORTH(0, 1),
227+
EAST(1, 0),
228+
SOUTH(0, -1),
229+
WEST(-1, 0);
230+
private final int dx;
231+
private final int dy;
232+
233+
Direction(int dx, int dy) {
234+
this.dx = dx;
235+
this.dy = dy;
236+
}
237+
238+
public int dx() {
239+
return dx;
240+
}
241+
242+
public int dy() {
243+
return dy;
244+
}
245+
}
246246
}

exercises/practice/ocr-numbers/.meta/config.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,8 @@
2828
"src/test/java/OpticalCharacterReaderTest.java"
2929
],
3030
"example": [
31-
".meta/src/reference/java/OpticalCharacterReader.java"
31+
".meta/src/reference/java/OpticalCharacterReader.java",
32+
".meta/src/reference/java/Digit.java"
3233
],
3334
"invalidator": [
3435
"build.gradle"

0 commit comments

Comments
 (0)