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

(mix test) add test_load_filters and test_warn_filters #14036

Merged
merged 9 commits into from
Dec 29, 2024

Conversation

SteffenDE
Copy link
Contributor

@SteffenDE SteffenDE commented Dec 7, 2024

Edit: This is the old suggestion, but I kept it for posterity. For the updated description, please scroll down :)

This is an alternative to #14034, which only traverses the file system once.

When using the default project configuration, mix test would only warn about files ending in _test.ex. The only mistake this warns about is forgetting the s of .exs. In a work project we noticed (after more than a year) that we had multiple test files that did not match the test pattern, preventing them from running in mix test locally and CI. Because we have many other tests, nobody noticed this. If CI passes, all is good, right?

Because there is no easy way to evaluate glob patterns in Elixir without touching the filesystem, I decided to deprecate the old configurations and instead add two new configurations: test_load_pattern and test_warn_pattern. Now, we can load all potential test files once and then match their paths to the patterns.

The test_load_pattern is used to filter the files that are loaded by mix test. This defaults to the regex equivalent of "*_test.exs". The test_warn_pattern is used to filter the files that we warned about if they are not loaded. By default, we warn about any file that either ends in _test.ex (the old behavior) but also any file that ends in .exs, but does not end in _helper.exs, which will prevent the default test_helper.exs from generating a warning and also provides a way to name other files that might be required explicitly in tests. As an escape hatch the test_warn_ignore_files list can be used to ignore specific files where the warning should not be generated.

For projects with an existing test_pattern or warn_test_pattern configuration, a deprecation warning is logged. The new warnings can be disabled by setting test_warn_pattern to a falsy value.

@josevalim
Copy link
Member

What do you think about keeping test_pattern? By default it finds both .ex and .exs files. And then we reject the results of test_pattern.

It is a smaller breaking change and if someone has changed the test_pattern, then worst case scenario they don’t get a warning.

@SteffenDE
Copy link
Contributor Author

But if we keep test_pattern as glob pattern, we need to evaluate the pattern twice, don't we?

I really wish there was a built in glob pattern to regex or something...

@josevalim
Copy link
Member

test_pattern is the glob, the others are strings and regexes we run over the matched files

@SteffenDE SteffenDE force-pushed the sd-test-warn-pattern branch from 5e43b87 to a0df137 Compare December 8, 2024 13:31
@SteffenDE
Copy link
Contributor Author

Adjusted to use test_pattern with new default *.{ex,exs}. Existing projects with custom test_pattern might still run into conflicts with the new test_load_pattern.

@SteffenDE SteffenDE force-pushed the sd-test-warn-pattern branch from ff0cb54 to 09ebf2b Compare December 10, 2024 22:48
@SteffenDE SteffenDE changed the title (mix test) add test_load_pattern and test_warn_pattern (mix test) add test_load_filters and test_warn_filters Dec 10, 2024
@SteffenDE
Copy link
Contributor Author

Updated description (taken from the commit message):

(mix test) add test_load_filters and test_warn_filters

When using the default project configuration, mix test would only warn about files ending in _test.ex. The only mistake this warns about is forgetting the s of .exs. In a work project we noticed (after more than a year) that we had multiple test files that did not match the test pattern, preventing them from running in mix test locally and CI. Because we have many other tests, nobody noticed this. If CI passes, all is good, right?

Because there is no easy way to evaluate glob patterns in Elixir without touching the filesystem, I decided to deprecate the old warn_test_pattern configuration and instead add two new configurations:

test_load_filters and test_warn_filters

Now, by changing the default of test_pattern to *.{ex,exs}, we can load all potential test files once and then match their paths to the patterns.

The test_load_filters is used to filter the files that are loaded by mix test. This defaults to the regex equivalent of "*_test.exs". The test_warn_filters is used to filter the files that we warn about if they are not loaded. By default, we ignore any file ending in _helper.exs, which will prevent the default test_helper.exs from generating a warning and also provides a simple way to name other files that might be required explicitly in tests. We also default to ignore any files that start with a configured elixirc_path, which are compiled often test support files.

