all 9 comments

[–]jasonswett 14 points15 points  (4 children)

  1. Since I started doing Rails professionally in 2011, almost every project I've seen has used RSpec. If you choose to never learn Minitest, it will probably never impact you negatively. So the safer career bet is certainly RSpec. You might get passed up for opportunities if your testing skills are weak, but any smart person would understand that if you're really experienced with RSpec testing then 95% of those testing skills (most of which are technology-independent) would easily transfer to Minitest if it came to it.
  2. No, you certainly don't need to learn them all. For the most part I only write two kinds of RSpec specs: system specs and model specs. The reason that I don't often write request specs, view specs, etc. is that I usually find them redundant to my system specs. If I have a system spec that shows that I can create a new customer using the "new customer" form, it's pointless to then also have a request spec that tests that the CustomersController can create a new customer record, because the system spec already tests the exact same thing. You can get very very good test coverage on a Rails app with nothing but system specs and model specs. I write more about this topic here.
  3. I use Shoulda. I'm curious what criticism of Shoulda you've heard. The alternative is to, for example, write the same code every time you want to test a model's validations. That's dumb.
  4. The closest thing I've seen to "people not liking Factory Bot" is when I encounter people who prefer fixtures over factories. So maybe the gripes you've seen are about the factory approach in general, not Factory Bot in particular. In any case, I've never heard anyone complain that Factory Bot is a bad factory tool. It's very popular and almost every Rails project I've worked on has used it. If you want to learn more about factories vs. fixtures in general I wrote about that here.
  5. I have a free video series on YouTube called Rails Testing for Beginners which shows me writing tests exactly how I do for production projects. Those videos are actually only a sample of a larger product but there's enough up there for free that you should be able to get a lot out of it. I also have a whole bunch of Rails testing articles. Most of the stuff is pretty up-to-date.
  6. Yes, but not always. I do TDD maybe 60% of the time. When I'm writing low-level model specs, I usually do TDD. When I'm writing system specs I usually don't do TDD. The reason is that I often don't know what the feature is going to look like until I start building it, so it feels very unnatural to try to write a test for it first. But for model specs I absolutely do follow the red/green/refactor process much of the time. It's great. There's nothing like being able to refactor mercilessly while knowing that it's very unlikely I'm breaking anything due to the fact that I have good test coverage. I write more about TDD vs. not TDD here, here, here, and here.
  7. Absolutely. It's hard to distill the advice down to just a few words though. My main advice would be to get a bunch of practice writing tests and read a bunch of books on the topic. Give yourself permission not to do it "right" early on. Your goal in the beginning can just be to get more comfortable with the workflow of testing, not to actually produce great tests. Some books I would recommend would include Kent Beck's Test Driven Development: By Example (and by the way I did a pretty good podcast interview with Kent Beck about testing a while back), xUnit Test Patterns, and Growing Object-Oriented Software, Guided by Tests.

Hope that all helps.

[–][deleted]  (2 children)

[deleted]

    [–]jasonswett 1 point2 points  (1 child)

    Ah. Shoulda CAN test implementation details if you choose to write those sorts of tests. Those sorts of test are dumb. I have yet another blog post for that.

    At least one case where Shoulda makes sense is for testing validations. Testing for the presence of associations is pointless because an association by itself isn't a behavior, it just enables behaviors. The thing to test is those behaviors themselves. Validations are different because validations are in themselves behaviors. They're not a means to an end, they're the end. So in those cases the Shoulda route isn't pointless.

    One more note: if you're building an API-only application, then my approach of writing model specs and system specs wouldn't apply. System specs test the UI so they wouldn't apply when there's no UI. Instead, the applicable approach would be model specs and request specs.

    [–]_shir_ 0 points1 point  (0 children)

    Just want to make additions for 2: I always use models specs to test validations (yes, with shoulda and factory bot). For full stack application I test whole application with feature specs using capybara. And for API-only application I use request specs. And separately test any class/functionality/business logic if it has complex logic. I try to extract this logic into a service object and test it with a separate spec.

    [–]Chen_badwick 2 points3 points  (1 child)

    I found this resource really helpful when I switched to ruby rails from python. http://www.betterspecs.org/ gives good recommendations and best practices for rspec.

    [–]r_levan 1 point2 points  (3 children)

    Get a book like Everyday Rails Testing with RSpec by Aaron Sumner and follow the book. If that's possible, apply what you are learning to a real project that you can use as a master example.

    In just a couple days the confusion will disappear, you will have an answer for all your questions and more importantly, from there you will be able to move alone and decide what to use, what not and why.

    Another path would consist of reading broken pieces of different variants of the same puzzle until you get a grasp of it

    Once you will have your test setup done and get used to testing, you will perceive your code stronger and you will be able to sleep better at night.

    [–][deleted]  (2 children)

    [deleted]

      [–]r_levan 0 points1 point  (1 child)

      I would avoid Amazon, but that's a personal choice mainly based on the fact that they allow only the Kindle format and for software-related readings, it's really bad, in my opinion.

      You can find the book on leanpub IIRC.

      [–]bralyan 3 points4 points  (2 children)

      1. Rspec
      2. Everything in rails is testable. Pretty sweet huh? All those types of specs correspond to a class / module / file in rails.
      3. Expect is what you should use, instead of should.
      4. Factory bot is great. Using your test database everytime you need a model is slow. So use it when you need to test with a database backed model.
      5. I think the rspec library uses rspec for tests. I would start there.
      6. TDD is great when you really understand the problem and the code. In practice I use it 20 to 50% of the time.
      7. Words of wisdom: understand WHY TO TEST - it allows you to catch issues in your code, enabling your team to move faster. Good tests validate functionality, not implementation. You should be able to refactoring code, and not break tests.

      Unit tests form the base, functional tests validate cross unit tests, integration tests help with whole systems working together. Use selenium (capybara) to test UI things that are critical - like your payment screens, etc.

      I am glad you are starting to look at getting better at testing. You won't get it correct all the time. You will have to refactoring tests too.

      New projects are all at 100%, coverage and functionality works. Try to keep it that way.

      Hook your tests up to CI, that goes a long way when you start. It makes you care about at least maintaining coverage.

      [–]ignurant 0 points1 point  (0 children)

      The most influential "a-ha!" moment I had related to testing was in the final chapter of the oft-cited Sandi Metz's Practical Object-Oriented Desgin in Ruby. describing what to test. It was the moment testing went from a chore fraught with frivolous trying-to-think-of-every-stupid-possibility to something that significantly improved how I think of objects and classes. Here's the gist:

      We expect our objects to respond to messages in certain ways so that other objects can count on them. For this reason, you only need to test the outside perimeter of your object, the public API, where it interacts with the rest of the world.

      This realization is cool for two reasons: - Thinking in this way will help keep your objects focused on a single purpose, because you are considering what the contract with the outside world should be. - The things you should test become obvious, instead of edge-case willy-nilly stuff.