I'm trying to run some tests on Ruby on Rails, but I don't know how to stay logged when testing. I tried :
setup do
sign_in FactoryGirl.create(:admin)
end
But I get an error (duplicate), because it's running before EACH tests.
duplicate key value violates unique constraint "index_users_on_email"
https://github.com/plataformatec/devise#integration-tests
How can I do for be logged only once in all tests ?
Had this as a comment but couldn't get formatting on it so put it here.
Why do you want to log in only once for all the tests?
In theory, the point of isolated testing is to have each unit run as if it were a single interaction.
If you wanted to call something a single time, before the entire suite, you could put it in the spec helper:
config.before(:suite) do
# Do Something Once
end
Are you talking feature specs? Models? Controllers?
But looking at what you posted it appears that you are probably talking about a feature spec, in which case, I would say do not do that. Let the user login for each spec.
Side Note:
Noticing the error you have, you need to make sure you clean your DB before you run each spec. Check out Database Cleaner Gem for this. This will allow you to have that user recreated for each spec.
Related
Using Paper Trail, I've built a change tracking element to my app. Works great in production. One aspect is that it uses the 'whodunnit' field to pull the user name to show which user made the change.
I've looked at the documentation (https://github.com/airblade/paper_trail) and I see the notation about rspec and whodunnit, but I didn't think the reference meant the 'whodunnit' field is not available, only that it would be nil'ed between tests.
Details:
I'm using the test helper for rspec, and I have the rspec feature test setup with
"..., versioning: true do"
Moreover, in debugging while running the test, I can see all the other fields for the event/change are there and saved in the database, only whodunnit is not being saved. Interestingly, I'm only having problems in test; no problems in production, works fine there, just doesn't work in test. And of course, I have
before_action :set_paper_trail_whodunnit
set (in my application controller, not the specific controller, but I moved it just to see if it makes a difference, and unsurprisingly, it doesn't).
EDIT:
I should have mentioned that I checked to confirm that there is a column 'whodunnit' in the test database while the tests are running. Also, there is a method current_user (as expected, otherwise it would not work in production) available in the controller.
I found this from a PaperTrail issue on Github
Unless you are running controller and / or integration specs prior to running your query it's likely that the whodunnit column is not being populated.
I ended up manually setting my whodunnit in my specs with
PaperTrail.controller_info[:whodunnit] = user.id
which kind of feels like defeats the purpose a little. But I'm running this in a unit spec vs a feature spec, so I think that's the only way to go.
I am still new to rails, but I went through Michael Hartl's book (super hepful, btw).
However, I started using Devise (also super helpful) and I had a question about testing with rspec. In Hartl's book, there are all these tests for user validations like uniqueness of email or just whether or not a user is created with valid attributes.
Are simple tests like this needed if I am using Devise?
Part of the reason I am asking is I can't figure out how to write the tests even though I know they are working. In general do you need to test gems to see if their internal functionality is working? Or can I just assume that will work and only test that a user can be created and logged in and be done with it?
I do test how I CanCan in that I test if I was redirected or not, but that seems more like testing that the rules I created are right. Testing the inner functions of Devise seems excessive?
I would consider testing the inner functions of devise to be excessive. However, if you make changes to devise, either the views, controllers, or validations, it would be appropriate then to test your changes.
I also always have request/acceptance tests that test the sign in/up part of my app.
You also asked:
In general do you need to test gems to see if their internal functionality is working?
No, this is generally not done. Things I like to look for: on the gem's github or webpage, do they link to TravisCI --- you can see if their current test suite works. In general, test at your level, not one beneath. For example, don't test that Rails works, just use Rails.
tl;dr: Jump to the last paragraph
Recently I've been trying to use RSpec's request specs to do some more targeted testing.
This is how my testing mostly looks:
general cucumber feature specification, i.e. user goes to a post with comment, upvotes on a comment and the author gets points
model specs for when the model actually has some functinality, i.e. User#upvote(comment)
controller specs where I stub most of the things and just try to make sure the code goes the way I expect
view specs for when there is something complex in the view, such as rendering a upvote link only when the user didn't already upvote, and these are stubbed as well
The problem is when I have some specific scenario which causes a bug and everything seems to work in the model/view layer where I am unable to reproduce it.
That forces me to write an integration test, which I can also do in cucumber. The problem arises once I am able to actually reproduce it, and I need to figure out why is it happening. This usually means playing around in tests, changing different things and seeing what happens.
For example create a comment that is owned by the user who is trying to upvote, try to vote with an expired session etc. However these are really huge pain to write in Cucumber, because of the need to write a scenario and then specify each step.
At this point, I prefer to write a request spec, because it is more low level and allows me to directly do stuff. The problem is, that I'm not really sure how to properly write a request spec, or what are the rules.
A simple example here is:
visit login_path
fill_in "Username", :with => user.username
fill_in "Password", :with => user.password
click_button "Log in"
vs
post sessions_path(:username => user.username, :password => user.password)
or even something more low level like
session[:user_id] = user.id # this actually doesn't work, but the idea is there
Both of these examples achieve the same thing, they'll log a user in. I know that the answer to which one to pick is based on what I need to test, but that doesn't answer the correct, conventional way to do this.
I've been trying to find something about request specs, but they're not really described anywhere. The RSpec book doesn't cover them, the RSpec documentation doesn't say anything either.
What is a correct way to write request specs? When should I use capybara and when just the Rails' #get and #post methods instead of clicking buttons and visiting paths?
For requests spec I believe the convention is to stick to testing user behaviour and interface interactions, which would mean loading the page, filling in the form etc. A website user cant set the session or interact with variables directly so neither should your request specs.
I've often been tempted to skip page loads and form interactions by posting or setting variables in request specs (for speeds sake, especially heavy ajax specs) but it really does break the purpose of a request spec.
As the comments mentioned, you should test the specific controller / view behaviour in the other spec types.
Sermon first....
I think the natural progression of YOU the test writer goes:
Controller
Model
Requests
a mix of Request, Controller and Model specs.
I know that I started looking at the controller first, cause it was easier to grasp.
You then get into Model specs, for non-happy path things...
Then you realize rspec doesn't actually render the view, so you are starting to see dumb errors in Airbrake, so you say, shoot... I need to test the views, and the workflow. Hence Request specs.
Lastly, you get older and realize, all 3 are important and should be used sparingly, but accordingly. I'm just at step 4 now... too many request specs, and you are slogging 5 mins for the whole suite on a medium sized app. sucks.
To answer your question:
I test workflow and views i need to be "seen" (with page.should or any tricky JS (jquery ui selectors for instance) with capybara in a request spec.
If i just need to make sure the controller variables are instantiated or to do something quick with a post for a non-happy path , out of workflow thing... I use the controller. E.g., POST to IPN Controller in paypal...
You'd be surprised how much this covers. This leaves you to test the models for all the whacked out stuff you need for total all the edge cases.
Honestly though, I'd say use Fixtures and Test Unit for integration tests... still like them better, faster... stronger... etc.
I'm currently writing specs for my Ruby on Rails application using Rspec and capybara with selenium to drive the browser.
While executing one of the specs I want to change the value of a session variable.
Eg: I want to set session[:location]="US" so that I can test my application while all values are seen in $. How do I go about it?
Capybara/Selenium specs are for acceptance testing. You shouldn't do any kind of mocking, stubbing or...changing session values directly. You should interact with your application from within the spec just like a normal user would do in the browser.
How the location is being set in your app? Can the user set it manually? If yes, you should do it in the spec in a before block.
It's not exacly as you say.In Cucumber scenario we have chance to test some cases, and you must have a changes to create some background for that cases like create some user in Given block or add somethink to db and etc. Sessions is the same resoures like db and i thnik you should have the chance to prepare it for tests. No metter how strong it's connected with end-user.
Imagin that you create some multistep application where you presist some info beatween steps in session. Your client couldn't even imagin his reservation wihout any of this few steps. So from this point of few it's seems to not make any seans to create acceptance test for every step separatly. But after moth your client want's add some extra super user-frandly validation on 4th step. Now he is only intresting in this side and this validation. Probably he could deal with other extra 4th steps but why? He already saw all this staff and accept it.
What you think about this point of view?
i'm daily in the process of learning new things about Rails (started learning 2 and now migrating to 3 concepts). As a project with Rails, i'm coding a browser game. Till now, i've been using fixtures to load data to my database and i've creating a custom task to recreate the db, load fixtures etc every time i need to. I have to say that i like this approach because i can easily define my monsters with weapons, bonuses etc through active record associations in features.
However, i see that people use a testing environment like RSpec for that kind of things. Although i see that RSpec is used as a language to define proper behaviour, i don't clearly see how it could help me. But since i like to do things the correct way, i'm pretty sure that there is much more for me to understand and read about it.
Therefore, i would like to ask for a solid example of how RSpec could be helpful. For instance, let's say that a user creates an alliance. Through my code, i'm checking whether this user already has an alliance, whether an alliance with that name exists, whether he has the money to create this alliance and more. Where would RSpec fit here ? What would a nice usage example be ?
Moreover, is fixtures done using RSpec in another way ?
I already know that Rails has many great programmer conveniences and i would like to harvest this one as well. But i'm still ignorant about RSpec. That is why i would appreciate some useful insight. Thank you :)
Rspec is a testing framework. It allows you to write automated pieces of code that verify that your code is actually working. For example, you could write a test to make sure that no two alliances have the same name:
describe Alliance do
it 'should not have the same name as another alliance' do
first = Alliance.create :name => "Test Name"
second = Alliance.build :name => "Test Name"
second.should_not be_valid
end
end
This code would then verify that no two alliances can have the same name - it's a way of testing that your code is actually working.
Fixtures, Factories, Mocks and Stubs are all ways of creating temporary data that can be used in tests. RSpec can use Fixtures, but it doesn't require them either. If you want to load test data into your database you can do this in whichever method best suits your needs to perform tests.
Some other testing frameworks are Cucumber, TestUnit, MiniTest and Shoulda. You should be using one already to write tests for your code. You can also read up on the others to find out which framework best suits your needs.