Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix randomly failing tests #4064

Merged
merged 5 commits into from
Jan 24, 2024
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 Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ COPY src src
COPY assets assets

# check that the code is formatted
# RUN mix format --check-formatted
RUN mix format --check-formatted

# compile assets
RUN cd assets && npm install
Expand Down
2 changes: 1 addition & 1 deletion config/test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ config :sanbase, Sanbase.PresignedS3Url.S3,
# Print only warnings and errors during test. Do not log JSON in tests.
config :logger, :console,
format: "$time $metadata[$level] $message\n",
level: :warn
level: :warning

config :sanbase, Sanbase.RepoReader, projects_data_endpoint_secret: "no_secret"

Expand Down
39 changes: 23 additions & 16 deletions lib/mix/failure_test_formatter.ex
Original file line number Diff line number Diff line change
Expand Up @@ -7,29 +7,30 @@ defmodule Sanbase.FailedTestFormatter do
def init(_opts) do
{:ok,
%{
failed: [],
failure_counter: 0
:error => %{list: [], counter: 0},
:invalid => %{list: [], counter: 0}
}}
end

def handle_cast({:test_finished, %ExUnit.Test{state: {:failed, _}} = test}, config) do
config =
case test do
%ExUnit.Test{state: {:failed, [{:error, _error, failures}]}} = test
when is_list(failures) ->
%ExUnit.Test{state: {:failed, [{kind, _error, _stacktrace}]}} = test
when kind in [:error, :invalid] ->
# Add a leading dot so the file:line string can be copy-pasted in the
# terminal to directly execute it
file = String.replace_leading(test.tags.file, File.cwd!() <> "/", "")
line = test.tags.line
test_identifier = "#{file}:#{line}"

%{
config
| failed: ["#{file}:#{line}" | config.failed],
failure_counter: config.failure_counter + 1
}
config
|> Map.update(kind, %{counter: 1, list: [test_identifier]}, fn map ->
map |> Map.update!(:counter, &(&1 + 1)) |> Map.update!(:list, &[test_identifier | &1])
end)

_ ->
IO.warn("Unexpected failed test format.")
# TODO: Support ExUnit.MultiError
test ->
IO.warn("Unexpected failed test format. Got: #{inspect(test)}")
config
end

Expand All @@ -46,13 +47,19 @@ defmodule Sanbase.FailedTestFormatter do
end

defp print_suite(config) do
if config.failure_counter > 0 do
message = config.failed |> Enum.map(&(" " <> &1)) |> Enum.join("\n")
for kind <- Map.keys(config) do
if (get_in(config, [kind, :counter]) || 0) > 0 do
# All tests that failed an assert will have `kind = :error`
error_tests_message =
get_in(config, [kind, :list]) |> Enum.map(&(" " <> &1)) |> Enum.join("\n")

formatted_message =
IO.ANSI.red() <> "\n\nFailed tests:\n" <> message <> "\n" <> IO.ANSI.reset()
formatted_message =
IO.ANSI.red() <>
"\n\n#{String.capitalize(to_string(kind))} tests:\n" <>
error_tests_message <> "\n" <> IO.ANSI.reset()

IO.puts(formatted_message)
IO.puts(formatted_message)
end
end
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ defmodule Sanbase.Graphql.ApiMetricSocialMetricsTimeframeRestrictionTest do
end

test "cannot access historical data for social metrics", context do
{from, to} = from_to(5 * 365, 2 * 365)
{from, to} = from_to(5 * 365 - 1, 2 * 365)
slug = context.project.slug
metric = Enum.random(context.metrics)
interval = "1d"
Expand All @@ -70,7 +70,7 @@ defmodule Sanbase.Graphql.ApiMetricSocialMetricsTimeframeRestrictionTest do
end

test "can access realtime data for social metrics", context do
{from, to} = from_to(2, 0)
{from, to} = from_to(3, 0)
slug = context.project.slug
metric = Enum.random(context.metrics)
interval = "5m"
Expand All @@ -82,7 +82,7 @@ defmodule Sanbase.Graphql.ApiMetricSocialMetricsTimeframeRestrictionTest do
end

test "can access historical data for social metrics", context do
{from, to} = from_to(5 * 365, 2 * 365)
{from, to} = from_to(5 * 365 - 2, 2 * 365)
slug = context.project.slug
metric = Enum.random(context.metrics)
interval = "1d"
Expand Down