This would greatly reduce people using additional coverage reporters like 
excoveralls or similar as some tools (at least GitLab CI that I am using) 
allows to parse test output to fetch general coverage from there.

My proposal is to generate per module and total percentage from default 
coverage reporter. Example Coverage module that provides such result 
(additional there is additional option :threshold which colours resulting 
coverage red/green).

defmodule Cover do
  @moduledoc false

  @threshold 90

  def start(compile_path, opts) do
    Mix.shell().info("Cover compiling modules ...")
    _ = :cover.start()

    case :cover.compile_beam_directory(compile_path |> to_charlist) do
      results when is_list(results) ->
        :ok

      {:error, _} ->
        Mix.raise("Failed to cover compile directory: " <> compile_path)
    end

    output = opts[:output]

    fn ->
      File.mkdir_p!(output)

      Mix.shell().info("\nCover results")

      {:result, ok, _fail} = :cover.analyse(:coverage, :module)

      Mix.shell().info("Percentage | Module")
      Mix.shell().info("-----------|--------------------------")

      total =
        ok
        |> Stream.each(&display(&1, opts))
        |> Stream.each(&html(&1, output))
        |> Enum.reduce({0, 0}, fn {_, {cov, not_cov}}, {tot_cov, 
tot_not_cov} ->
          {tot_cov + cov, tot_not_cov + not_cov}
        end)

      Mix.shell().info("-----------|--------------------------")

      display({"Total", total}, opts)
    end
  end

  defp colour(percentage, threshold) when percentage > threshold, do: :green
  defp colour(_, _), do: :red

  defp display({name, coverage}, opts) do
    threshold = Keyword.get(opts, :threshold, @threshold)
    percentage = percentage(coverage)

    Mix.shell().info([
      colour(percentage, threshold),
      format(percentage, 9),
      "%",
      :reset,
      " | #{name}"
    ])
  end

  defp html({mod, _}, output) do
    {:ok, _} = :cover.analyse_to_file(mod, '#{output}/#{mod}.html', [:html])
  end

  defp percentage({0, 0}), do: 100
  defp percentage({cov, not_cov}), do: cov / (cov + not_cov) * 100

  defp format(num, len) when is_integer(num) do
    num
    |> Integer.to_string()
    |> String.pad_leading(len)
  end

  defp format(num, len) when is_float(num) do
    num
    |> Float.round(2)
    |> Float.to_string()
    |> String.pad_leading(len)
  end
end

-- 
You received this message because you are subscribed to the Google Groups 
"elixir-lang-core" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/elixir-lang-core/6ca4916a-8b3d-44c5-9df7-ba0467150a5a%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to