For projects with an existing warn_test_pattern configuration, a deprecation warning is logged. The warnings can be disabled by setting test_warn_filters to a falsy value.

Projects with an existing custom test_pattern should check if their pattern conflicts with the new test_load_filters and adjust their configuration accordingly. It is also possible to keep the old test_pattern and configure the test_load_filters to accept any file, for example by configuring it to [fn _ -> true end]. In that case, the test_warn_filters don't have an effect, as any potential test file is also loaded.

@mgibowski
Copy link
Contributor

I don't know how far you want to take the default pattern, just sharing my experience - it happened to me calling the test files ...text_exs.

@SteffenDE
Copy link
Contributor Author

@mgibowski no file extension at all? 😅

With the changes from the PR, you'd get a warning for foo_text_exs if you set the test_paths to **.

@mgibowski
Copy link
Contributor

@SteffenDE
oh, sorry - it was late when I wrote this message.
What I meant was ..._text.exs

@SteffenDE
Copy link
Contributor Author

@mgibowski that should warn with the new defaults :)

@SteffenDE SteffenDE force-pushed the sd-test-warn-pattern branch from 09ebf2b to 42e9086 Compare December 13, 2024 16:40
@SteffenDE SteffenDE force-pushed the sd-test-warn-pattern branch from 8e12c62 to 3d41609 Compare December 27, 2024 14:29
When using the default project configuration, mix test would only warn
about files ending in `_test.ex`. The only mistake this warns about is
forgetting the `s` of `.exs`. In a work project we noticed (after more
than a year) that we had multiple test files that did not match the test
pattern, preventing them from running in mix test locally and CI.
Because we have many other tests, nobody noticed this. If CI passes, all
is good, right?

Because there is no easy way to evaluate glob patterns in Elixir without
touching the filesystem, I decided to deprecate the old `warn_test_pattern`
configuration and instead add two new configurations:

`test_load_filters` and `test_warn_filters`

Now, by changing the default of `test_pattern` to `*.{ex,exs}`, we can
load all potential test files once and then match their paths to the
patterns.

The `test_load_filters` is used to filter the files that are loaded by
mix test. This defaults to the regex equivalent of "*_test.exs". The
`test_warn_filters` is used to filter the files that we warn about if
they are not loaded. By default, we ignore any file ending in `_helper.exs`,
which will prevent the default test_helper.exs from generating a warning
and also provides a simple way to name other files that might be required
explicitly in tests. We also default to ignore any files that start with
a configured elixirc_path, which are compiled often test support files.

For projects with an existing `warn_test_pattern` configuration,
a deprecation warning is logged. The warnings can be disabled by setting
`test_warn_filters` to a falsy value.

Projects with an existing custom `test_pattern` should check if their
pattern conflicts with the new `test_load_filters` and adjust their
configuration accordingly. It is also possible to keep the old `test_pattern`
and configure the `test_load_filters` to accept any file, for example by
configuring it to `[fn _ -> true end]`. In that case, the `test_warn_filters`
don't have an effect, as any potential test file is also loaded.
@SteffenDE SteffenDE force-pushed the sd-test-warn-pattern branch from 3d41609 to e6b21b5 Compare December 27, 2024 14:29
Keyword.get_lazy(project, :test_ignore_filters, fn ->
[
&String.ends_with?(&1, "_helper.exs"),
fn file -> Enum.any?(elixirc_paths, &String.starts_with?(file, &1)) end
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should include this filter by default, because if the user wants to add a new one, we should not ask them to reimplement this. WDYT? I am not sure if we should exclude the test_helper.exs by default too, but we probably should. So the user simply passes additional filters?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed! If anyone feels the need to change those defaults, they'll hopefully open up an issue :)

Copy link
Member

@josevalim josevalim left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added only nits now, we are good to go!

@josevalim josevalim merged commit a4cb71c into elixir-lang:main Dec 29, 2024
8 of 9 checks passed
@josevalim
Copy link
Member

💚 💙 💜 💛 ❤️

SteffenDE added a commit to phoenixframework/phoenix_live_view that referenced this pull request Dec 29, 2024
SteffenDE added a commit to phoenixframework/phoenix that referenced this pull request Dec 29, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

3 participants