How would I test this view? - ruby-on-rails

So I'm writing my app doing feature-first BDD with Rails, Cucumber, RSpec.
My client requested that a total gets calculated as you fill in the fields.
My question is, this is not really a feature, more of a spec. This is related to the feature of creating the invoice, but I don't think it justifies a whole integration test.
It's just javascript that's running.
So my mind is telling me to write a spec for this in the view spec. Is this correct? And is it possible to test these javascript cases in rspec?
Or should I isolate this a step further and go straight for a javascript testing framework?

I'd really recommend you start with integration tests for every feature you plan to add to your app, they're an invaluable tool for understanding the problem your trying to solve and communicating new additions to the software with clients.
To test JavaScript on your page, you may want to look into Selenium, from memory you can use Selenium as a drop in replacement of Rack::Test when using Capybara to test web pages.
As far as Cucumber goes, I'd suggest making a new feature file for creating the invoice and having a scenario that tests that the correct total total gets calculated when you enter a certain string into a field. Something like:
Scenario: Filling out the form
Given I am looking at the invoice form
When I fill in the fields with <value1> and <value2> without submitting
Then I should see <total> on the page
Obviously I don't know enough about your form to know what fields need to be filled out, but that's a general outline of how I'd test it. I'd also make a test in the view spec to ensure that there is a section for the calculated total value in the form.
After that, I'd drop down to writing specs for the Javascript in Jasmine and implement the code to calculate and display the total.

If you're just trying to test your JavaScript code, I recommend Jasmine.

Related

In rails, should I include user input form error flows on capybara (or integration) tests?

Rails supports several types of tests:
Model tests
Controller tests
Functional tests
Integration tests
And, with capybara, it can also support:
Acceptance/integration/feature (depends on the author) tests
On some sites I see that these acceptance/integration/feature tests should only test particular flows, leaving edge cases for other kinds of tests. For example:
Integration tests are used to test the interaction among any number of controllers. They are generally used to test important work flows within your application.
http://guides.rubyonrails.org/testing.html#integration-testing
While these are great for testing high level functionality, keep in mind that feature specs are slow to run. Instead of testing every possible path through your application with Capybara, leave testing edge cases up to your model, view, and controller specs.
http://robots.thoughtbot.com/how-we-test-rails-applications
But I also see things like:
Your goal should be to write an integration test for every flow through your app: make sure every page gets visited, that every form gets submitted correctly one time and incorrectly one time, and test each flow for different types of users who may have different permissions (to make sure they can visit the pages they're allowed to, and not visit the pages they're not allowed to). You should have a lot of integration tests for your apps!
https://www.learnhowtoprogram.com/lessons/integration-testing-with-capybara
So, that's my question: In rails, should I include user input form error flows on capybara (or integration) tests?
Or do you think it should be enough to write view tests to test for the existance of flash messages, test failure flows via controller tests with the assigns helper, and only test successful flows through acceptance/integration/feature tests?
Edit The accepted answer was due to the comments.
User input form errors are handled by Active Record validations in Rails. So you could cover these with unit tests. But those kinds of tests only verify that you have validations present on your model. I'm not sure how much utility these types of tests offer other than allowing you to recreate your models in another framework or language and still have your tests pass.

Setting bounds between rspec and cucumber in Rails

