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 more bugs in declarative specs filter #49141

Merged
merged 1 commit into from
Sep 7, 2023

Conversation

ghiculescu
Copy link
Member

ref: #47942

This PR fixes some things that were missed in first PR.

  1. Minitest::Spec doesn't extend Rails::LineFiltering, so compose_filter (and thus escape_declarative_test_filter) were not being called in the tests we added. This PR adds a new test case with Rails::LineFiltering included to confirm behaviour is the same either way.
  2. The filter in escape_declarative_test_filter didn't work on regexes that had passed through Regexp#escape. Now it supports that too.

@ghiculescu
Copy link
Member Author

Red tests are due to rails/globalid#168

filter = filter.gsub(/\s+/, '[\s_]+')
filter = filter.gsub("\\ ", '[\s_]+').gsub(/\s+/, '[\s_]+')
Copy link
Member

Choose a reason for hiding this comment

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

Is this fixing a bug, or is this just expanding the set of regexps we accept? If the latter, when is it necessary to write a filter like that?

I am hesitant to do any more transformations here. I can accept gsub(/\s+/, '[\s_]+') as a necessary evil, but manipulating regexps is very error prone. Consider the following:

Regexp.new("[\\ ]")
# => /[\ ]/

Regexp.new("[\\ ]".gsub("\\ ", '[\s_]+'))
# => /[[\s_]+]/

Regexp.new("[\\ ]".gsub("\\ ", '[\s_]+')).match?("+")
# => true


Regexp.new("\\\\ ")
# => /\\ /

Regexp.new("\\\\ ".gsub("\\ ", '[\s_]+'))
# warning: regular expression has ']' without escape: /\[\s_]+/
# => /\[\s_]+/

Regexp.new("\\\\ ".gsub("\\ ", '[\s_]+')).match?("[ _]")
# warning: regular expression has ']' without escape: /\[\s_]+/
# => true

Basically, we have to draw the line somewhere.

Copy link
Member Author

Choose a reason for hiding this comment

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

I do a lot of my test running using the m gem. The regex I'm testing here comes from there. Specifically from the Regexp#escape call on this line.

I realise it's not part of Rails so if the answer is we can't support it, I can try and find a way to support this in m. It just feels like it's something we should support since it's not like that gem is doing something really funky with the regex.

Copy link
Member

Choose a reason for hiding this comment

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

I've pushed a commit that I think solves the problem. Instead of wading through the weeds of regexps, we can simply join the original filter and the underscore-normalized filter.

Also, I discovered why the filter was being escaped over and over as you described in #47942 (comment): the same options instance is used for each call to Rails::LineFiltering#run, and we were modifying it in place each time. I've fixed that, so escape_declarative_test_filter (now renamed normalize_declarative_test_filter) no longer has to be idempotent.

Let me know what you think.

Copy link
Member Author

Choose a reason for hiding this comment

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

Instead of wading through the weeds of regexps, we can simply join the original filter and the underscore-normalized filter.

Damn. That's a great idea.

Copy link
Member Author

Choose a reason for hiding this comment

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

This approach looks great to me 💯

Thanks for your help!!

railties/test/application/test_runner_test.rb Outdated Show resolved Hide resolved
railties/test/application/test_runner_test.rb Outdated Show resolved Hide resolved
@@ -5,7 +5,7 @@
module Rails
module LineFiltering # :nodoc:
def run(reporter, options = {})
options[:filter] = Rails::TestUnit::Runner.compose_filter(self, options[:filter])
options = options.merge(filter: Rails::TestUnit::Runner.compose_filter(self, options[:filter]))
Copy link
Member Author

Choose a reason for hiding this comment

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

You could use options.merge! here @jonathanhefner

Copy link
Member

Choose a reason for hiding this comment

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

That would defeat the purpose. 😄 See #49141 (comment).

Copy link
Member Author

Choose a reason for hiding this comment

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

🤦 yep it would.

Follow-up to rails#47942.

This commit simplifies the normalization of regexp test filters.
Instead of modifying a given regexp to match a union of whitespace and
underscores, the regexp is unioned with the underscore-normalized
version of itself.  This allows filters that include escaped spaces,
such as `/foo\ bar/`.

This commit also fixes `Rails::LineFiltering#run` such that
normalization isn't reapplied for every test suite.  Thus
`normalize_declarative_test_filter` is no longer required to be
idempotent.

Co-authored-by: Jonathan Hefner <jonathan@hefner.pro>
@jonathanhefner jonathanhefner merged commit 4986cfb into rails:main Sep 7, 2023
4 checks passed
@jonathanhefner
Copy link
Member

Thank you, @ghiculescu! 👓

@ghiculescu ghiculescu deleted the declarative-specs-2 branch September 7, 2023 02:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants