session[] doesn't persist across cucumber steps - ruby-on-rails

Every time this step
Given /blah.../
...
cart = session[:cart] ||= Cart.new
...
end
runs in a scenario, it creates a new cart as opposed to (starting from the second call) picking one up from the session. Anyone knows how to fix that?
I am on rails 2.2.2, cucumber 0.3.98, webrat 0.4.4
P.S.
Possibly adding selenium into the circuit might help. But, since a preliminary attempt to get cucumber/selenuim working didn't succeed, I thought a little call for wisdom was in order before standing up against Dark Force of 'things that never just work'

In the way Webrat simulates a browser for testing your application you don't get any session support. This means that storing information in the session hash works for the current request, but the information doesn't get stored for subsequent requests.
Depending on a session which is created in previous scenario's isn't really a good way of testing. Each scenario you create should be self-containing. In the 'Given' steps you should make sure the prerequisites for the steps are met, if this includes setting up a shopping cart, you should do so.
Another tip: you can concatenate several Given/When/Then blocks in one scenario if you want to test further once you made some assertions:
Scenario: Foobar
Given the cart exists
When I click checkout
Then I should see '$100'
When I click 'Pay'
Then I should see 'Paid'
It seems tempting to concatenate all you scenario's in one, but this makes it harder to debug your application once the scenario fails. I prefer a lot of short scenarios!

There is not really a clean way to do this because cucumber is simulating your browser. All your browsers knows of sessions is an opaque cookie that rails politely turns into a hash for each request.
The best solution is to make your application create a cart in the usual fashion, that is logging in, selection a product and adding it to the cart. This can all be done in one step, but I would do it in separate steps because it is reusable and also because it follows more closely what your user is likely to have done.
Scenario: Foobar
Given I am a logged in user
And I add a "wizbang" to my cart
When I click checkout
Then I should see '$100'
When I click 'Pay'
Then I should see 'Paid'
If the problem is maintaining information between steps, you can use IVars that will persist through the whole senario. ie:
#cart ||= Cart.new

Related

What would be the best way to test a flow (cross controllers)?

There is a certain flow within our application that makes separate calls with related data. These are in different controllers, but interact with the same user.
We're trying to build a test to confirm that the full flow works as expected. We've built individual tests for the constituent parts, but want a test for the full flow.
E.g., we have a user who checks in to work (checkin) and then builds a widget (widgetize). We have methods that will filter our users between who have checked in, and who have widgetized (and checked in). We can build little objects with FactoryGirl to ensure that the filter works, but we want a test that will have a user check in, another user check in, and the second one widgetize so that we can confirm that our filtering methods only capture the users we want it to capture.
My first thought was to build an rspec test that simply made a direct call to checkin from the widgetize spec, and then confirm the filter methods -- but I discovered that rspec does not allow cross controller calls (or at least I could not figure out how to make it work; posts and gets to that controller were not working). Also, people told me this was very bad practice.
How should I go about testing this?
This article goes over how you can use request-specs to go through integration tests fairly well.
http://everydayrails.com/2012/04/24/testing-series-rspec-requests.html
Basically you want to use a gem like capybara so you can simulate user input and get your tests to run through your app and check to see if everything is going as you expect it to.

Given When Then Testing - Do I NEED a "When"?

I am implementing some smoke tests to our website.
I'm using a Given/When/Then format for existing automated acceptance tests/User stories. But now I want to do an initial smoke test of:
Given I'm on the homepage
Then I should see "Welcome To The Site"
Am I missing something? Is it "ok" to not have a When?
Tools Used: MVC3, SpecFlow, Nunit, Watin
It is completely valid syntax to omit any of Given, When or Then (and even to mix them in any order - specflow doesn't care.)
However, for the purpose of readability, rather than omit the When I often rephrase the Given, i.e.
When I view the homepage
Then I should see "Welcome To The Site"
I prefer to omit the Given section, because the When is supposed to indicate what the tested action is.
If the code for the step binding is the same and you want to re-use it, you can always bind your given and my when to the same method.
[Given(#"I'm on the homepage"]
[When(#"I view the homepage"]
public void NavigateToHomePage()
{
...
I think you are really missing the point here. You ALWAYS need a When. That is the thing you should be testing! What you can leave out are the Givens
What you should be saying is;
When I visit the homepage
Then I should see "Welcome To The Site"
Given When Then is really a nicer way of representing a state machine.
Given some initial state // in your case, non
When I perform some action // in your case, visiting the homepage
Then I have some final state // in your case, text displayed to a user
What I like to do is to think about all the things that must be present to allow the When to happen. In your case there doesn't seem to be any initial state. But consider if you had some web application. You would need to have an initial state before visiting the homepage (you'd need to make sure the user is logged in);
Given a user // user must be stored in the database
And the user is logged in // a logged in user must be in the session
When the user visits their homepage
Then the user should see "Welcome To Your Homepage"
An alternative scenario would be;
Given no logged in user // some people would leave this Given out, but I add it for completness
When a user visits their homepage
Then the user should be redirect to the login page
As someone correctly pointed out, most BDD tools don't actually differentiate between Given When Then but you should! The verbose nature of 'Given When Then' has been chosen as its easier for us humans to understand and helps our thought processes. A machine couldn't care less what you call the steps. With this being the case, you should make every effort to utilise the keywords correctly at all times.
Additional
BDD structure is no different to a well set-out test with arrange, act, assert.
The benefit of BDD though is that it gives a verbose structure to tests. This helps devs have domain appropriate conversations with product owners - Behaviour Driven Development.
If you aren't having these conversations, there's very little value in using BDD over normal tests practices.
I tend to see Given as the equivalent of traditional pre-conditions. When as the equivalent of the test action. And Then as the equivalent of the expected result.
Therefore, if there are no pre-conditions, I would leave out Given and simply focus on When and Then:
When I'm on the homepage
Then I should see "Welcome To The Site"
Specflow will allow you to use Given or When, but Visual Studio will also allow you to write a single class that is 1000's of lines long. Just because both are possible, does not mean either is 'right'.
Apologies for the thread resurrection...
I'd have probably gone with:
Given there is a homepage
When I view the homepage
Then I should see "Welcome To The Site"
I like to keep at least one Given, When and Then in each Scenario - don't forget you can also use And and But (not that they're particularly relevant to this scenario). You can even just make a bullet-point style list with *.
I would say:
Given I have requested the home page
When the home page loads
Then I should see 'Welcome To The Site'
You don't need a When. I like the think of the Given/When/Then keywords like
Given - This is a preparation step, do anything you need to be able to perform the test
When - This should be an action that your test will verify.
Then - This should be where you verify your test based on the action performed in the When steps.
As previously suggestion they only affect the execution order.

When doing Acceptance Testing and following BDD, do you assert database changes or just what the user sees?

I am doing acceptance testing with Steak on a Ruby on Rails application. Imagine I want to test the functionality of a form.
It should create an user if all the fields are correct.
It should not create a user if any of the fields are incorrect.
In the first case, a message will inform that the user has been created: 'The user has been created'
In the second case error messages will indicate the errors.
I can base my tests on the information displayed. That is, the first test pass if the correct message is displayed.
Or I can base my tests on the changes on the database. That is, the first test pass if the database has a new user which contains the data entered.
Or I can assert for both conditions, database should change and the appropriate message should be displayed.
What is the conceptually adequate way of testing this kind of behaviour, according to Behaviour Driven Development?
What is the practical way of testing this kind of behaviour, according to being a Pragmatic Programmer?
Generally, keep to what the user sees.
However, sometimes there's more than one user of the information. Perhaps, once the data has reached the database, another application then uses that data (fairly typical for internal projects!)
If you can't automate with both applications together, then asserting the contents of the database, or perhaps verifying resources on a RESTful URL, can be a good way to go.
If you do this, it will probably change the nature of your scenarios. Rather than saying, Then the database should contain XYZ, try something like:
Given that Fred Brown lives at 25 Warrington Grove, Springfield
When Fred orders a deckchair
Then the warehouse should receive an order:
Deckchair
Quantity: 1
To: Fred Brown
25 Warrington Grove
Springfield
So you're always looking at the capabilities of the system, rather than just the data - even if the warehouse doesn't really receive it in your scenario, you're showing why the data has to be in that particular place and form.
This way, you also leave yourself the option of using a real UI, or a RESTful URL, etc. later - the step is independent of the implementation you choose.
My BDD practices involve using Cucumber. I try my hardest to keep it to what the user sees. That is, any When and Then statements should reflect user input or user visuals.
In your case I would make sure that a success message appears afterwards, and then I would (if possible) look for data on the screen indicating the application is aware of the object. For instance, if you added a comment to a blog post you should fill in the post, hit the 'accept' button, see a 'Message Posted' success message, and then also see your content on the page as a new post.
You should back up your user-driven BDD tests with unit and sometimes controller tests to make sure everything behind-the-scenes is functioning correctly as well.
I tend to use RSpec and verify that things get added to the database, methods are returning expected results etc. But I also use Cucumber to make sure the user sees what the user is expecting to see (But I don't really let cucumber care about what's in the DB).
I hope this helps. If you aren't using cucumber yet I highly recommend it for BDD testing in conjunction with RSpec. You should check out the book (comes in electronic PDF form) - I started with that and it helped a ton with my testing practices:
http://www.pragprog.com/titles/achbd/the-rspec-book
I would agree with keeping with what the user see's, up to a point.
If there is some kind of layer that could potentially persist a value in memory, such that it might show up on the site as if it was in the db, when it's not actually been written out TO the db.. then it might be a good idea to back up your 'what the user's see's' with some checks at the db level.

Can I run multiple RSpec/Selenium tests in order without resetting browser state?

So I just started using Steak, which in turn uses Capybara, which in turn uses Selenium.
So I've heard it's good RSpec practice to split testing into lots of little it-clauses, each testing a small piece of functionality. But then it makes a test run take a lot longer, because the same steps get repeated for each test.
Say I'm testing some ajax functionality. I want to test that:
a form appears when I click a certain link
error messages appear if I submit invalid input to that form
a confirmation message appears if I submit valid input, etc.
But if I have each of those things broken into its own test case, then Selenium has to start from scratch: it has to load the same page three times, click the link to make the form appear three times, etc. It strikes me as wasteful.
What I'd like to be able to do is specify a sequence of tests that preserve browser state, so each test continues where the previous one left off. Is that possible?
It is possible.
One way is to override Capybara's visit method and keep track of the last url and only revisit when it changes.
Something along the lines of:
module Capybara
alias original_visit visit
def visit(url)
original_visit url if url != $last_url
$last_url = url
end
end
but you should only do that if you really know what you are doing...

how to create wizard forms in ruby on rails

I'm trying to understand the best options for pulling off a wizard form in ruby on rails. Ideally I'd like to have it so the application signup has a back and next button that allows the user to submit data in steps.
So in step 1 they could fill out contact info. Once they are done they could click next and be on step 2 to fill out payment info, etc. If they make a mistake, they can click back and correct it. Some steps will be required, while others will not, but you do have to make it to the last step to submit the data to the database to sign up. They then need the ability to go back and fill out the past steps in the same fashion after completion. (example: perhaps if they clicked on a profile link they could recomplete the steps in the same fashion because they didn't want to complete all the steps right away. Maybe by being given a skip button before they completed the steps to sign up?). I also need validation to happen on what steps have been completed preventing them from moving onto the next step until corrected or completed.
Option 1) I've noticed that ajax has been recommended as an option in other questions on stackoverflow. The only problem I have with it is that the user would not be able to sign up if javascript was disabled. Ideally I'd like to have it be native to ruby on rails but I'm willing to work with whatever is necessary to get it to work.
You should watch this rails cast episode on multi step forms:
http://railscasts.com/episodes/217-multistep-forms
Be prepared to rewind and watch again. He's very quick!
There are a couple of plugins that provide wizzard construction facilitation in rails.
Acts as Wizard and Wizardly seem the most popular.
The main idea is to:
* create a model in the first step
* then edit it on subsequent steps,
* applying partial validation on each step and
* having the model implement some sort of state machine.
Wicked looks promising for rails 3:
https://github.com/schneems/wicked
Have a look at wicked, explained in this rails cast: http://railscasts.com/episodes/346-wizard-forms-with-wicked?autoplay=true
An alternative approach, for simpler multi step forms especially, is to simply show-hide parts of a single form depending on the step, this way you don't hit the database on every step but rather let the user build up his object until he's ready with a valid instance.
Such an approach strongly favors using a form class instead of working with the model directly (http://blog.codeclimate.com/blog/2012/10/17/7-ways-to-decompose-fat-activerecord-models/) and you need to tweak error message rendering a bit.
Pros: only one db hit, no hassle with persisting invalid instances (not null columns, before_save sanity checks for messed up attributes), no callback hell
Cons: more html sent to user, error message tweaks, requires a well built form class to be elegant and really useful

Resources