bigpotato
bigpotato

Reputation: 27527

Rails: Should I test validations using Cucumber, RSpec, or both?

I have been using RSpec and Cucumber for a few months. But since I'm the only developer here, it's been all self learning, so I'm asking this to clarify where to test what.

I'm currently creating a CMS for Coupons. There's a form to create a new coupon. I have the happy path working and tested in Cucumber. Should I also have a test for when the form is filled out incorrectly? If so, should I be creating a scenario for each case that doesn't pass my validations?

I already have my validations tested in RSpec:

it { should validate_presence_of(:name) }
it { should validate_presence_of(:code) }


describe "validations" do
  specify "the start date must be before the end date" do
    site_wide_coupon = SiteWideCoupon.new(name: "Free Shipping", code: "ABC123")
    site_wide_coupon.start_date = 1.month.from_now
    site_wide_coupon.end_date = 1.month.ago
    expect(site_wide_coupon.valid?).to be_false
    expect(site_wide_coupon.errors.full_messages).to include("Start date must be before the end date")
  end

  context "it is a flat amount coupon" do
    let(:site_wide_coupon) {
      site_wide_coupon = SiteWideCoupon.new(name: "Flat Amount", code: "ABC123")
      site_wide_coupon.start_date = 1.month.ago
      site_wide_coupon.end_date = 1.month.from_now
      site_wide_coupon.valid?
      site_wide_coupon
    }

    it "validates presence of discount_amount" do
      expect(site_wide_coupon.errors.full_messages).to include("Discount amount can't be blank")
    end

    it "doesn't validate the presence of discount_percentage" do
      expect(site_wide_coupon.errors.full_messages).not_to include("Discount percentage can't be blank")
    end
  end

  context "it is a percentage amount coupon" do
    let(:site_wide_coupon) {
      site_wide_coupon = SiteWideCoupon.new(name: "Percentage Amount", code: "ABC123")
      site_wide_coupon.start_date = 1.month.ago
      site_wide_coupon.end_date = 1.month.from_now
      site_wide_coupon.valid?
      site_wide_coupon
    }

    it "validates presence of discount_amount" do
      expect(site_wide_coupon.errors.full_messages).to include("Discount percentage can't be blank")
    end

    it "doesn't validate the presence of discount_percentage" do
      expect(site_wide_coupon.errors.full_messages).not_to include("Discount amount can't be blank")
    end
  end
end

describe "#flat_amount?" do
  context "name equals 'Flat Amount'" do
    it "returns true" do
      site_wide_coupon = SiteWideCoupon.new(name: "Flat Amount")
      expect(site_wide_coupon.flat_amount?).to be_true
    end
  end

  context "name doesn't equal 'Flat Amount'" do
    it "returns false" do
      site_wide_coupon = SiteWideCoupon.new(name: "Something else")
      expect(site_wide_coupon.flat_amount?).to be_false
    end
  end
end

describe "#percentage_amount?" do
  context "name equals 'Percentage Amount'" do
    it "returns true" do
      site_wide_coupon = SiteWideCoupon.new(name: "Percentage Amount")
      expect(site_wide_coupon.flat_amount?).to be_true
    end
  end

  context "name doesn't equal 'Flat Amount'" do
    it "returns false" do
      site_wide_coupon = SiteWideCoupon.new(name: "Something else")
      expect(site_wide_coupon.flat_amount?).to be_false
    end
  end
end

Would it be necessary to test that my validations fire in Cucumber then? Or would that just be repeating my RSpec tests and not adding any value?

Or maybe I should only have one test that submits the form without filling anything in and testing that the errors show up on the page?

What do you guys usually do?

Upvotes: 2

Views: 364

Answers (3)

Piotr Brudny
Piotr Brudny

Reputation: 656

I think that having validation tests only in RSpec is not sufficient. If you want to make sure that user can see the error message you have to use Cucumber/Capybara/Jasmine...

I agree that testing all validations in Cucumber is not a good idea. However testing one validation per form might be really helpful.

My approach is that I test each validation in RSpec + one Cucumber scenario per form with failing one validation.

Upvotes: 0

Zach Kemp
Zach Kemp

Reputation: 11904

My two cents: Forget about cucumber. Having to keep another whole DSL in your head and maintain the steps results in a lot of wasted time in the long run (especially if you're working by yourself). RSpec is a much better way to go as it's closer to plain Ruby, and you can probably even transition to MiniTest::Spec fairly easily. Don't erase your cucumber tests all at once, but delete them as they fail and replace them with specs.

As for duplication in tests, I tend to not mind it as much. Since you're defining detailed scenarios and their expected outcomes, a repetitive series of tests can be more explicit and easier to understand than even a well-refactored suite.

Upvotes: 1

chris-tulip
chris-tulip

Reputation: 1830

It comes down to why you're testing in the first place. The goal of a test suite is to warn developers in the event that something in broken so that they can fix it. Imo double testing is a form of waste since the goal of the test suite has been fulfilled if after writing one test.

So long story short I reckon it's fine to test it just in rSpec unless your cucumber test is testing something different.

Upvotes: 0

Related Questions