Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/elixir_tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ jobs:
runs-on: ubuntu-24.04

container:
image: hexpm/elixir:1.18.1-erlang-27.2-debian-bookworm-20241223
image: hexpm/elixir:1.19.4-erlang-28.1-debian-bookworm-20251117

steps:
- name: Install git
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/exercism_test_helper_build_test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ jobs:
runs-on: ubuntu-24.04

container:
image: hexpm/elixir:1.18.1-erlang-27.2-debian-bookworm-20241223
image: hexpm/elixir:1.19.4-erlang-28.1-debian-bookworm-20251117

steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
Expand Down
4 changes: 2 additions & 2 deletions .tool-versions
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
elixir 1.18.1-otp-27
erlang 27.2
elixir 1.19.4-otp-28
erlang 28.1
4 changes: 2 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM hexpm/elixir:1.18.1-erlang-27.2-debian-bookworm-20241223 as builder
FROM hexpm/elixir:1.19.4-erlang-28.1-debian-bookworm-20251117 as builder

# Create appuser
RUN useradd -ms /bin/bash appuser
Expand All @@ -19,7 +19,7 @@ RUN mix local.rebar --force && \
RUN MIX_ENV=prod mix escript.build && \
mv exercism_test_helper /opt/test-runner/bin

FROM hexpm/elixir:1.18.1-erlang-27.2-debian-bookworm-20241223 as runner
FROM hexpm/elixir:1.19.4-erlang-28.1-debian-bookworm-20251117 as runner
COPY --from=builder /etc/passwd /etc/passwd
COPY --from=builder /opt/test-runner /opt/test-runner

Expand Down
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ Exercism Automated Test Runner for Elixir Exercises

## Environment

The test runner currently targets exercises supporting Elixir >= 1.14 and Erlang/OTP >= 25, but is running on Elixir 1.18.0 on hexpm's `elixir:1.18.1-erlang-27.2-debian-bookworm-20241223` image.
The test runner currently targets exercises supporting Elixir >= 1.15 and Erlang/OTP >= 26, but is running on Elixir 1.19.4 on hexpm's `elixir:1.19.4-erlang-28.1-debian-bookworm-20251117` image.

The `Dockerfile` also has added `bash`, `jo` and `jq` to the image.

Expand All @@ -19,6 +19,10 @@ The `Dockerfile` also has added `bash`, `jo` and `jq` to the image.

---

## Smoke tests

There is a gotcha in the smoke test setup: for the tests to work as expected locally, your **global** Elixir and Erlang versions must also be set to the same values as locally via `.tool-versions`.

## Contributing Guide

