Is there anyway to load a page in capybara in a before :all block, and then run each test on the same page?
It seems right now at the end of each test the page is unloaded, so I have to do the setup in a before :each block, which really slows things down.
You can do that by not requiring capybara/rspec and instead implementing you're own before after blocks and RSpec configuration that don't call Capybara.reset_sessions, however that defaults the whole concept of tests being independent, and potentially also makes your tests order dependent which really isn't a good idea.
If your issue is logging in each time you should look into fast tracking the login (for instance test mode in Devise - https://github.com/plataformatec/devise/wiki/How-To:-Test-with-Capybara)
Related
I'm finding Rails integration tests relevant for testing flows and I have some questions about the industry standard on replacing controller test (deprecated in rails 5) with integration tests.
Usually we have tiny controllers where we get the parameters, call the right collaborator and prepare the response and it is easy to test it by mocking the collaborator directly on the controller object.
I am concerned about the overhead of migrating every controller test to integration test that persist the db. What are the standards for this case?
Whats the standard when testing just one route/action and not a complete flow?
How can we replace this?:
#controller.stubs(:authenticate).returns(true)
Integration tests are intended to mimic a real user. They're meant to test the entire application in their entirety.
Opinion varies on what this means. To me, it means you should avoid stubbing/mocking completely. Not a single thing stubbed or mocked, everything executed in full. This means that every integration test I write goes through the actual authentication process of typing in a username and password. Some of the steps are redundant, yes.
Integrations tests are slower all around than unit/controller tests. Cutting out the authentication steps likely won't save you enough time to make a difference in the long run (no pun intended).
We have a very large application that we are currently implementing rspec feature tests. It is a rails application with a knockout.js front-end framework. We have a lot of trouble with wait_for_ajax. We constantly have tests fail because of ajax, and our developers sometimes have to put wait_for_ajax in sometimes three or four times.
This can't be the correct way to do this. What is the correct way to wait for ajax calls in rspec tests?
The hard truth is that javascript tests in capybara are painful and slow.
The only way we can determining if an ajax request if the ajax requests are finished is though hacks like this:
module JavascriptTestHelpers
def wait_for_ajax
Timeout.timeout(Capybara.default_wait_time) do
loop until finished_all_ajax_requests?
end
end
def finished_all_ajax_requests?
page.evaluate_script('jQuery.active').zero?
end
end
I would be really happy if someone proves me wrong. Its almost impossible to get a handle on a specific ajax request unless you do a crazy hack like assigning the promises to the global object. In general this seems to be problematic no matter what the language when automating web browsers.
Running tests in parallel can help a bit with the slowness.
Thoughbot has a really good blog post on some of the common gotchas of capybara JS test which can cause "flapping" tests.
I think that for client heavy applications a javascript test suite in Mocha, Jasmine or (shudder) QUnit is a necessary compliment.
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.
I'm trying to get the best codecoverage/development time result
Currently I use rspec+shoulda to test my models and rspec+capybara to write my acceptance tests.
I tried writing a controller test for a simple crud but it kinda took too long and I got a confusing test in the end(my bad probably)
What`s the best pratice on controller testing with rspec?
Here is a gist on my test and my controller(one test does not pass yet):
https://gist.github.com/991687
https://gist.github.com/991685
Maybe not.
Sure you can write tests for your controller. It might help write better controllers. But if the logic in your controllers is simple, as it should be, then your controller tests are not where the battle is won.
Personally I prefer well-tested models and a thorough set of integration (acceptance) tests over controller tests any time.
That said, if you have trouble writing tests for controllers, then by all means do test them. At least until you get the hang of it. Then decide whether you want to continue or not. Same goes for every kind of test: try it until you understand it, decide afterwards.
The way I view this is that acceptance tests (i.e. Cucumber / Capybara), test the interactions that a user would normally perform on the application. This usually includes things like can a user create a specific resource with valid data and then do they see errors if they enter invalid data. A controller test is more for things that a user shouldn't be able to normally do or extreme edge cases that would be too (cu)cumbersome to test with Cucumber.
Usually when people write controller tests, they are effectively testing the same thing. The only reason to test a controller's method in a controller test are for edge cases.
Edge cases such as if a user enters an invalid ID to a show page they should be shown a 404 page. This is a very simple kind of thing to test with a controller test, and I would recommend doing that. You want to make sure that when they hit the action that they receive a 404 response, boom, simple.
Making sure that your new action responds successfully and doesn't syntax error? Please. That's what your Cucumber features would tell you. If the action suddenly develops a Case of the Whoops, your feature will break and then you will fix that.
Another way of thinking about it is do you want to test a specific action responds in a certain way (i.e. controller tests), or do you care more about that a user can go to that new action and actually go through the whole motions of creating that resource (i.e. acceptance tests)?
Writing controller tests gives your application permission to lie to you. Some reasons:
controller tests are not executed in the environment they are run in. i.e. they are not at the end of a rack middleware stack, so things like users are not available when using devise (as a single, simple example). As Rails moves more to a rack based setup, more rack middlewares are used, and your environment deviates increasingly from the 'unit' behaviour.
You're not testing the behaviour of your application, you're testing the implementation. By mocking and stubbing your way through, you're re-implementing implementation in spec form. One easy way to tell if you're doing this; if you don't change the expected behaviour of url response, but do change the implementation of the controller (maybe even map to a different controller), do your tests break? If they do, you're testing implementation not behaviour. You're also setting your self up to be lied to. When you stub and mock, there's no assurances that the mocks or stubs you've setup do what you think they do, or even if the methods they're pretending to be exists after refactoring occurs.
Calling controller methods is impossible via your applications 'public' api. The only way to get to a controller is via the stack, and the route. If you can't break it from a request via a url, is it really broken?
I use my tests as an assurance the my application is not going to break when I deploy it. Controller tests add nothing to my confidence that my application is indeed functional, and actually their presence decreases my confidence.
One other example, when testing your 'behaviour' of your application, do you care that a particular file template was rendered, or that a certain exception was raised, or instead is the behaviour of your application to return some stuff to the client with a particular status code?
Testing controllers (or views) increases the burden of tests that you impose on yourself, and means that the cost of refactoring is higher than it needs to be because of the potential to break tests.
Should you test? yes
There are gems that make testing controllers faster
http://blog.carbonfive.com/2010/12/10/speedy-test-iterations-for-rails-3-with-spork-and-guard/
Definitely test the controller. A few painfully learned rules of thumb:
mock out model objects
stub model object methods that your controller action uses
sacrifice lots of chickens.
I like to have a test on every controller method at least just to eliminate stupid syntax errors that may cause the page to blow up.
A lot of people seem to be moving towards the approach of using Cucumber for integration testing in place of writing controller and routing tests.
After some time of doing Cucumber & RSpec BDD, I realized that many of my Cucumber features are just higher level view tests.
When I start writing my scenario and then go down to RSpec, I don't ever write view specs, since I could just copy and paste part of the scenario, which would be ugly dupliacation.
Take this scenario for example
Scenario: New user comes to the site
Given I am not signed in
When I go to the home page
Then I should see "Sign up free"
I know that this isn't directly testing the view, but writing separate view spec to check for the same thing seems redundant to me.
Am I approaching Cucumber wrong? What exactly should I test in view specs?
Should I write them for every single view, for example testing views for actions like
def show
#project = current_user.projects.first
end
or should I just test more complex views?
It's a widely-accepted (and in my opinion, incorrect) Cucumber philosophy that views should never be tested within RSpec. The argument goes that since the behavior of the view can be described in Cucumber, RSpec should stick to what it knows best -- Models and Controllers.
I argue that the "human-readable" aspect of Cucumber makes some aspects of view-speccing important. For instance, I find view specs to work very well when working in parallel with a front-end developer. If a JavaScript developer knows that he'll want to hook into a selector on your page, it's important that your view provides that selector.
For example:
describe 'gremlins/show.html.haml' do
context 'given it is after midnight' do
it 'has a #gremlin_warning selector' do
Time.stub!(:now).and_return(Time.parse '2010-12-16 00:01:00')
rendered.should have_selector '#gremlin_warning'
end
end
context 'it is before midnight' do
it 'does not have a #gremlin_warning selector' do
Time.stub!(:now).and_return(Time.parse '2010-12-16 23:59:00')
rendered.should_not have_selector '#gremlin_warning'
end
end
end
Note that the specs do not describe the content, they are willfully brief, and they do not describe interaction behaviors. Because the view is the portion of your application that will change the most, view specs should be used sparingly.
tl;dr: View specs are for communicating a contract to other developers and should be used sparingly (but nonetheless should be used).
Personally, I never use view specs when using Cucumber. To me, acceptance tests make a lot more sense, and my complex views are generally Javascript-focused and cannot be tested using view specs.
Don't use view specs for anything, ever. Cucumber stories -- or even RSpec integration tests -- do that better. The examples bobocopy gives are good ones for the case he postulates, but they should be rolled into Cucumber stories/integration tests, not left on their own.