#275 How I Test
Jul 18, 2011 | 15 minutes | Refactoring, Testing
Here I show how I would add tests to the password reset feature created in the previous episode. I use RSpec, Capybara, Factory Girl, and Guard to make request, model, and mailer specs.
- Download:
- source code
- mp4
- m4v
- webm
- ogv
Finished checking it out. Definitely a faster paced screencast, but throughout I've identified things that I can read up on and do further study with later. I love how you covered both ui testing and actual functionality (making sure the email is actually sent, not just that the email link does something visually)
Luckily I've used RSpec and Capybara before, so I was able to follow along decently enough, but at least some experience with both is probably a pre-requisite to keeping up.
Overall, loved the screencast and would love to see more. Thanks as always, Ryan!
you've outdone yourself with this one ryan. Seeing real world TDD like this is amazing.
Yeah Wow
That was so jam packed. Amazing.
I think i need to watch it in slow mo.
Great episode! As a developer that mostly works in isolation, I pick up a lot of my coding style from seeing how others do this and that on the web. One of the drawbacks is that you don't have that much of an opportunity to learn about other coders' testing styles, so this is a huge help. Hopefully push me further in a direction I know I need to go. As many times as I'm allowed, I vote (and greatly appreciate) testing included in these railscasts. Thanks again man.
Once again you've provided an excellent and educational screencast. It looks like our testing environments are quite similar. However, I've only recently gotten into testing and I was struggling with finding an approach that made the most sense to me, and controller and view specs happened to be the ones giving me the most trouble. Thank you for providing another perspective of how to tackle testing. It was a tremendous help.
Keep up the great work.
Nice Ryan!
I like how you said "close the browser and write some tests" I think thats a good start for me.
I've always wanted to know how a pro tested. I know on my next project i'll be using guard for testing.
Thank you very much for another great screencast! I agree that doing complex testing in each episode would be an overkill, but an episode dedicated to testing only from time to time is a really great idea and will encourage not-so-experienced developers like myself that testing really is the way to go.
Also you could at some point return to the idea of walkthrough screencasts like the ones you did around the release of 3.0. I personally also considered them a great help and they made me a better coder.
Thank you very much again and keep up the amazing work!
Great ! You seem to test your code pretty much like I do.
I tried to use Cucumber, I really did. But I soon realized that I spent too much time trying to write tests that read great, maintaining an horrible stack of "steps", for pretty much nothing in return.
RSpec acceptance testing is just the level of abstraction I need.
You suggest to remove this line:
config.fixture_path = "#{::Rails.root}/spec/fixtures"
But when I remove it, my tests hang at startup, I have to "kill -KILL", even I don't use fixtures at all. So I would not recommend to remove that line.
Hmm, that is strange. It is working for me as you saw in the episode. It may be something specific to the RSpec version.
I have the same problem. Only difference I can see so far is that I'm using it with rails 3.0.9 instead of 3.1.
Awesome railscast btw as usual. =)
Great screencast!
I would also recommend using a metrics tool (I use simplecov, but there are others) to automatically generate reports showing you how much of your code base is tested. It only shows what code has been executed (as opposed to actual functionality being tested), but it goes a long way toward improving your coverage.
I agree. SimpleCov is awesome. I considered including it but decided to take it out at the last minute because it made the episode too long.
im using spork and simple cov, and simple cov does not seem to cover everything. In my Model it says "No data available"
Any solutions to this :)
Nice job, This should convert some @NTDD's to @TDD's
Thanks for the great screencast.
I think You missed one thing for factory_girl.
Its problem om models with, for example,
Its very annoying while working with associated model, like
:hotel belongs_to => :city, and city have validation on uniqueness of name.
How to deal with this problems?
https://github.com/thoughtbot/factory_girl/wiki/Usage
See the section about sequences.
Great screencast! Having been passionate about testing, yet being totally self taught, it is great to see the similarities and differences in our testing process.
One thing I am curious about is: What do you think about the approach of having only one assertion per test? I have read quite often that people take this approach in TDD, but it seems like, at least when writing request specs, the responses from a failing test make it very clear which assertion failed. Perhaps this is better practice in model specs?
Yes, I'd agree with this. For unit-style tests, one assertion per test makes sense, but for integration or acceptance tests, multiple assertions are perfectly okay.
Can you explain why? It's not obvious to me.
I have looked into the one-assertion-per-test style but could not make it work for me. The test suite can easily become very slow. I have not heard a convincing argument for it. Some say it makes it much easier to determine what failed, but RSpec makes it easy to see which exact line is causing the failure.
I like your test style as you don't really refactor your tests. This leaves them really 'readable'. Great episode! Thanks you!
I personally think that it works well in models, but in request specs you end up having to refector pretty heavily to make it efficient.
I do aim for 1 assertion per test in the model though...
Loved this episode Ryan, real world TDD is something that doesn't recieve enough coverage in my opinion.
Would be great if future episodes would include tests. Perhaps not in the video (although I really enjoy TDD, it might make the episodes too long), but as sourcecode.
One episode per month in which you would do this kind of real world TDD on video, would make me write better tests.
Ryan, in your episode you commented out the whole test at some point. We could achieve almost the same effect by using :broken tag in RSpec.
I didn't know about the
:broken
tag, thanks for bringing it to my attention.This is really refreshing to see. I think seeing TDD in real action like this may do a lot to help its adoption. I've long felt that there's been a bit of a hypocrisy particularly in the Ruby community that we have it hammered into our heads that we should be doing TDD or BDD or what have you, but are barely at all shown how. I see TDD as adopting the philosophy that writing tests/specs/etc is an integral part of one's development process, not some special separate step -- and yet, all the literature (books, blogs, screencasts) illustrates development without the testing, unless the testing tools are themselves the subject matter, and then you kind of see it in isolation. Even this episode, you've titled it "How I Test" rather than just, "How I Develop." If TDD should be the default way of working, we should treat it that way rather than always talking about it as some special thing.
I've been slow to adopt TDD practices, not because I need any more convincing of their benefit, but because I feel like I don't have a real understanding how it should be done (and even moreso in Rails development, where there's a lot of support infrastructure that needs setting up to spin up the app's environment, test database, fixtures, mocking out authentication, etc, before you can even get started running the tests!) and that frustrates me. I feel guilty every day that goes by that I don't do the right thing. So I'm all in favor of more episodes like this showing the full process. I'll likely be returning to this episode a few times and taking some notes.
Also, I think multiple assertions per example is fine, provided they are closely related and the later ones are more specific (maybe depending on something being tested for in one of the previous ones).
This was the motivation behind my tweet asking if others would like to see testing integrated into every episode, almost showing how I would solve the problem in the real world.
However, the issue is that the episodes would be too long, and it would muddy whatever else I'm trying to teach. This is why I opted to keep the testing episodes separate.
I almost scrapped this episode because it was difficult to get the flow right. This is because the example was not contrived and optimized for presentation. But now I see there is a lot of value in non-contrived examples.
I have struggled with this too, but I feel my testing workflow is finally at a point where I'm confident to share it with others. The way I show how to test here is relatively easy once you get past the initial hurdle.
Ryan. I just wanted to add to this sentiment.
While there was much more to wrap my head around than one of your typical screen-casts, the process you are using here is fundamentally different than the typical fleshing out of features without tests. Seeing you test, step by step is invaluable, and I would love to see more of it.
I totally understand the issue of length for each episode. Having an episode focused on building a feature then having another focused on building it with TDD seems like a great approach. It avoids the issue of length and gives you the time to focus on both aspects (functionality and testing) adequately.
I would also like to see the tdd in every episode. i also miss in every book and many aricles the tdd style to show also the test style. It looks for me like everybody claim to do testing but nobody show how he do this. For a beginner with rails and testing this would be a good starting point to digg into the secrets of testing.
As you write the test everybody see the what code you write next.
The argument the episode becomes too long is not accepted ;-).
You can speed up things if you not switch always to the test results and not explain what to do next because of the test fail. You should only give a litte space of the screen to the test green dots or error dots (and maybe the importent part of the test fail message). Then you just do write test and implememt code. The log from the specs are shown in the same time at a split screen and do not need explaination.
Charles, thanks for writing that. It perfectly describes how I feel and what I've observed as a new Rails developer.
Very useful episode, your level of abstraction seems optimal and focused on features.
Unfortunatly often a not so obvious knowledge is needed to perform some kind of tests.
Super awesome! Ryan, have you seen any good documentation on all the methods available in capybara to do request specs?
I almost jumped into it at one point, but could never find the equivalent document for it like this one: http://guides.rubyonrails.org/testing.html
This video is a great overview, but was wondering if you knew of a capybara reference to kept open to see all available methods?
This seems like it would really slow down my development speed.
Does your company require you to write tests first?
It certainly does slow down your development speed up front, but once you get into the flow of it, ensuring that your entire code base is covered with tests is absolutely invaluable. Especially when you are working on a large project or just coming back to an old one. The amount of time that is saved from debugging is more than the time that is spent writing tests.
Of course, it is all about finding the balance that works for you. It's just a matter of trying it out for long enough to actually experience the benefits of it.
I was wondering how do you use very handy webrat view and controller marchers as those are conflicting with capybara?
I decided that webrat marchers are more important for my workflow and had to get rid of capybara.
What is your take on that?
Cheers,
Dmytrii.
Ryan,
Great screencast. Like most everyone else, I love the idea of having some Railscasts include a focus on testing. I'd really like to see more real-world TDD/BDD style projects, even if they span multiple screencasts.
As a beginner to rails and "backend programming" in general, I really cannot see the benefit of these tests... it just seems like extra work to me that can be avoided by just using the app and entering dummy data to see if everything works.
Could someone perhaps explain to me why it is important to do tests this way instead of via the browser? Like an article on why testing is important?
In my opinion, the two main advantages of testing are:
Staying focused. By writing tests upfront, and writing only the code needed to make them pass, I don't waste my time on not so important things anymore, but spend it only on things relevant to the task at hand. For this to work, you need to start with high-level tests (just like Ryan does), breaking things down into lower-level tests (model, controller) only when needed.
Regression testing. When you start modifying an app you haven't touched for months or even years, what's the best way to ensure you haven't broken anything ? Run the tests !
But of course, there are many others:
Documentation. Good, extensive testing can help other developers understand your code and contribute to the project more quickly. Even you can benefit from it.
Catching bugs before they even start to fly. Granted, writing tests / specs is slow. This is a feature :) It makes you think about your product twice, and you often find corner-cases you wouldn't have thought of by writing code upfront. Writing one spec, then, can lead you to write several more, which of course will all have to pass by the end of the day...
Dopamine. What a warm and fuzzy feeling it is to see all these green dots on the screen ! It helps you staying motivated.
I'm sure other people can think of even more benefits. Of course, there also are pitfalls, like over-testing. But with experience, you'll know when you're doing the right thing, or if something is wrong in your process.
Also, don't forget than testing really starts to pay off on big projects. What may seem useless on artificial examples or on new applications might real soon become necessary. If you start a big project without testing, you will soon regret it !
Hope this helps,
Ga
Thanks for replying Ga
In addition to the reasons that gaeldeest mentioned:
I experience that the tests run really slow, is there a way to speed things up?
In my experience, most of the slowness comes in loading the rails environment for every new test run. You can avoid this with spork. Spork will load your environment once then reload only what it needs for subsequent test runs. To me, it's a must for test driven development with rails.
In addition, you may be able to speed up the tests themselves by eliminating db calls. Ask yourself if you really need a persisted record for your test or if something in memory will do. In most cases, an in memory object with stubs for any associations will be fine for unit tests. Mocking is very powerful and helps you test your code in isolation.
This is true for me as well. Everytime Ryan is executing tests they run 4 times faster than with my computer. I know that you can speed up tests with spork, but Ryan doesn't do it in his episode and he gets 4 times faster results:
With the repo of this episode the tests run in 2 seconds on my pc.
On Ryans PC they run in 0.5 seconds or less
Thanks for the excellent screencast (and indeed the whole series).
I have been using Rails for a year now, and have found it a steep learning curve (which I am still climbing). I loved this episode because it does show just how much you need to master in order to do just a tiny part of a system in Rails. Made me feel less stupid.
Try and sit down and watch it from the point of view from someone new to Rails and see how it skips about, demanding knowledge of many gems etc. I know there is a bit of a discussion at the moment about whether Rails is too hard to get into - I think anyone who doubts that should watch this video.
This is fantastic... would love to see testing in your future episodes. You pack so much already into what you create it doesn't feel right to ask for more :) But would be so appreciated if you add tests when the functionality tested might be something out of the ordinary --- maybe not a good example, but what comes to mind are things like tests to assure background tasks function as expected, as well as maybe just dropping a best practice once in a while.
Anyway keep it up and thanks!
I'll never forget watching Pat Maddox and BJ Clark at the Ruby|Web conference in Utah do BDD pair programming live in front of the entire conference. It was amazing. Half of the {B|T}DD tricks I know came from that single demo. The other half will come from this episode. Thanks a ton Ryan!!
Do you have a link for that? That's something I would love to see!
Hi Ryan,
I've been trying and trying to start with testing, but it's very easy to get lost. Thanks for this great railscast! I will definately pick up on testing again!
I watch all your eps and love them!
Not sure if you're still looking at comments - but I see you're not using Cucumber here at all - do you ever use it with rspec? Do you think there's a benefit to using it when you're already using cabybara?
We have found Cucumber to actually slow tests down a bit more than Capybara. You can easily use Cucumber and Capybara hand in hand if you would like.
The benefit would be more human readable cucumber steps which means being able to lay out a complete feature with a client or be able to show a client your feature file and having them be able to grasp what is going on.
This is fantastic. Really helpful.
You mentioned that the feedback you got was to not include testing in every RAILSCAST episode, which is fair enough. But is there anyway you can maybe include the tests in the show notes as a middle ground - i.e. you do a Railscast on a topic and write the tests as you would have done before doing the coding and have those in show notes even if you don't talk about the tests in the episode?
Does Rails 3.1 now set render_views in the specs/request/.rb tests? In 3.0.9, it seems like only tests in spec/controllers get the right includes automatically? I cannot seem to put render_views in spec/requests/ in 3.0 and get it to work.
Hi Ryan.
Have you thought about doing an episode about testing ajax functionalities?
Cheers, Kai
Hi Ryan,
I have a small question about this testing approach. Since I'm not testing a "controller", I don't have the session/params/cookies variables to work with.
My authentication depends on storing session[:user_id] but I can't set it from the integration test since I get that session is not defined.
How can I get around that?
Thanks!
Try
ApplicationController.session[:key]
.I'm getting
undefined method 'session' for ApplicationController:Class
EDIT: I managed to get this working by stubbing the
current_user
methodApplicationController.stub(:current_user).and_return(user)
I'm trying to set up this and use rspec integration tests and I thank you for this, but isn't this always going to pass when testing?
``` sessions_spec.rb
describe "Login" do
before do
@user = Factory(:user)
ApplicationController.stub(:current_user).and_return(@user)
end
```
I cannot get capybara to work on rails 3.1.0.rc5.
I wonder if somebody knows how to make it work.
What's your problem? I'm using Rails 3.1 rc5 and it works perfectly.
What error do you get?
Spork (which I'd installed beforehand together with autotest, webrat, and rspec) crashes.
Most probably I'm missing some code to make it run correctly with capybara.
Problem is solved, not sure exactly why, but I can run Capybara now.
It is much more strict than Webrat and I have discovered some bugs in my application which did not show up with Webrat.
Thanks for this great episode.
Hi Ryan,
thanks for the great episode. After watching it it was keen trying it myself and downloaded the complete source code. After extraction I installed the bundle, did a "rake db:migrate" and tested the app in the browser, all worked fine.
When following the coding using the auth-before tree as a start I soon got this error:
I checked in the auth-after (bundle, rake db:migrate, guard) and I do get the same error. So there must be something wrong with my testing environment as the regular development environment find the user table in the browser. I am on Ubuntu Linux, I installed/updated libnotify, rb-inotify, and childprocess as guard did complain about not finding them or them being out-dated...
Any help would be appreciated.
Cheers Juergen
SOLVED:
rake db:test:prepare
Should have guessed... sigh
After creating a new migration, I always run:
which propagates any migrations to both development and test environments equally
Gread episode, thanks!
I have just one problem with this line:
mail.body.encoded.should match(edit_password_reset_path(user.password_reset_token))
It failed with:
It looks like I cannot use paths in mailer spec. Im using
rails 3.0.9,
rspec (2.6.0)
rspec-core (2.6.4, 2.6.3)
rspec-expectations (2.6.0)
rspec-mocks (2.6.0)
rspec-rails (2.6.1)
Could somebody help me to deal with this?
Not sure if this is still applicable to you, but I ran into a similar problem and was solved by adding the following code in spec_helper.rb:
Rspec.configure do |config|
config.include Rails.application.routes.url_helpers
...
end
This allows named routes to work in rspec.
I'm using this to practice
Thanks for the Railscast Ryan! I did my own "How I Test" including tests for both "remember me" and "forgot password" using Cucumber, email_spec, Delorean, etc. Hope this helps someone!
https://github.com/leesmith/decent_authentication
Hi,
I am a newbie to Rails/web programming, and am following along with your railscasts, which have been an awesome resource. However, I have come across a problem I can't seem to fix here, despite following the railscast. I get this error when running the test:
This, despite the fact that the create controller redirects to root_url, and when i do it through the browser, it works just fine. However, the test keeps wanting to route itself to the index action.
Anyone else get this error? Any ideas?
Can you post your PasswordResetsController? It seems that it has no "index" action.
Maybe you misspelled it, happens to me all the time :-S
It doens't have an index action; but it shouldn't have one. Not conceptually, and not according to Ryan's code. Even when I copy/paste his code, it gets the error. (Only in testing, not when I click it manually on the web). Maybe it's a bug in Rspec/Capybara?
This was posted a while ago, I know, but you should look at the update action in your password_resets controller and make sure that it isn't redirecting to the index.
Really great screencast.
I had a question. Am I right in thinking that you use request specs in favor of controller specs? Or, do you write controller specs too?
hi,
i always get into problems testing the content of emails send with delayed_job. it should be pretty common to do so right ? haven't found any good solution for that... tips ?
why does that not work:
?
it should work see:
http://stackoverflow.com/questions/7270741/testing-emails-with-capybara-and-delayed-job/7281393#7281393
Great episode as always Ryan. I'm dying to know -- do you ever use rspec controller tests instead of or in addition to request specs? If so, do you have any rules of thumb for when you would go to controller specs?
Great episode, Ryan, Thanks a lot> I tried it on a Windows machine with some minore modifications(added some specific gem dependencies) and everything worked as needed. Then I copy-pasted the same project on a Linux (Ubuntu 10.04) PC, changed the dependencies in Gemfile for gem 'libnotify', :group => [:test, :development], and the guard fails after running the bundle and 'guard' commandes:
@@
serge@serge-laptop:~/Development/Ruby/Rails3/auth_rememberme_with_tests$ guard
Guard is now watching at '/home/serge/Development/Ruby/Rails3/auth_rememberme_with_tests'
Guard::RSpec is running, with RSpec 2!
Running all specs
/home/serge/.rvm/gems/ruby-1.9.2-head/gems/activesupport-3.1.0/lib/active_support/dependencies.rb:234:in
load': /home/serge/Development/Ruby/Rails3/auth_rememberme_with_tests/spec/models/users_spec.rb:1: syntax error, unexpected tIDENTIFIER, expecting $end (SyntaxError)
block in load'describe "send_pas..."
... ^
from /home/serge/.rvm/gems/ruby-1.9.2-head/gems/activesupport-3.1.0/lib/active_support/dependencies.rb:234:in
from /home/serge/.rvm/gems/ruby-1.9.2-head/gems/activesupport-3.1.0/lib/active_support/dependencies.rb:225:in
load_dependency'
load'from /home/serge/.rvm/gems/ruby-1.9.2-head/gems/activesupport-3.1.0/lib/active_support/dependencies.rb:234:in
from /home/serge/.rvm/gems/ruby-1.9.2-head/gems/rspec-core-2.6.4/lib/rspec/core/configuration.rb:419:in
block in load_spec_files'
map'from /home/serge/.rvm/gems/ruby-1.9.2-head/gems/rspec-core-2.6.4/lib/rspec/core/configuration.rb:419:in
from /home/serge/.rvm/gems/ruby-1.9.2-head/gems/rspec-core-2.6.4/lib/rspec/core/configuration.rb:419:in
load_spec_files'
run'from /home/serge/.rvm/gems/ruby-1.9.2-head/gems/rspec-core-2.6.4/lib/rspec/core/command_line.rb:18:in
from /home/serge/.rvm/gems/ruby-1.9.2-head/gems/rspec-core-2.6.4/lib/rspec/core/runner.rb:80:in
run_in_process'
run'from /home/serge/.rvm/gems/ruby-1.9.2-head/gems/rspec-core-2.6.4/lib/rspec/core/runner.rb:69:in
from /home/serge/.rvm/gems/ruby-1.9.2-head/gems/rspec-core-2.6.4/lib/rspec/core/runner.rb:11:in `block in autorun'
@@@
Any idea on that?
I'm on Rails 3.1. and use Ruby 1.9.2 p0 version.
Thanks a lot.
Solved. I don't know why after copy-paste it did not work but after creating the same project from scratch everything worked fine. Thanks!
I'm new to rails, stumbling along! I've followed this tutorial and #274 but am now getting a failed example that I can't work out:
''' ruby
Guard is now watching at '/Users/andrew/Sites/app_name'
Guard::RSpec is running, with RSpec 2!
Running all specs
DEPRECATION WARNING: ActiveRecord::Associations::AssociationCollection is deprecated! Use ActiveRecord::Associations::CollectionProxy instead. (called from at /Users/andrew/Sites/app_name/config/environment.rb:5)
.F
Failures:
1) PasswordResets should email user when requesting password reset
Failure/Error: current_path.should eq(root_path)
Finished in 0.71308 seconds
2 examples, 1 failure
Failed examples:
rspec ./spec/requests/password_resets_spec.rb:4 # PasswordResets should email user when requesting password reset
'''
This seems to come up no matter what I put in the "current_path.should..." line. The only way I can get it to pass is to go
''' ruby
current_path.should eq nil
'''
But when I try the form in my browser, it does redirect to the root_path.
Here's part of my test log:
''' ruby
To reset your password, click the URL below.
http://localhost:3000/password_resets/_CdAYKLafBbLyLVLvHaLpw/edit
If you did not request your password to be reset, just ignore this email and your password will continue to stay the same.
Redirected to http://www.example.com/
Completed 302 Found in 60ms
Started GET "/" for 127.0.0.1 at 2011-09-20 19:31:11 +1000
Processing by HomeController#index as HTML
Rendered home/index.html.erb within layouts/public (0.3ms)
Completed 200 OK in 6ms (Views: 5.7ms | ActiveRecord: 0.0ms)
'''
Not sure why it says something about http://www.example.com. Did a search and none of my code appears to contain that domain, except for the Factories email address.
Also, does anyone know why I am getting a "Depreciation Warning" and how to resolve it? I'm running Rails 3.1.0 and Ruby 1.9.2.
Any help would be appreciated... thanks!
Anyone have any ideas?
Just stumbled upon the solution: get rid of webrat from your Gemfile.
Fixed many other testing issues too.
Awesome as usual. Don't forget to add
after
gem install rb-fsevent
;)
For the life of me, I cannot figure out how to get my guard logs in color. It's really hard to see without it. Tips anyone?
Maybe gem 'turn', :require => false -- it should pretty printe test output
Worth to mention that I had to add the 'type' options to make capybara work properly.
tags: paths NoMethodError undefined method 'visit'
How do you handle sections that require session info in your integration test? I have pages that call on current_user, should this be stubbed out somehow or is there a better way?
require 'capybara/rails'
capybara/rspec
was unable to load, this works fine for me.Using Rails 3.1 on Ubuntu.
Ryan, the series is amazing!
I am testing the presence of particular page elements in views and can't figure out where such views testing belongs - controller tests with integrated views or integration tests. Could you elaborate on that a little in the future episodes?
Ryan, do you use integration tests exclusively? Do you every write model tests? I'm trying to wrap my head around the entire testing process. This video has been a huge help, so thanks!
Hi Ryan, as always a great RailsCast and a lot of useful information, thanks!
I'm new to Rails and to TDD, I've a question, sorry if it's a little bit off topic: is there some reason for which you created a PasswordResetsController just to send the password reset e-mail instead of just add an action to the Users controller given it's an action highly related to users?
Thanks.
Hi Ryan. I was wondering how you test validations. Do you always do it through integration tests (like in the example below) or do you use something else?
If you do use integration tests, what's your advice to make the code cleaner/less repetitive?
Thanks for the great screencast!
I am wondering, if I use Integration testing, is functional testing necessary? And what about Acceptance testing? I am struggling to understand if you can stick to Integration testing and then just forget about Functional testing?
Thank you :)
I am working on a new app in rails 3.2.2 with rspec 2.9 and I'm getting an error when testing emails that have been sent.
In the example here ryan you use this line 'last_email.to.should include(user.email)' which worked fine before but now I'm getting an error on this which says
'Failure/Error: last_email.to.should include(user.email)
NoMethodError:
undefined method `to' for nil:NilClass'
Any thoughts on this??
Ignore this, I have sorted out the issue.
I had changed something in a method in my user.rb file which meant something in my database wasn't being set...
If I'm not mistaken this allows a blank password (and confirmation) to be submitted when resetting the password, because in this case the
validates_presence_of :password
is only called on creation of a user.It would appear that the FactoryGirl syntax has changed a bit. Instead of
Factory.define :user do |f|
f.sequence(:email) { |n| "foo#{n}@example.com" }
f.password "secret"
end
You now need something more like
FactoryGirl.define do
factory :user do
sequence :email do |n|
"foo#{n}@example.com"
end
password "secret"
end
end
Also then use FactoryGirl.create(:user) instead of Factory(:user)
Thanks!
Thanks - saved me some time this afternoon!
Hi Ryan,
This code last_email.to.should include(user.email) would check that last email was sent to the specified email. But how would you ensure that Password reset email was sent not any other email?
Ryan - Thanks for this awesome RailsCast. I was trying to figure out RSpec and this made so much sense. Please create new RailsCasts about testing as your process changes and the tools improve.
Hi Ryan,
these screencasts are really great. And this way you demonstrate is "the way" to go.
Still, being new to this (that being the reason I watch), it is a critical time in terms of adopt/not adopt and the instructions being outdated does not help.
I would suggest a notice right up top pointing this out, maybe to David Fishers post about how the FactoryGirl syntax works now.
Still, thanks also for all those other great intros,
Torsten
Interesting to see you don't use cucumber :) I don't use it.
Ryan, I'm a new rails dev and your screencasts are the best resource! Thanks for making them easy to get and search!
While following this screencast I was getting:
undefined method `visit' for #...
For my test. Turns out the current versions of Rspec and Capabara have moved the auto include of Capybara's DSL to only be included in the 'features' space of the spec tests.
You can either do the Capybara 'visit' (and other methods) into only the features tests or you can add Capybara's DSL to the request scope.
I chose to add the DSL to request scope so I could follow along.
in spec/spec_helper.rb
RSpec.configure do |config|
...
config.include Capybara::DSL, :type => :request
...
end
Hope this helps other noobs!
Thanks @bdudney -- I had the same issue, I much prefer your second solution. Thanks for saving me some time.
Thanks for pointing this out! It saved me a bunch of time!
Unbelievable. I spent my entire Saturday watching your videos on testing. Something I knew I should be doing, but never really took the time to learn. This one brings it all together. Absolutely brilliant! Thank you!
Failures:
1) PasswordResets emails user when requesting password reset
Failure/Error: click_button "Reset Password"
ActiveRecord::RecordInvalid:
Validation failed: Password is too short (minimum is 6 characters), Password confirmation can't be blank
# ./app/models/user.rb:57:in
send_password_reset'
create'# ./app/controllers/password_resets_controller.rb:7:in
# (eval):2:in
click_button'
block (2 levels) in '# ./spec/requests/password_resets_spec.rb:9:in
Finished in 14.17 seconds
167 examples, 1 failure
Failed examples:
rspec ./spec/requests/password_resets_spec.rb:4 # PasswordResets emails user when requesting password reset
On the model user I have the following validations needed for my test unit:
validates :password, length: { minimum: 6 }
validates :password_confirmation, presence: true
Any help how to get the test to pass?!
the problem is with send_password_reset method:
def send_password_reset
generate_token(:password_reset_token)
self.password_reset_sent_at = Time.zone.now
save! # this line will raise the exception
UserMailer.password_reset(self).deliver
end
before the method saves it has to set/(leave the same) the :password and :password_confirmation!
how do you do that...?
if I use:
save!(validate: false)
the test will pass. Using the above will not validate anything in the send_password_reset method. Is there's any danger of invalid information being saved to the database?!
Your spec/requests folder should be spec/features to get capybara to work. This is if you are getting a NoMethodError: / undefined method `visit' error.
click_on question.
Trying to test a link that has a pdf to a file that is on a remote server.
But click_on will fail with this error.
No route matches [GET] "/u/54803135/Resume.pdf"
As if it is cutting the full url out for some reason?
If I look at the page it is fine and the url is in the source so not sure if there is a switch I am missing to tell click_on to pass the full url to page.response_headers['Content-Type'].should eq "application/pdf"
The url is nothing special just a simple url with some numbers.
Thanks
ps wrong thread? Just let me know if there is a good site to post this type of question, new to ruby/rails.
hi there, I had some problems with factory_girl, actual versions syntax is a bit different (Link). This factories.rb accomplished the same job (as in the screencast):
you can create a user in your specs with:
I'm also using database_cleaner to get my db into a clean state for the tests (Link), because some of the changes to the database weren't rolled back after the tests when using factory_girl and I got failures in further test-runs (I needed version 1.0.1, because 1.1.1 generates a bug if using sqlite-db Link).
Adding this line to my Gemfile under the test group definition does the fix:
Database_cleaner is quite easy to setup and seems to work pretty neat.
Maybe someone runs into the same problems, it took me quite a bit of googling to get everything together with the current sw-versions, so I thought I'd post it here. Cheers!
If you don't want Factory Girl to hit your database, you can try using
build_stubbed
.If someone is in trouble with an "undefined method error" to capybara, just try to rename the requests folder to features.
Hope it help someone.
https://github.com/rspec/rspec-rails/issues/360
i keep coming back to this screencast; the best screencast on TDD i've seen so far.
Absolutely amazing screencast. I keep discovering new things I didn't know every time I watch it.
I have simple project, updated to Rails 4, and the current version of all the testing gems he used. (It also includes spork.) The readme includes some vague instructions that will make more sense if you follow along to this railscast. With the railscast and my code, you should be able to get testing working.
https://github.com/crslade/todoAuthW14
Try https://github.com/evrone/factory_girl-seeds to speed up your tests
Why is the
guard-rspec
gem in the test environment group, while on the project's README it says to put it in the development group?