For an in-depth discussion of how exercism language tracks and exercises work, please see [CONTRIBUTING.md](https://github.com/exercism/elixir-test-runner/blob/master/CONTRIBUTING.md)
Expand Down
2 changes: 1 addition & 1 deletion elixir
Submodule elixir updated 188 files
16 changes: 10 additions & 6 deletions exercism_test_helper/lib/json_formatter.ex
Original file line number Diff line number Diff line change
Expand Up @@ -235,12 +235,7 @@ defmodule JSONFormatter do

# Colorize Utility Functions -- from ExUnit.CLIFormatter, but can't import d/t being private in source

defp colorize(escape, msg, config) when is_doc(msg) do
msg = Inspect.Algebra.format(msg, 2)
colorize(escape, msg, config)
end

defp colorize(escape, string, %{colors: colors}) do
defp colorize(escape, string, %{colors: colors}) when is_binary(string) do
if colors[:enabled] do
[escape, string, :reset]
|> IO.ANSI.format_fragment(true)
Expand All @@ -250,6 +245,15 @@ defmodule JSONFormatter do
end
end

defp colorize(escape, msg, config) when is_doc(msg) do
msg =
msg
|> Inspect.Algebra.format(2)
|> IO.iodata_to_binary()

colorize(escape, msg, config)
end

@doc """
Helper function to get the full path of the generated report file.
It can be passed 2 configurations via environment variable
Expand Down
2 changes: 1 addition & 1 deletion exercism_test_helper/lib/meta/style.ex
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ defmodule Meta.Style do
def format(ast) do
ast
|> Macro.to_string()
|> Code.format_string!([line_length: 120, force_do_end_blocks: true])
|> Code.format_string!(line_length: 120, force_do_end_blocks: true)
|> IO.iodata_to_binary()
end
end
2 changes: 1 addition & 1 deletion exercism_test_helper/mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ defmodule ExercismTestHelper.MixProject do
[
app: :exercism_test_helper,
version: "0.1.2",
elixir: "~> 1.18",
elixir: "~> 1.19",
start_permanent: Mix.env() == :prod,
deps: deps(),
escript: escript()
Expand Down
2 changes: 1 addition & 1 deletion test/community-garden/expected_results.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"message":null,"status":"fail","tests":[{"message":null,"name":"test start returns an alive pid","output":"","status":"pass","task_id":1,"test_code":"assert {:ok, pid} = CommunityGarden.start()\nassert Process.alive?(pid)"},{"message":" 1) test when started, the registry is empty (CommunityGardenTest)\n \u001b[1m\u001b[30mtest/community_garden_test.exs:11\u001b[0m\n \u001b[31mAssertion with == failed\u001b[0m\n \u001b[36mcode: \u001b[0massert [] == CommunityGarden.list_registrations(pid)\n \u001b[36mleft: \u001b[0m\u001b[31m[]\u001b[0m\n \u001b[36mright: \u001b[0m\u001b[32mnil\u001b[0m\n \u001b[36mstacktrace:\u001b[0m\n test/community_garden_test.exs:14: (test)\n","name":"test when started, the registry is empty","output":"","status":"fail","task_id":2,"test_code":"assert {:ok, pid} = CommunityGarden.start()\nassert [] == CommunityGarden.list_registrations(pid)"},{"message":" 2) test can register a new plot (CommunityGardenTest)\n \u001b[1m\u001b[30mtest/community_garden_test.exs:18\u001b[0m\n \u001b[31mmatch (=) failed\u001b[0m\n \u001b[36mcode: \u001b[0massert %Plot{} = CommunityGarden.register(pid, \"Johnny Appleseed\")\n \u001b[36mleft: \u001b[0m\u001b[31m%Plot{\n \n}\u001b[0m\n \u001b[36mright: \u001b[0m\u001b[32mnil\u001b[0m\n \u001b[36mstacktrace:\u001b[0m\n test/community_garden_test.exs:21: (test)\n","name":"test can register a new plot","output":"","status":"fail","task_id":3,"test_code":"assert {:ok, pid} = CommunityGarden.start()\nassert %Plot{} = CommunityGarden.register(pid, \"Johnny Appleseed\")"},{"message":" 3) test maintains a registry of plots (CommunityGardenTest)\n \u001b[1m\u001b[30mtest/community_garden_test.exs:25\u001b[0m\n \u001b[31mmatch (=) failed\u001b[0m\n \u001b[36mcode: \u001b[0massert %Plot{} = plot = CommunityGarden.register(pid, \"Johnny Appleseed\")\n \u001b[36mleft: \u001b[0m\u001b[31m%Plot{\n \n}\u001b[0m\n \u001b[36mright: \u001b[0m\u001b[32mnil\u001b[0m\n \u001b[36mstacktrace:\u001b[0m\n test/community_garden_test.exs:28: (test)\n","name":"test maintains a registry of plots","output":"","status":"fail","task_id":3,"test_code":"assert {:ok, pid} = CommunityGarden.start()\nassert %Plot{} = plot = CommunityGarden.register(pid, \"Johnny Appleseed\")\nassert [plot] == CommunityGarden.list_registrations(pid)"},{"message":" 4) test can release a plot (CommunityGardenTest)\n \u001b[1m\u001b[30mtest/community_garden_test.exs:33\u001b[0m\n \u001b[31mmatch (=) failed\u001b[0m\n \u001b[36mcode: \u001b[0massert %Plot{} = plot = CommunityGarden.register(pid, \"Johnny Appleseed\")\n \u001b[36mleft: \u001b[0m\u001b[31m%Plot{\n \n}\u001b[0m\n \u001b[36mright: \u001b[0m\u001b[32mnil\u001b[0m\n \u001b[36mstacktrace:\u001b[0m\n test/community_garden_test.exs:36: (test)\n","name":"test can release a plot","output":"","status":"fail","task_id":4,"test_code":"assert {:ok, pid} = CommunityGarden.start()\nassert %Plot{} = plot = CommunityGarden.register(pid, \"Johnny Appleseed\")\nassert :ok = CommunityGarden.release(pid, plot.plot_id)\nassert [] == CommunityGarden.list_registrations(pid)"},{"message":" 5) test can get registration of a registered plot (CommunityGardenTest)\n \u001b[1m\u001b[30mtest/community_garden_test.exs:42\u001b[0m\n \u001b[31mmatch (=) failed\u001b[0m\n \u001b[36mcode: \u001b[0massert %Plot{} = plot = CommunityGarden.register(pid, \"Johnny Appleseed\")\n \u001b[36mleft: \u001b[0m\u001b[31m%Plot{\n \n}\u001b[0m\n \u001b[36mright: \u001b[0m\u001b[32mnil\u001b[0m\n \u001b[36mstacktrace:\u001b[0m\n test/community_garden_test.exs:45: (test)\n","name":"test can get registration of a registered plot","output":"","status":"fail","task_id":5,"test_code":"assert {:ok, pid} = CommunityGarden.start()\nassert %Plot{} = plot = CommunityGarden.register(pid, \"Johnny Appleseed\")\nassert %Plot{} = registered_plot = CommunityGarden.get_registration(pid, plot.plot_id)\nassert registered_plot.plot_id == plot.plot_id\nassert registered_plot.registered_to == \"Johnny Appleseed\""},{"message":" 6) test return not_found when attempt to get registration of an unregistered plot (CommunityGardenTest)\n \u001b[1m\u001b[30mtest/community_garden_test.exs:52\u001b[0m\n \u001b[31mmatch (=) failed\u001b[0m\n \u001b[36mcode: \u001b[0massert {:not_found, \"plot is unregistered\"} = CommunityGarden.get_registration(pid, 1)\n \u001b[36mleft: \u001b[0m\u001b[31m{\n :not_found,\n \"plot is unregistered\"\n}\u001b[0m\n \u001b[36mright: \u001b[0m\u001b[32mnil\u001b[0m\n \u001b[36mstacktrace:\u001b[0m\n test/community_garden_test.exs:59: (test)\n","name":"test return not_found when attempt to get registration of an unregistered plot","output":"","status":"fail","task_id":5,"test_code":"assert {:ok, pid} = CommunityGarden.start()\nassert {:not_found, \"plot is unregistered\"} = CommunityGarden.get_registration(pid, 1)"}],"version":3}
{"message":null,"status":"fail","tests":[{"message":null,"name":"test start returns an alive pid","output":"","status":"pass","task_id":1,"test_code":"assert {:ok, pid} = CommunityGarden.start()\nassert Process.alive?(pid)"},{"message":" 1) test when started, the registry is empty (CommunityGardenTest)\n \u001B[1m\u001B[30mtest/community_garden_test.exs:11\u001B[0m\n \u001B[31mAssertion with == failed\u001B[0m\n \u001B[36mcode: \u001B[0massert [] == CommunityGarden.list_registrations(pid)\n \u001B[36mleft: \u001B[0m\u001B[31m[]\u001B[0m\n \u001B[36mright: \u001B[0m\u001B[32mnil\u001B[0m\n \u001B[36mstacktrace:\u001B[0m\n test/community_garden_test.exs:14: (test)\n","name":"test when started, the registry is empty","output":"","status":"fail","task_id":2,"test_code":"assert {:ok, pid} = CommunityGarden.start()\nassert [] == CommunityGarden.list_registrations(pid)"},{"message":" 2) test can register a new plot (CommunityGardenTest)\n \u001B[1m\u001B[30mtest/community_garden_test.exs:18\u001B[0m\n \u001B[31mmatch (=) failed\u001B[0m\n \u001B[36mcode: \u001B[0massert %Plot{} = CommunityGarden.register(pid, \"Johnny Appleseed\")\n \u001B[36mleft: \u001B[0m\u001B[31m%Plot{\n \n}\u001B[0m\n \u001B[36mright: \u001B[0m\u001B[32mnil\u001B[0m\n \u001B[36mstacktrace:\u001B[0m\n test/community_garden_test.exs:21: (test)\n","name":"test can register a new plot","output":"","status":"fail","task_id":3,"test_code":"assert {:ok, pid} = CommunityGarden.start()\nassert %Plot{} = CommunityGarden.register(pid, \"Johnny Appleseed\")"},{"message":" 3) test maintains a registry of plots (CommunityGardenTest)\n \u001B[1m\u001B[30mtest/community_garden_test.exs:25\u001B[0m\n \u001B[31mmatch (=) failed\u001B[0m\n \u001B[36mcode: \u001B[0massert %Plot{} = plot = CommunityGarden.register(pid, \"Johnny Appleseed\")\n \u001B[36mleft: \u001B[0m\u001B[31m%Plot{} = plot\u001B[0m\n \u001B[36mright: \u001B[0m\u001B[32mnil\u001B[0m\n \u001B[36mstacktrace:\u001B[0m\n test/community_garden_test.exs:28: (test)\n","name":"test maintains a registry of plots","output":"","status":"fail","task_id":3,"test_code":"assert {:ok, pid} = CommunityGarden.start()\nassert %Plot{} = plot = CommunityGarden.register(pid, \"Johnny Appleseed\")\nassert [plot] == CommunityGarden.list_registrations(pid)"},{"message":" 4) test can release a plot (CommunityGardenTest)\n \u001B[1m\u001B[30mtest/community_garden_test.exs:33\u001B[0m\n \u001B[31mmatch (=) failed\u001B[0m\n \u001B[36mcode: \u001B[0massert %Plot{} = plot = CommunityGarden.register(pid, \"Johnny Appleseed\")\n \u001B[36mleft: \u001B[0m\u001B[31m%Plot{} = plot\u001B[0m\n \u001B[36mright: \u001B[0m\u001B[32mnil\u001B[0m\n \u001B[36mstacktrace:\u001B[0m\n test/community_garden_test.exs:36: (test)\n","name":"test can release a plot","output":"","status":"fail","task_id":4,"test_code":"assert {:ok, pid} = CommunityGarden.start()\nassert %Plot{} = plot = CommunityGarden.register(pid, \"Johnny Appleseed\")\nassert :ok = CommunityGarden.release(pid, plot.plot_id)\nassert [] == CommunityGarden.list_registrations(pid)"},{"message":" 5) test can get registration of a registered plot (CommunityGardenTest)\n \u001B[1m\u001B[30mtest/community_garden_test.exs:42\u001B[0m\n \u001B[31mmatch (=) failed\u001B[0m\n \u001B[36mcode: \u001B[0massert %Plot{} = plot = CommunityGarden.register(pid, \"Johnny Appleseed\")\n \u001B[36mleft: \u001B[0m\u001B[31m%Plot{} = plot\u001B[0m\n \u001B[36mright: \u001B[0m\u001B[32mnil\u001B[0m\n \u001B[36mstacktrace:\u001B[0m\n test/community_garden_test.exs:45: (test)\n","name":"test can get registration of a registered plot","output":"","status":"fail","task_id":5,"test_code":"assert {:ok, pid} = CommunityGarden.start()\nassert %Plot{} = plot = CommunityGarden.register(pid, \"Johnny Appleseed\")\nassert %Plot{} = registered_plot = CommunityGarden.get_registration(pid, plot.plot_id)\nassert registered_plot.plot_id == plot.plot_id\nassert registered_plot.registered_to == \"Johnny Appleseed\""},{"message":" 6) test return not_found when attempt to get registration of an unregistered plot (CommunityGardenTest)\n \u001B[1m\u001B[30mtest/community_garden_test.exs:52\u001B[0m\n \u001B[31mmatch (=) failed\u001B[0m\n \u001B[36mcode: \u001B[0massert {:not_found, \"plot is unregistered\"} = CommunityGarden.get_registration(pid, 1)\n \u001B[36mleft: \u001B[0m\u001B[31m{\n :not_found,\n \"plot is unregistered\"\n}\u001B[0m\n \u001B[36mright: \u001B[0m\u001B[32mnil\u001B[0m\n \u001B[36mstacktrace:\u001B[0m\n test/community_garden_test.exs:59: (test)\n","name":"test return not_found when attempt to get registration of an unregistered plot","output":"","status":"fail","task_id":5,"test_code":"assert {:ok, pid} = CommunityGarden.start()\nassert {:not_found, \"plot is unregistered\"} = CommunityGarden.get_registration(pid, 1)"}],"version":3}