Skip to content

Commit

Permalink
Mix.Tasks.Test: use refactored functions from ExUnit.Filters
Browse files Browse the repository at this point in the history
  • Loading branch information
azizk committed Oct 1, 2023
1 parent e427a0c commit 04da97e
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 46 deletions.
53 changes: 36 additions & 17 deletions lib/ex_unit/lib/ex_unit/filters.ex
Original file line number Diff line number Diff line change
Expand Up @@ -14,27 +14,43 @@ defmodule ExUnit.Filters do
on the command line) includes a line number filter, and if so returns the
appropriate ExUnit configuration options.
"""
@spec parse_path(String.t()) :: {String.t(), Keyword.t()}
def parse_path(file) do
case extract_locations(file) do
{path, []} -> {path, []}
{path, locations} -> {path, exclude: [:test], include: locations}
@spec parse_path(String.t()) :: {String.t(), [pos_integer]}
def parse_path(file_path) do
{[parsed_path], exunit_opts} = parse_paths([file_path])
{parsed_path, exunit_opts}
end

@doc "Like `parse_path/1` but for multiple paths. ExUnit filter options are combined."
@spec parse_paths([String.t()]) :: {[String.t()], Keyword.t()}
def parse_paths(file_paths) do
Enum.reduce(file_paths, {[], []}, fn file_path, {parsed_paths, includes} ->
{parsed_path, lines} = extract_line_numbers(file_path)
includes = Enum.reduce(lines, includes, &[{:location, {parsed_path, &1}} | &2])
{[parsed_path | parsed_paths], includes}
end)
|> case do
{parsed_paths, []} ->
{parsed_paths, []}

{parsed_paths, includes} ->
{parsed_paths, exclude: [:test], include: Enum.reverse(includes)}
end
end

defp extract_locations(file) do
case String.split(file, ":") do
[part] ->
{part, []}
defp extract_line_numbers(file_path) do
case String.split(file_path, ":") do
[path] ->
{path, []}

[path | parts] ->
{path_parts, line_numbers} = Enum.split_while(parts, &(not valid_line_number?(&1)))

# Stitch back path parts that are not valid integer line numbers.
path = Enum.join([path | path_parts], ":")

locations = for n <- line_numbers, valid_line_number(n), do: {:location, {path, n}}
lines = Enum.filter(line_numbers, &valid_line_number/1)

{path, locations}
{path, lines}
end
end

Expand Down Expand Up @@ -186,15 +202,14 @@ defmodule ExUnit.Filters do
end
end

defp has_tag(
{:location, {_file, line}},
%{line: _, describe_line: describe_line} = tags,
collection
) do
defp has_tag({:location, {file, line}}, %{line: _, describe_line: _} = tags, collection) do
line = to_integer(line)

cond do
describe_line == line ->
file && not String.ends_with?(tags.file, file) ->
false

tags.describe_line == line ->
true

describe_block?(line, collection) ->
Expand All @@ -205,6 +220,10 @@ defmodule ExUnit.Filters do
end
end

defp has_tag({:line, line}, %{line: _, describe_line: _} = tags, collection) do
has_tag({:location, {nil, line}}, tags, collection)
end

defp has_tag(pair, tags, _collection) do
has_tag(pair, tags)
end
Expand Down
25 changes: 7 additions & 18 deletions lib/mix/lib/mix/tasks/test.ex
Original file line number Diff line number Diff line change
Expand Up @@ -555,7 +555,7 @@ defmodule Mix.Tasks.Test do

# Finally parse, require and load the files
test_elixirc_options = project[:test_elixirc_options] || []
test_files = parse_files(files, shell, test_paths)
test_files = parse_file_paths(files, test_paths)
test_pattern = project[:test_pattern] || "*_test.exs"
warn_test_pattern = project[:warn_test_pattern] || "*_test.ex"

Expand Down Expand Up @@ -692,30 +692,19 @@ defmodule Mix.Tasks.Test do
[autorun: false] ++ opts
end

defp parse_files([], _shell, test_paths) do
defp parse_file_paths([], test_paths) do
test_paths
end

defp parse_files([single_file], _shell, _test_paths) do
# Check if the single file path matches test/path/to_test.exs:123. If it does,
# apply "--only line:123" and trim the trailing :123 part.
{single_file, opts} = ExUnit.Filters.parse_path(single_file)
defp parse_file_paths(file_paths, _test_paths) do
{parsed_file_paths, opts} = ExUnit.Filters.parse_paths(file_paths)
ExUnit.configure(opts)
[single_file]
end

defp parse_files(files, shell, _test_paths) do
if Enum.any?(files, &match?({_, [_ | _]}, ExUnit.Filters.parse_path(&1))) do
raise_with_shell(shell, "Line numbers can only be used when running a single test file")
else
files
end
parsed_file_paths
end

defp parse_filters(opts, key) do
if Keyword.has_key?(opts, key) do
ExUnit.Filters.parse(Keyword.get_values(opts, key))
end
values = Keyword.get_values(opts, key)
if values != [], do: ExUnit.Filters.parse(values)
end

defp filter_opts(opts, :only) do
Expand Down
22 changes: 11 additions & 11 deletions lib/mix/test/mix/tasks/test_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -438,17 +438,17 @@ defmodule Mix.Tasks.TestTest do
end)
end

test "raises an exception if line numbers are given with multiple files" do
in_fixture("test_stale", fn ->
assert_run_output(
[
"test/a_test_stale.exs",
"test/b_test_stale.exs:4"
],
"Line numbers can only be used when running a single test file"
)
end)
end
# test "raises an exception if line numbers are given with multiple files" do
# in_fixture("test_stale", fn ->
# assert_run_output(
# [
# "test/a_test_stale.exs",
# "test/b_test_stale.exs:4"
# ],
# "Line numbers can only be used when running a single test file"
# )
# end)
# end

test "umbrella with file path" do
in_fixture("umbrella_test", fn ->
Expand Down

0 comments on commit 04da97e

Please sign in to comment.