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

RSpec 4 plan #61

Open
31 of 53 tasks
pirj opened this issue Sep 4, 2020 · 37 comments
Open
31 of 53 tasks

RSpec 4 plan #61

pirj opened this issue Sep 4, 2020 · 37 comments
Assignees
Labels

Comments

@pirj
Copy link
Member

pirj commented Sep 4, 2020

It's been in the air and mostly in sparse @JonRowe's comments (1, 2). This is an attempt to gather the ideas and start the discussion.

Release step-by-step plan

pre-4.0:

4.0.0:

post-4.0

  • update RubyGems [new gem generator [1, 2]
  • update rspec-rails/rspec-collection_matchers/rspec-its to support RSpec 4
  • extract monkey-patching .should to a gem
  • kwargs delegation
  • [?] update transpec to facilitate migration from 3.x to 4.x (describe - > RSpec.describe?)
  • Cleanup: CI scripts
  • --no-document for gem
  • unindent/dedent -> <<~
  • rearrange gemfile/gemspec (runtime dependencies to gemspec, development - to gemfiles)
  • figure out why rubocop passes while there are offences in lib (core, probably others too)
  • set TargetRubyVersion for RuboCop, and bump to latest (that supports parsing 2.4, which even the edge should)
  • tighten and improve minimum_coverage
  • update rake, cucumber, aruba to latest versions (cucumber to 4.1 because 5.x depends on Ruby 2.5+, or even 3.x because of diff-lcs)

Ruby support

EOL Ruby means we support 2.5+, since 2.4 is EOL in April 2020
However, according to 2020 RoR community survey
image

70% use 2.5+
81% use 2.4+
89% use 2.3+

Do 2.3 and 2.4 cause any trouble? I could only find this:

        # 2.4 has improved BigDecimal formatting so we do not need
        # to provide our own.
        # https://github.com/ruby/bigdecimal/pull/42
        classes.delete(BigDecimalInspector) if RUBY_VERSION >= '2.4'

I can only think of RuboCop's TargetRubyVersion setting that has a minimum of 2.4. That means we won't be able to run rubocop on 2.3 CI build.

More on this in https://github.com/rspec/rspec/issues/25

Remove deprecated features/Introduce new defaults

Consider deprecating long-hanging/obscure features

  • [ ] DRb runner. I only know of Spork that was using it, but its 2.0.0-rc is years old now with no signs of life

Cleanup

  • rspec-core: "Ruby 1.9 has a bug that can lead to infinite recursion and a"
    Drafted in commits: ce2f4a0b 123e6ee7
    Drop Ruby < 2.3 support rspec-core#2787 (review)

    RSpec::Matchers.define(:be_one) do
      match { |actual| actual == 1 }
    end
    RSpec.describe do
      alias_method :b, :be_one
      it { expect(1).to be_one }
    end
  • for all repos

    • bump cucumber to ~> 5.2.0, cucumber-ruby (undefined method with_filtered_backtrace') + fix deprec titletoname`
      • 1.3-2.0 don't work for me locally with a weird error: undefined method []' for nil:NilClass (NoMethodError) /Users/pirj/.rvm/gems/ruby-2.7.1@rspec-core/gems/cucumber-1.3.20/lib/cucumber/core_ext/proc.rb:17:in file_colon_line'
      • 2.4.0 spits "undefined method `with_filtered_backtrace'"
      • 3.2.0 - "undefined method 'ok?'"
      • 4.1 depends on diff-lcs (< 1.4, >= 1.3, ~> 1.3), while we depend on = 1.4.4
      • 5.2.0 Found tags option '~@wip'. '~@tag' is no longer supported, use 'not @tag' instead
    • update diff-lcs ">= 1.4.4" (Stop using DiffHelpers rspec-support#477 and co)
    • update rake to latest
    • skip documentation
      yes | gem update --system --no-document
      yes | gem install bundler --no-document
      also on sub-builds?
    • rearrange Gemfile/gemspec
      e.g. core: simplecov, test-unit, aruba, rake
      To my best knowledge, add_development_dependency only affects local bundling. I've moved it over from the Gemfile.
      As far as I understand we can shuffle those dependencies between add_development_dependency and Gemfile without affecting anything.
      To me, it's better to keep those gems that we directly depend on here, while reserving the Gemfile to add version constraints for third-party dependencies like ffi and those that require a conditional, e.g.
      if RUBY_VERSION >= '2.4'
    • figure out why rubocop lib passes on core
      frozen string literal - run with --only Style/FrozenStringLiteralComment, why it doesn't detect offences without --only?
      lib/rspec/core/backport_random.rb excluded
    • <<- chomp gsub unindent dedent -> <<~
      • remove write_file_formatted in rspec-core

kwargs delegation

@JonRowe
Copy link
Member

JonRowe commented Sep 4, 2020

The main thing I want from RSpec 4 is dropping old Ruby support. My plan is for us to release with Ruby 3, which is slated for Christmas 2020, it will make it so much easier to support if we don't have to support non keyword argument Ruby.

@JonRowe
Copy link
Member

JonRowe commented Sep 4, 2020

Removing monkey patching mode (extracting it with .should to a 3rd party gem) would be an ideal goal within that.

Extra features can be added in point releases easily so anything thats ready can be shipped in 4 but I'm not going to gate them to hold out to make it "special".

@benoittgt
Copy link
Member

For the differ I didn't work on it that much. I am still following the work on @mcmire on https://github.com/mcmire/super_diff and I am wondering if telling to user that they can use super_diff easily or with rspec/rspec-expectations#1096 could be a good idea. 🤔

@pirj
Copy link
Member Author

pirj commented Dec 15, 2020

Updated the plan:

  • separated tasks for pre-4.0, 4.0 and 4.x
  • dumped my TODO

@benoittgt @JonRowe do you think we should fix kwargs delegation in 4.0, or can do it later? 3.0-preview2 passes just fine so far. ruby-head failure is for a different reason - they've fixed something and we have pending in a spec. Can e postpone kwargs delegation?
I'll focus on pre-4.0 and 4.0 tasks then.

@JonRowe
Copy link
Member

JonRowe commented Dec 15, 2020

Extract rarely used features (any_instance...,) to gems, keep bundled

This has to be in a major version

@pirj
Copy link
Member Author

pirj commented Dec 15, 2020

keep bundled

This has to be in a major version

Sorry, I obviously wasn't clear. By "keep bundled" I mean that if we happen to extract rspec-any_instance_of gem from rspec-mocks, rspec-mocks's gemspec will still include rspec-any_instance_of as a runtime dependency. This way nothing changes for the users.
This dependency is removed in a major version of rspec-mocks, strictly.
Those who would prefer to continue using any_instance_of (me included) can include them in their apps' Gemfile explicitly, just like rspec-its/rspec-collection_matchers.

Do you foresee any issues with this approach?

@benoittgt
Copy link
Member

@benoittgt @JonRowe do you think we should fix kwargs delegation in 4.0, or can do it later?

In kwargs delegation. Is this rspec/rspec-mocks#1306 included?
If yes, I think we should look at rspec/rspec-mocks#1306 not too late, but I am not sure this is a blocker for next release.

@pirj
Copy link
Member Author

pirj commented Dec 15, 2020

I've switched to the noisy 2.7.1 for everything, and have never seen this. 2.7.2 muted deprecation warnings. There are no build failures on 3.0 previews (apart from the missing warning on access to @undefined). Thoughts?

@pirj
Copy link
Member Author

pirj commented Dec 16, 2020

@JonRowe do you have a preference on how rspec-should (or whatever it will be called) is going to be plugged in?
I was thinking that if

RSpec.configure do |config|
  config.expect_with :rspec do |expectations|
    expectations.syntax = :should # or [:expect, :should]

is called, we make an attempt to require rspec-should/expectations, and it does the monkey patching. If require fails, we fail with a message suggesting to add rspec-should to the bundle. Is this a reasonable approach?

Should we consider syntax = :expect the default unless syntax = :should or syntax = [:expect, :should] is called, and syntax = :expect is not called?

The same applies to Mocks and its should_receive/... methods, but we attempt to require rspec-should/mocks.

I can take a stab at extracting it.

One (very minor) thing is the current non-additive behaviour of syntax=. So if there are two different spec helpers in the project, one of them is using :should, another - :expect, and one of those settings would override another.
But I guess it's a known gotcha, and projects that use different syntaxes for their different parts already account for that.

@myronmarston
Copy link
Member

@pirj take my suggestion with a grain of salt (since I'm no longer working on RSpec!) but one idea is to remove the syntax option entirely. Instead:

  • the core rspec gems would always define the expect syntax (with no config option to turn it off)
  • rspec-should gem (or whatever it's called) would automatically add the .should syntax if loaded
  • Optionally, the rspec-should gem could have an option to remove the expect syntax but I'm not sure if that's necessary. (If someone doesn't like it, they can just not use it).

In general, I think it's ideal for the core rspec gems to be blissfully unaware that rspec-should even exists and keeping the config option just adds complexity, IMO.

@JonRowe
Copy link
Member

JonRowe commented Dec 16, 2020

Myron's approach is basically what I was going to recommend. If people requested it we could probably add an opt in config for rspec-should to remove expect, but it'd be essentially an include that just removes the method / forces a raise for those that really want to enforce the old style and probably a stretch goal.

I'd have one gem rspec-should containing all of the syntax, and have it detect the relevant other gems when defining things.

@JonRowe
Copy link
Member

JonRowe commented Dec 16, 2020

I want to fix the keyword argument issues we have before releasing 4.0, with Ruby 3 coming up in ... 10 days? It's an essential item for me. The problem we have is lack of specs using them.

@JonRowe
Copy link
Member

JonRowe commented Dec 17, 2020

I also want to remove the monkey patching mode in 4.0.

It's worth noting we could (to get 4.0 out quickly) remove things and maintain 3.x whilst building the extracted gems?

@pirj
Copy link
Member Author

pirj commented Dec 23, 2020

@JonRowe How do you feel about (as the next chance might only be in a couple of years from now) of:

  1. Extracting AnyInstance from Mocks to a gem. Mocks README says:

It is the most complicated feature of rspec-mocks, and has historically received the most bug reports. (None of the core team actively use it, which doesn't help.)

  1. Dropping support for DRb from Core. I only know of Spork that was using it, but its 2.0.0-rc is ~7 years old now with no signs of life.

I can take care of those two.

@JonRowe
Copy link
Member

JonRowe commented Dec 23, 2020

I'd say yes except they needs to use public APIs to be extracted, that might be difficult?

@jfelchner
Copy link

@JonRowe I'd love to get a progress bar formatter included in RSpec 4 by default (ie Fuubar) I think that with with 10 years under its belt and 18.8 million downloads, it's proven itself a useful, general formatter rather than something bespoke.

I think it would be a net positive for RSpec, especially considering the increased awareness (eg in --help) would make people aware of an option they wanted, but didn't know existed.

I'm happy to continue supporting it but I'd love to get it into RSpec proper. The only thing it depends on is rspec-core (obviously) and my other gem ruby-progressbar (currently 12 years old) which itself has zero runtime dependencies.

Also open to opening a dedicated issue to this if you think it's warranted.

@JonRowe
Copy link
Member

JonRowe commented Dec 27, 2020

@jfelchner We are glad that Fuubar is part of the ecosystem for RSpec, and its a great example of how RSpec is extensible for such needs, but we are trying not to inflate RSpec too much, our goal is empower others to build things they want rather than offer them ourselves. (For the record 18.8 million downloads is fantastic, but its also at the time of writing around 3% of the downloads for rspec-core).

@jfelchner
Copy link

I think my point was more that, if it were a part of core, it would be used by far more people as I would argue it is a much more information-dense outputter than the current built-in versions. But I understand where you're coming from. :) Thanks for all the work you all do!

@pirj
Copy link
Member Author

pirj commented Dec 27, 2020

@jfelchner I was under the impression that we mention Fuubar in our configuration documentation, but I was wrong.
I suggest adding an Extensions just like minitest's section, adding a reference to Fuubar there. https://github.com/topics/rspec is a good source of finding extensions, and I suggest you add #rspec tag on Fuubar repository as well.
No doubt Fuubar deserves better exposure.

Side note:

It's a lesser-known feature, but RSpec is configurable with .rspec-local project file, and also ~/.config/rspec/options/~/.rspec. One can add --format fuubar there. With RVM global gemset and .rvm/hooks/after_install_global hook in theory it would be possible to install fuubar, but rspec command wouldn't be able to load it, even with --require fuubar in its config, because Bundler doesn't load gems from the global gemset automatically.

@jfelchner
Copy link

@pirj thank you so much!

@myronmarston
Copy link
Member

@JonRowe What should we do with include_chain_clauses_in_custom_matcher_descriptions?
[1]:

This option will default to true in RSpec 4

[2]:

It is false by default for backwards compatibility.

Is my understanding correct that we're keeping the option, just the default value for it is now true, and we don't explicitly set it to true in the project initializer?

You didn't ask me, but my two cents in case it's useful: I don't think there's any benefit to setting it to false. We just added the config option to avoid what could be considered a breaking change in 3.x. e.g. if someone had a library of matchers and had specs that asserted what the descriptions are, our change could have broken their specs--so we added the config option. IMO the config option should go away in 4.0 and the behavior true enables should be the only behavior.

(@JonRowe may disagree).

@JonRowe
Copy link
Member

JonRowe commented Jan 6, 2021

I agree (Thank you Myron for explaining better than I could until I've had ☕ 😂 )

@mvz
Copy link

mvz commented Feb 26, 2021

I can only think of RuboCop's TargetRubyVersion setting that has a minimum of 2.4. That means we won't be able to run rubocop on 2.3 CI build.

You'll also be fighting against RuboCop's understanding of what's valid syntax and its check for the Ruby version being set properly in the gemspec. Not insurmountable, but it means you can't rely on RuboCop to get those right.

Another thing: Dropping support for Ruby 2.3 would allow RSpec to start using Aruba 1.0 as well as some newer version of Cucumber for its Cucumber suites.

@JonRowe
Copy link
Member

JonRowe commented Feb 26, 2021

Another thing: Dropping support for Ruby 2.3 would allow RSpec to start using Aruba 1.0 as well as some newer version of Cucumber for its Cucumber suites

I'm curious whats in Aruba that wouldn't work on Ruby 2.3? As long as you're not using the esoteric syntax operators (which theres plain ruby alternatives for) 2.3 was the start of the "2.x" period of stability and I've never seen something break on 2.3 that works on 2.4 etc.

@mvz
Copy link

mvz commented Feb 26, 2021

I'm curious whats in Aruba that wouldn't work on Ruby 2.3?

Nothing, really, although by now there would probably be a few syntax issues. I basically drew the line at some point before the 1.0 release. Note that Cucumber 5.2.0, mentioned in the roadmap above, even requires Ruby 2.5.

@JonRowe
Copy link
Member

JonRowe commented Feb 26, 2021

Note that Cucumber 5.2.0, mentioned in the roadmap above, even requires Ruby 2.5.

Well that rules it out for us then. As a testing library we should support the highest amount of Rubyists we can. Dropping 30% to support 2.5+ is too many people left behind for my tastes.

@mvz
Copy link

mvz commented Feb 26, 2021

Dropping 30% to support 2.5+ is too many people left behind for my tastes.

I agree in principle, but since those numbers are from a Ruby-on-Rails survey, perhaps those people are already left behind by Rails, and hence already used to using old versions of their dependencies?

Perhaps something can be done to make the cucumber scenarios run with Aruba 1.0 + Cucumber 2, 3 or 4? That would allow supporting at least down to 2.4.

I'm not fundamentally against adding support for 2.3 back for Aruba, but that does have two practical downsides:

  • I can't easily get Ruby 2.3 installed locally so any bugs in that particular version would be hard to fix.
  • Latest RuboCop doesn't support 2.3 so I'd have to downgrade that dependency.

@pirj
Copy link
Member Author

pirj commented Feb 26, 2021

@mvz Thanks for bringing this up. I've added Aruba update to post-4.0 plan 👍

@myronmarston
Copy link
Member

Latest RuboCop doesn't support 2.3 so I'd have to downgrade that dependency.

Alternately, couldn't you just choose to not install and run rubocop on your 2.3 build?

@JonRowe
Copy link
Member

JonRowe commented Feb 26, 2021

Indeed, as Myron implies thats what we do, we only install and run Rubocop on supported platforms.

Potentially controversial suggestion, we could run Cucumber only on 2.5 or higher? Its main purpose is self executing documentation, so we could run it only on the newer Rubies...

@mvz
Copy link

mvz commented Feb 26, 2021

Alternately, couldn't you just choose to not install and run rubocop on your 2.3 build?

I could, but RuboCop will try to 'fix' things in a way that works with Ruby 2.4 and up. This means having to disable potentially useful cops, and more hand-holding when upgrading RuboCop dependencies. Because of this, I prefer downgrading RuboCop.

By the way, I'm now working on a pull request to bring back Ruby 2.3 support to Aruba. I've solved the problem of getting Ruby 2.3 to install locally by updating Aruba's old Dockerfile. See cucumber/aruba#787.

@boardfish
Copy link

I'm a big fan of implicit block syntax and believe it makes for very readable tests, while also encouraging testing against one single subject as much as possible. If it can be extracted out to a gem, that'd be great.

I was digging through this repo when helping a friend out with their issue and stumbled upon this one, so it was a slight shock to the system to know that the syntax I've been leaning on quite heavily is being deprecated.

@pirj
Copy link
Member Author

pirj commented Nov 29, 2021

@boardfish Deprecated in 3.99, and restricted in 4.0. Check rspec/rspec-expectations#1285 and especially an attempt to restrict it in 3.8.5 for details and reasoning.
An example how existing matchers can be patched to work with implicit block syntax. I encourage you to create a gem that would patch RSpec built-in matchers, we'll be happy to mention it in the RSpec 4.0 announcement.
I suggest continuing the discussion in rspec/rspec-expectations#1285.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

7 participants