8
\$\begingroup\$

I'm working on writing tests for a rails application using cucumber and capybara. I have a scenario for a user editing a post, and making it invalid.

The scenario looks like this:

Scenario: I edit a post and make the data invalid.
 Given I have 1 post
 And I view my 1st post
 Then I click "Edit"
 And I fill in the edit post form with bad data
 When I click the "Update post" button
 Then I should see "Title is too short (minimum is 3 characters)"
 And I should see "Body is too short (minimum is 30 characters)"

Should I leave the scenario as-is, or create a scenario for entering the title incorrectly, and another scenario for entering the body incorrectly, like this:

Scenario: I edit a post and make the title too short.
 Given I have 1 post
 And I view my 1st post
 Then I click "Edit"
 And I fill in the edit post form with a title that is too short
 When I click the "Update post" button
 Then I should see "Title is too short (minimum is 3 characters)"
Scenario: I edit a post and make the body too short.
 Given I have 1 post
 And I view my 1st post
 Then I click "Edit"
 And I fill in the edit post form with a body that is too short
 When I click the "Update post" button
 Then I should see "Body is too short (minimum is 30 characters)"

If the post has several more fields, should I still create a scenario for each one, or would it be more DRY to use one scenario?

Phrancis
20.5k6 gold badges69 silver badges155 bronze badges
asked Apr 3, 2016 at 0:05
\$\endgroup\$
3
  • 3
    \$\begingroup\$ I have retracted my vote to close after looking at Cucumber website, I did not realize at first that this was actual code. \$\endgroup\$ Commented Apr 3, 2016 at 0:35
  • \$\begingroup\$ @Hosch250 This is actual code that tests a rails application. The given/when/then/and lines tell cucumber what to do (They correspond to ruby code in another file, but I was wondering what was the best way to write the cucumber steps and scenarios would be in the feature file.) The current way I have works (it is the second example in the question), but was wondering if it was implemented correctly (so I think it falls under "Best practices and design pattern usage"). \$\endgroup\$ Commented Apr 3, 2016 at 0:35
  • \$\begingroup\$ Cool. I thought it might not be pseudocode, but I don't know Cucumber, so I thought I'd better ask. Good question. \$\endgroup\$ Commented Apr 3, 2016 at 1:11

2 Answers 2

7
\$\begingroup\$

Personally, I only write feature tests for critical and very common cases, and outsource more specific tests (i.e is a certain field on a model validated) to model specs.

I wouldn't consider it a feature that a certain validation error is shown to the user, but I consider it a feature that the user gets informed that something went wrong and his post couldn't be created.

TL;DR Test the user experience in a feature spec and data integrity in model / controller specs.

Use different thinking hats for different tests:

  • Feature tests: Think in the user's perspective, how does the user interact with your app? what is the user expecting from your app?
  • Model tests: Think compulsive orderliness, how can you ensure data integrity?
  • Controller tests: Think paranoid, who can access what? does your controller comply with your API specs?

I would test in a feature spec for a "post":

  • That the user is able to create a post with an expected set of information (i.e the minimum that is required to create a post) and is redirected to the new post which shows the entered information.

  • That the user is unable to create a post by just hitting the "Submit" button without filling anything in and is shown a validation error. After correcting the user's mistake he should be able to create the post and be redirecred to the new post which shows the entered information.

This ensures the following "features":

  • Posts can be created
  • The user is informed about mistakes
  • Mistakes can be fixed
  • The user is assured that his post has been created.

I would test in a model spec:

Spec.describe Post, type: :model do
 subject { create(:post) }
 context 'validations' do
 it { should validate_presence_of(:title) }
 # for my taste, it's good enough to test that we validate the length
 it { should validate_length_of(:title) }
 it { should validate_presence_of(:body) }
 # if you want to be super-strict, you can check the length
 it { should validate_length_of(:body).is_at_least(100) }
 end
end
answered Apr 3, 2016 at 1:21
\$\endgroup\$
3
  • 1
    \$\begingroup\$ Could you perhaps in your answer expand on why you prefer to do this in model specs? \$\endgroup\$ Commented Apr 3, 2016 at 1:30
  • \$\begingroup\$ I added some lines about it, I don't consider it a feature that a very specific validation error is shown. But let's say you provide a set of choices if the user doesn't enter something - then it's a feature to test that these choices appear if the user didn't fill in that field. \$\endgroup\$ Commented Apr 3, 2016 at 1:35
  • \$\begingroup\$ @jacwah also note that my answer is just my opinion from experience - unfortunately there's no scientifically correct answer :/ \$\endgroup\$ Commented Apr 3, 2016 at 1:59
2
\$\begingroup\$

I personally would use a Scenario Outline in this situation.

Feature: Shortest Length Validation
Rules
 - Title must be more than 3 characters long
 - Body must be more than 30 characters long
Scenario Outline: I edit posts making various lengths too short.
 Given I have 1 post
 And I view my 1st post
 Then I click "Edit"
 And I fill in the edit post form with a <type> that is too short
 When I click the "Update post" button
 Then I should see "<capType> is too short (minimum is <minLength> characters)"
Examples:
| type | minLength | capType | 
| title | 3 | Title |
| body | 30 | Body |

If you want to add more to it, you can add more to the table, and replace the values to change with the heading of the column that you would like to replace it with, in between these brackets: <>.

If you wish to make lots of Scenarios that fundamentally do the same thing but in different ways, this is almost definitely the best way of doing it.

answered Apr 4, 2016 at 10:47
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.