I like the way Cucumber connects user specifications to integration testing. The Cucumber part is more or less clear to me.
I struggle when it comes to what should be tested with rspec (non-integration testing) and what shouldn't.
Is it right to unit-test with rspec something that has already been tested with Cucumber (e.g. unit-test will 100% fail if Cucumber test fails, and unit-test will 100% succeed if Cucumber test succeeds)?
To be specific, I have three examples I'd like to resolve.
Here is a case from the RSpec book.
They have the following Cucumber scenario:
Given I am not yet playing
When I start a new game
Then I should see "Welcome to Codebreaker!"
And I should see "Enter guess:"
They build two rspec-tests right after:
describe "#start" do
it "sends a welcome message" do
end
it "prompts for the first guess" do
end
end
Another example is testing routing or action redirect, while there is the following scenario:
Given I am at the login page
When I fill in the right username and password
Then I should be at the index page
Sometimes we test helpers that are already tested with Cucumber:
Given Mike has spent 283 minutes online
When I go to the Mike's profile page
Then I should see "4:43" for "Time online:"
I should probably test helper that breaks 283 minutes into "4:43", but it turns out that it is already tested with Cucumber.
It may not be the best examples, but it illustrates what I am talking about.
To me those tests are duplicates.
Could you please comment on the examples above?
Is there any principles or guidelines on what should be tested with rspec, when there are Cucumber tests already?
All this is only my personal opinion on this broad and open topic. Some people might disagree and funny enough they can.
As of general guidelines you should use Cucumber to test entire application stack, something that is called user experience. This application stack might be composed of many smaller independent objects but, same as user using your application wouldn't be interested in those details, your cucumber test shouldn't care for them and focus instead on outer layer of your application.
RSpec( in your setup!) should on the other hand put a main focus on those small objects, building blocks of your application.
There is a big problem with small application examples from the books: They are to small!
Boarder between outer layer of your application and its interiors is to blurred. Entire application is build with two objects! It is hard to distinguished what should test what. As your application grow in size its getting more obvious what is a user experience test(cucumber) and what is object - state test/message expectation test(RSpec).
Using your second example:
With this Cucumber story:
Given I am at the login page
When I fill in the right username and password
Then I should be at the index page
Rspec:
You will probably have some sort of User model:
test user name syntax(must start with capital for example)
test password must be 7 characters have numbers etc...
You can have some sort of authentication object:
test for valid and invalid logins etc
test for exceptions being thrown ....
What if your Authentication database is on different server?
mock connection and authentication database and test if database receive an request from authentication object.
And yada yada yada... Forever your cucumber test will guard general purpose of your application user login. Even when you add or change behaviour, under the hood, as long as this test pass you can be confident that user can login.
you should test things once(in one place)
object its responsible for testing its incoming massage(object public interface) for state(return value)
when your object depends on other object(sends its a message) don't test it for state(return value) that object is responsible for it.
when your object depends on other object(sends its a message) mock that second object and test if it receive your message.
Generally your question is too broad and you wont find a single answer, different people will have different ideas. What you should focus on is to test, as good as you can and with time you will definitely find right way for you. Not a great test suit is much better then none.
Because good design helps to write good test I would recommend Practical Object-Oriented Design in Ruby: An Agile Primer by Sandi Metz(which is one of a best book I've read)

Ruby_on_Rails Testing The Database Using Rspec

Actually i am newbie to rails testing
I want to know what are all the step covered in the rails testing.?
Could anyone help me knowing the steps involve in Professional Testing
Check out the rails guide Gavin linked you. Can also check out this book: http://pragprog.com/book/achbd/the-rspec-book. It covers how to use rspec, and covers testing various parts of the application.
I also rather enjoyed Rails 3 in action, which teaches the basics and various topics of rails, while doing inside-out testing throughout the entire book. Rails 4 in action is a work in progress edition as well.
As for my answer:
Generally testing first before you write code makes the process better & easier. Writing tests after the fact isn't as nice, even though it does give you the coverage. When it's part of your regular workflow to add features, it's quite nice. If you have a new feature that you want to add, such as user sign up that sends a confirmation email. You can write the integration test first. It describes the user as going through the sign up form, filling it properly, and then checking if an email was sent.
From there you can test internals of the user model, making sure methods you build for this to work function as expected. Then when you have your tests green, add another scenario to the integration tests where the login was invalid.

How should I test my Rails app?

In the past couple of days I've been making slow progress adding tests to an existing rails app I've been working on for a little bit.
I'm just trying to figure out how much and what kind of tests (unit, functional, integration) will be enough to save me time debugging and fixing deploys that break existing functionality.
I'm the only one working on this application. It's basically an inventory management database for a small company (~20 employees). I didn't add testing from the beginning because I didn't really see the point but I've have a couple of deploys screw up existing functionality in the last little bit, so I thought it might be a good thing to add.
Do I need to test my models and controllers individually AND perform integration testing? There seem to be developers who believe that you should just integration test and backtrack to figure out what's wrong if you get an error from there.
So far I'm using RSpec + Factory Girl + Shoulda. That made it pretty easy to set up tests for the models.
I'm starting on the controllers now and am more than a little bit lost. I know how to test an individual controller but I don't know if I should just be testing application flow using integration tests as that would test the controllers at the same time.
I use integration tests to test the successful paths and general failure paths, but for the edge cases or more in-depth scenarios then I write model/view/controller tests.
I usually write the tests before writing the functionality in the application but if you want to add tests afterwards then I recommend using something like SimpleCov to see which areas of your application need more testing and slowly build up the test coverage for your application.
Writing tests after the app is already written is going to be tedious. At a minimum you should be testing for integration cases (which will test most controller functions and views), and also model tests separately so that your model calls work as you think they should.
For integration testing I find Capybara easy to use.
As a rule of thumb, most of your tests need to be unit, some functional, few integration.
Rails adheres to this wholeheartedly and you should do the same.
At the minimum you have to have:
A unit test for each of your models, add a test case for each of your validations in each of them, and finally a last one to make the sure the model is saved. If you have stuff like dependant: :destroy, touch: true on related models (has_many, belongs_to), add test cases for them as well.
A functional test for each of your controllers. Test cases for each action. Some actions can have multiple responses (like in case of 422 errors) so add another case to test the error response. If you have a authorization filter, test them as well.
Then you can have an integration test for a typical new user flow. Like
Sign Up -> Create Post -> View it -> logout. Another one is to make sure that unauthorized users cannot access your resources.
And from now, do not commit ANY code without the above mentioned tests.
The best time to plant a tree was 10 years ago, second best time is now, so start testing!

How do specflow features link to unit tests in asp.net webforms projects?

For example if I write Add A customer feature which might go like this:
Scenario: Add A customer
Given I am on the customer page
When I enter login name
then I press Add
And I should see the newly added customer confirmation message
I start to write the code in watin to open the browser and go to the customer page.
Which doesn't exist at this point.
The questions are:
1) do I then jump into unit tests and write a unit test for the page that doesn't exist? in MVC this would be a controller but in asp.net webforms it's the same test that is in the step definition.
2) How does the unit test tie in with the step definition? Let's say at the end of the project I have a load of features and a load of unit tests. Then one of the features starts failing if I looked at that how would I know which unit tests correspond to it? Or does this even matter?
I'm not sure if this is a best practice question or it's whatever people feel is right.
Thanks in advance.
One of the cool things about specflow (and cucumber...) is that you can write the test before any page exists. So what I'd do is exactly what you planned to do.
1) Write a specflow test, which describes how you want to work with the page. Looks like you have that already.
2) Run the test. The first line will fail (Given I am on the customer page).
Now you have a choice. Do you just wan to write the code that fires up watin and navigates to the customer page? Fine, do that; then write the customer page (just enough so that the first line of the test passes).
Or, recognize that your test requires a customer page. There's lots here to test: do all the data fields exist? Does the page do input validation correctly? If I post to the server, do I get the correct response? If I post to the server, does the DB get updated correctly? And so on. Some of these sound like unit tests (business logic that takes the form data and stores it in the DB); some sound like UI tests that would be good with SpecFlow (page details, validation) and some sound like integration tests (probably good with specflow).
Once you've written all those and they pass, go back to your original test, and get the second step to pass (I click...)
And so on.
To answer your second question, hopefully you're running the unit tests and specflow tests often enough that if a test fails, it's due to something you've done in the last few minutes. It shouldn't be too hard to see what failed and match it to what you just did.
If you're not running your tests that often, then well you should be.

Resources