diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 000000000..7d04f1a71 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,23 @@ +name: Test + +on: + push: + branches: [main] + pull_request: + workflow_dispatch: + +jobs: + ci: + runs-on: ubuntu-20.04 + + steps: + - name: Checkout repository + uses: actions/checkout@v2 + + - uses: erlef/setup-beam@v1.13.0 + with: + otp-version: "23.2" + gleam-version: "0.24.0" + + - name: Run tests for all exercises + run: bin/test diff --git a/bin/test b/bin/test new file mode 100755 index 000000000..c3f834015 --- /dev/null +++ b/bin/test @@ -0,0 +1,66 @@ +#!/usr/bin/env bash + +set -euo pipefail + +# Synopsis: +# Test the track's exercises. +# +# At a minimum, this file must check if the example/exemplar solution of each +# Practice/Concept Exercise passes the exercise's tests. +# +# To check this, you usually have to (temporarily) replace the exercise's solution files +# with its exemplar/example files. +# +# If your track uses skipped tests, make sure to (temporarily) enable these tests +# before running the tests. +# +# The path to the solution/example/exemplar files can be found in the exercise's +# .meta/config.json file, or possibly inferred from the exercise's directory name. + +# Example: +# ./bin/test + +exit_code=0 + +function verify_exercise { + local dir slug implementation_file stub_backup_file module + dir=$(realpath "$1") + slug=$(basename "${dir}") + module=${slug//-/_} + implementation_file="${dir}/.meta/example.gleam" + stub_file="${dir}/src/${module}.gleam" + stub_backup_file="${stub_file}.bak" + + cp "${stub_file}" "${stub_backup_file}" + cp "${implementation_file}" "${stub_file}" + + if ! (cd "$dir" && gleam test) + then + echo "${slug}: proof solution did not pass the tests" + exit_code=1 + fi + + mv "${stub_backup_file}" "${stub_file}" +} + +# Verify the Concept Exercises +for concept_exercise_dir in ./exercises/concept/*/ +do + if [ -d "$concept_exercise_dir" ] + then + echo "Checking $(basename "${concept_exercise_dir}") concept exercise..." + verify_exercise "${concept_exercise_dir}" + fi +done + +# Verify the Practice Exercises +for practice_exercise_dir in ./exercises/practice/*/ +do + if [ -d "$practice_exercise_dir" ] + then + echo "Checking $(basename "${practice_exercise_dir}") practice exercise..." + verify_exercise "${practice_exercise_dir}" + fi +done + +exit ${exit_code} diff --git a/exercises/practice/bowling/.meta/example.gleam b/exercises/practice/bowling/.meta/example.gleam index 003276a74..59a492b31 100644 --- a/exercises/practice/bowling/.meta/example.gleam +++ b/exercises/practice/bowling/.meta/example.gleam @@ -1,5 +1,4 @@ import gleam/list -import gleam/bool import gleam/result pub opaque type Frame { @@ -26,7 +25,7 @@ fn is_frame_rolls_valid(frame: Frame) -> Bool { } fn is_frame_open(frame: Frame) -> Bool { - list.length(frame.rolls) == 2 && frame.rolls(score_rolls) < 10 + list.length(frame.rolls) == 2 && score_rolls(frame.rolls) < 10 } fn is_frame_strike(frame: Frame) -> Bool { diff --git a/exercises/practice/forth/.meta/example.gleam b/exercises/practice/forth/.meta/example.gleam index 0bd4bc810..998f4b69d 100644 --- a/exercises/practice/forth/.meta/example.gleam +++ b/exercises/practice/forth/.meta/example.gleam @@ -1,9 +1,6 @@ -import gleam/result -import gleam/io import gleam/int import gleam/map import gleam/order -import gleam/bool import gleam/list import gleam/string import gleam/string_builder diff --git a/exercises/practice/forth/src/forth.gleam b/exercises/practice/forth/src/forth.gleam index 3bb213805..428008bd4 100644 --- a/exercises/practice/forth/src/forth.gleam +++ b/exercises/practice/forth/src/forth.gleam @@ -1,5 +1,3 @@ -import gleam/result - pub type Forth { Forth } diff --git a/exercises/practice/forth/test/forth_test.gleam b/exercises/practice/forth/test/forth_test.gleam index b9f95763f..a1ce77d01 100644 --- a/exercises/practice/forth/test/forth_test.gleam +++ b/exercises/practice/forth/test/forth_test.gleam @@ -1,7 +1,5 @@ import forth import gleam/result -import gleam/list -import gleam/io import gleeunit import gleeunit/should diff --git a/exercises/practice/freelancer-rates/.meta/example.gleam b/exercises/practice/freelancer-rates/.meta/example.gleam index 195e8a28f..9d3e43cf0 100644 --- a/exercises/practice/freelancer-rates/.meta/example.gleam +++ b/exercises/practice/freelancer-rates/.meta/example.gleam @@ -7,15 +7,20 @@ pub fn daily_rate(hourly_rate: Int) -> Float { pub fn apply_discount(before_discount: Int, discount: Float) -> Float { let float_discount = int.to_float(before_discount) - float_discount -. {float_discount *. {discount /. 100.0}} + float_discount -. float_discount *. { discount /. 100.0 } } pub fn monthly_rate(hourly_rate: Int, discount: Float) -> Int { let before_discount = float.round(daily_rate(hourly_rate) *. 22.0) - let after_discount = apply_discount(before_discount, discount) - float.truncate(float.ceiling(after_discount)) + let after_discount = apply_discount(before_discount, discount) + float.truncate(float.ceiling(after_discount)) } pub fn days_in_budget(budget: Int, hourly_rate: Int, discount: Float) -> Float { - float.floor( int.to_float(budget) /. apply_discount(float.round(daily_rate(hourly_rate)), discount)) -} \ No newline at end of file + float.floor( + int.to_float(budget) /. apply_discount( + float.round(daily_rate(hourly_rate)), + discount, + ), + ) +}