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
shoulda-matchers 5.0.0 #1380
Comments
I agree with those thoughts! It would be nice to get some feedback from the community to answer some of those questions:
I think that asking for the job of the developer would be a good idea. Ask if he used it as a Fullstack or a Backend developer or had experience in both cases. Perhaps this information will give us some insight, but I'm still not sure what. Maybe with a Google Form. What do you think? |
@vsppedro I think making a Google Form makes sense. Going off of your questions, maybe we list each matcher and offer a 0-5 scale (0 means "I've never heard of this matcher", 1 means "I've heard of this matcher but have never used it or would not use it", 5 means "I use it all the time")? Also maybe while we are asking that, we can ask people for some general feedback, i.e., "Is there anything you find confusing/frustrating about using shoulda-matchers?" or "Is there anything you would change about shoulda-matchers that would improve the developer experience?" Something like that. |
Sounds like a plan! As soon as I have some time I will create this form with the questions we talked about and I will share it with your email. |
It would be great to see allow_value to be improved. The proposed API elsewhere is: it { should validate_attribute(:brand).set_to("Suzuki").with_failure_message("is out of business") } I'd propose a few other additions to this API:
so these combos would be possible it { should validate_attribute(:brand).set_to("Suzuki").with_failure_type(:out_of_business) }
it { should validate_attribute(:brand).set_to("Suzuki").with_failure_type(:out_of_business).with_failure_message("is out of business") }
context "with brand" do
before do
subject.brand = "Suzuki"
end
it { should validate_attribute(:brand).with_failure_type(:out_of_business) }
end Note also that the ActiveModel::Errors api changed with Rails 6.1 and currently has deprecation warnings based on internals that will break in 6.2. We'll need a solution for that too. |
@jonspalmer We are working on fixing integration with Rails 6.1 so hopefully we can address that last issue you mentioned at least. @vsppedro What are your ideas on the remainder of the next release? I don't want to get into a place where it takes a year to finish it and we're holding up other PRs that people are submitting, so I'm wondering if it makes sense to just stick to removing support for EOL'ed Ruby and Rails releases and that's it? Maybe we address some of the other things that I or other people have mentioned in future releases. |
For ruby:
For rails:
That is what I would like to achieve. Yes, I know this is going to take a long time. If you want, I will concentrate only in removing, and in the next version, I’ll try to add all the pending support. |
@vsppedro That sounds good. No, I think it's okay to add support for Ruby 3.0 and Rails 6.1 and 7.0 now. I feel like people are going to be asking for it and based on what I've seen so far, I feel like it may involve making breaking changes to add that support, so I feel like it's worth working through all of that now vs. later. |
@jonspalmer I don't think we'll be able to get to changing |
@mcmire Sounds very reasonable. Rails 6.x, 7.0 and Ruby 3 would be huge wins and should take priority. Phasing out |
Is it correct to say that Ruby 3 is not currently supported?
Believe this is related to https://www.ruby-lang.org/en/news/2019/12/12/separation-of-positional-and-keyword-arguments-in-ruby-3-0/. |
I'm sorry, we are not supporting ruby 3.0.0 for now. I think that this problem that you're pointing out was solved in this PR: #1409. We will release it with ShouldaMatcher 5.0.0. Unfortunelly, the CI don't work with Ruby 3.0.0 because of this bug: https://bugs.ruby-lang.org/issues/17536. We are waiting for a new realese with this commit: ruby/ruby#4077. I tried to make it work with ruby-head, but did not work out as you can see in this comment: #1427 (comment) I will give it another try. I hope that the ruby 3.0.1 will be released soon. For now, I think you can use this PR if you can't wait: #1410. I hope that helps. |
I would love to hear any feedback from anyone using the 5.0.0.rc1. Thanks! |
It seems to me that we can close this issue and maybe start a new discussion for the next release. 🎉 |
That's fine with me :) |
I know we've been talking about this lately so I figured that it would be better to talk about it in one place.
What do we want to include in 5.0.0? We know that we want to remove support for old Rubies and Rails. So minimally we have:
But, given this is a major release, if we've been wanting to make breaking changes, now is the time to do it. So we should think about that too. Something I've been wanting to know is, how many matchers do people actually use? Which matchers are used the most? Which ones are used the least? Given that every matcher we add creates more maintenance cost, are there any matchers that we can outright remove?
Based on that, here are some thoughts on possible breaking changes:
ActionController matchers
Some of the controller matchers we offer only apply to Minitest. These matchers were originally added as matcher versions of assertions that Rails provided in Test::Unit land. However, rspec-rails has some equivalent matchers, some of which are named the same. These matchers are:
redirect_to
(also calledredirect_to
in rspec-rails)render_template
(also calledrender_template
)render_with_layout
(already captured by rspec-rails'srender_template
)respond_with
(covered by rspec-rails'shave_http_status
matcher)So, ideally, 1) we should not add these matchers to RSpec example groups so that users can make use of rspec-rails's matchers freely without interference. Also, 2) in Minitest, there is no real reason that these matchers shouldn't be equivalent to rspec-rails's matchers. So perhaps there is a way to simply import these matchers from rspec-rails into Minitest test cases rather than reimplement them as we have done. That would save us from having to maintain them.
Some of our controller matchers are not very helpful. For instance, does
set_session
andset_flash
really provide any more information that cannot be gleaned by saying something likeit { expect(controller.flash[:foo]).to eq("bar") }
orassert_equal "bar", controller.flash[:foo]
? My guess is that it does not.I question the value of
filter_param
, which (aside from not being related to controllers) merely checks that you've added a value toRails.application.config.filter_parameters
. In my opinion, this is not a valuable test. My philosophy is that if you add a change to your code, and that change contains no logic, then it is not worth it to write a test for that code (because that code is deterministic and simple). There is no logic in making a configuration change to your Rails application, so in my opinion, there is no reason to havefilter_param
.I also question the value of the callback matchers. In my opinion, if you want to test a callback — and this applies to models, jobs, or any other thing that has the ability to add a callback — you should not test that the callback gets called, you should the actual behavior of the callback itself. However, the callback matchers don't do that. In fact, the callback matchers (like many of our matchers) rely on a private API in Rails. So not only are we encouraging poor testing practices, but we have a matcher that is liable to break on a future Rails change. We should consider removing this matcher.
I also question the value of
rescue_from
, for a similar reason. All this does is check that you've registered a method for a particular class of exceptions. It doesn't actually test what happens when that exception occurs, which to me is a way more valuable test. We should consider also removing this matcher.ActiveModel matchers
allow_value
— this matcher has a confusing API. In Wordingallow_value
..with_message
does not read well #1022 I proposed changing this matcher entirely (validate_attribute
instead ofallow_value
). We should consider whether it is worth it to make this change.ActiveRecord matchers
have_db_index
andhave_db_column
— these matchers have always been a little weird to me. Similar to my point aboutfilter_param
, your database schema is 1) not code, 2) doesn't contain logic and 3) is a form of configuration. So it seems extremely odd that we would give people a way to test their database. Plus, I've never come across a codebase that is not using shoulda-matchers where people consciously test the database in this manner, so it does not match the real world. I would really be curious to know how this is providing value for people. But in my opinion, these are not useful and we should consider removing them to save cost of maintenance.serialize
— I really don't know how this is helpful either. Again, typically there is no logic around this. This matcher does not test behavior, so if your serialize class doesn't work then you won't get an error just from using the matcher.have_readonly_attribute
— similar story. I think it's better to test that an attribute cannot be written to rather than that it shows up inMyModel.readonly_attributes
.implicit_order_column
— similar story.enum
— again, I question the value of this matcher. How does this help anyone if this is (again) using a private API to verify that Rails knows your attribute is an enum attribute AND if the options you give to the matcher are exactly the same as what you're using in your model?accept_nested_attributes_for
— similar. To be honest, I've never used this matcher.validate_uniqueness_of
— there is a bit of inconsistency in the examples we give in the docs vs. how the matcher actually works. Namely, it doesn't make use of thesubject
in a logical way. This bug is documented in validate_uniqueness_of not using given record #1067 and perhaps we should consider changing this behavior. (Not sure if this would require a backward-incompatible change, but noting it in case it does.)With that in mind, what are y'all's thoughts on these changes? I know that removing matchers would be much larger than merely removing old Rubies/Rails. I don't want to make people angry, and I don't want people to switch away from using this library. But at the same time 1) it's a lot of work to maintain shoulda-matchers, and the less stuff we can have it in it, the better; and 2) as I alluded to above, some of the matchers we have are not based on good testing philosophy or even real-world practice, and I want this library to help people find bugs faster in their code and not give them something that they could have easily done themselves. Anyway, I'm open to alternate opinions.
@vsppedro @KapilSachdev @guialbuk
The text was updated successfully, but these errors were encountered: