How do I go about adding testing to a finished rails app? - ruby-on-rails

Right so I started a rails app [3.0.9] a while back and didn't include any testing, and now that I'm nearing the end of it, the daunting task looms. I don't actually have testing experience yet. A cardinal sin, I know, but nothing that can be done about it now other than fix it.
Luckily in my case, it's a relatively small app with just 4 models, and only a few controller methods per model. The business logic is mostly non-trivial. Where would I start testing here? Should I do cucumber tests and add RSpec to the exceptions? What combination should give me enough coverage to confidently push it to production when the time comes?

What I generally advise in a case like this (a finished site and no tests) is to write black-box tests first with cucumber. This will make sure you can have very quickly a test-suite that will cover purely the operational side: it will make sure the entire website works (and keeps working) as intended.
Only then I would start writing tests (I prefer rspec, but that is a matter of opinion), based on a need. The cucumber tests go through all layers, so everything could be covered.
With rspec you can test your models, controllers and views in isolation which is really nice, but will be a lot of work to do afterwards (although for only 4 models ...).

Rspec is awesome.
If you plan to do any UI testing then watir or selenium are very good open source tools. You can use rspec or test::unit for using watir or selenium.

Adding tests for a small app with just 4 models is not that difficult. Any test is better than nothing. RSpec or Test::Unit will do for the beginning.

Consider this an opportunity to learn a testing framework that you think you'll like and would use in future projects since the application you have written seems relatively small.
I don't know if Heckle would work or if there is something like it, but that could help you check that your tests actually are testing what you want.

Related

What are all the pieces to an effective TDD strategy?

I'm really getting frustrated with learning how to properly develop software using TDD. It seems that everyone does it differently and in a different order. At this point, I'd just like to know what are all the considerations? This much is what I've come up with: I should use rspec, and capybara. With that said, what are all the different types of test I need to write, to have a well built and tested application. I'm looking for a list that comprises the area of my application being tested, the framework needed to test it, and any dependencies.
For example, it seems that people advise to start by unit testing your models, but when I watch tutorials on TDD it seems like they only write integration test. Am I missing something?
Well, the theme "how do you TDD" is as much out there in the open as the theme "how do you properly test?". In Ruby, and more specifically in Rails, rspec should be the tool to start with, but not be done with. RSpec allows you to write Unit Tests for your components, to test them separately. In the Rails context, that means:
test your models
test your controllers
test your views
test your helpers
test your routes
It is a very good tool not exactly rails-bound, it is also used to test other frameworks.
After you're done with RSpec, you should jump to cucumber. Cucumber (http://cukes.info/) is the most used tool (again, for the Rails environment) to write integration tests. You can then integrate capybara on cucumber.
After you're done with cucumber, you'll be done with having tested your application backend and (part of) its HTML output. That's when you should also test your javascript code. How to do that? First, you'll have to Unit test it. Jasmine (http://pivotal.github.com/jasmine/) is one of the tools you might use for the job.
Then you'll have to test its integration in your structure. How to do that? You'll come back to cucumber and integrate selenium (http://seleniumhq.org/) with your cucumber framework, and you'll be able to test your integration "live" in the browser, having access to your javascript magic and testing it on the spot.
So, after you're done with these steps, you'll have covered most of the necessary steps to have a well-integrated test environment. Are we done? Not really. You should also set a coverage tool (one available: https://github.com/colszowka/simplecov) to check if your code is being really well tested and no loose ends are left.
After you're done with these morose steps, you should also do one last thing, in case you are not developing it all alone and the team is big enough to make it still unmanageable by itself: you'll set a test server, which will do nothing other than run all the previous steps regularly and deliver notifications about its results.
So, all of this sets a good TDD environment for the interested developer. I only named the most used frameworks in the ruby/rails community for the different types of testing, but that doesn't mean there aren't other frameworks as or more suitable for your job. It still doesn't teach you how to test properly. For that there's more theory involved, and a lot of subdebates.
In case I forgot something, please write it in a comment below.
Besides that, you should approach how you test properly. Namely, are you going for the declarative or imperative approach?
Start simple and add more tools and techniques as you need them. There are many way to TDD an app because every app is different. One way to do that is to start with an end-to-end test with Rspec and Capybara (or Cucumber and Capybara) and then add more fine-grained tests as you need them.
You know you need more fine-grained tests when it takes more than a few minutes to make a Capybara test pass.
Also, if the domain of your application is non-trivial it might be more fruitful for you to start testing the domain first.
It depends! Try different approaches and see what works for you.
End-to-end development of real-world applications with TDD is an underdocumented activity indeed. It's true that you'll mostly find schoolbook examples, katas and theoretical articles out there. However, a few books take a more comprehensive and practical approach to TDD - GOOS for instance (highly recommended), and, to a lesser extent, Beck's Test Driven Development by Example, although they don't address RoR specifically.
The approach described in GOOS starts with writing end-to-end acceptance tests (integration tests, which may amount to RSpec tests in your case) but within that loop, you code as many TDD unit tests as you need to design your lower-level objects. When writing those you can basically start where you want -from the outer layers, the inner layers or just the parts of your application that are most convenient to you. As long as you mock out any dependency, they'll remain unit tests anyway.
I also have the same question when I started learning rails, there're so many tools or methods to make the test better but after spending to much time on that, I finally realized that you could simply forget the rule that you must do something or not, test something that you think it might have problem first, then somewhere else. Well ,it needs time.
that's just my point of view.

What do you advice in order to test my Ruby on Rails application?

I am using Ruby on Rails 3.0.10 and I am planning to switch to the versioni 3.1 as soon as possible. With the new RoR version I am planning also to add automated tests in my application.
What do you advice in order to test my application?
Do you advice some book to read and\or software to use?
If I start to write tests for RoR 3.0.10, those will be available and compatible in RoR 3.1?
In few words, I would like to know all about testing that I can, should and "must" use to improve my applications (also to test jQuery-JavaScript code).
What do you mean by automated tests?
If you mean unit/functional/integration tests, then you should have those in place before you upgrade to Rails 3.1. They will be very helpful in finding where things break during the upgrade, and when they all pass you can have some degree of confidence that your application works again.
If by automated tests, you mean something more high level, like UI testing (which is what I interpret it as), I would suggest either Watir or Selenium. Tests like those should still function and wouldn't be affected by the underlying implementation (whether it's Rails 3.0.10 or 3.1). As long as the app still works those tests would still work.
Use Rspec 2
Use Capybara
Use Spork
Use Guard
Guard + Spork (+ Rspec + Capybara) = Automated Testing.
I don't recommend using Cucumber. Everyone loves Cucumber, but it's a lot more work than it's worth. It's a regular expression layer on top of what you can do very easily with Rspec + Capybara with the new acceptance testing feature (it was a separate gem, now it's included in rspec).
When you build your app, I recommend this:
As you're conceptualizing your models, write Rspec models test descriptions. Things like it "should save a :start_date". Start building your models first by writing tests for the attributes (which start_date values it accepts, how to handle invalid values, etc.). Then as needed, write integration tests between models. They're model tests, not unit tests. When you're writing tests for the model attributes, those are unit tests (isolated class tests). When you're testing the functionality between models (when I do user.posts.create(:title => "My first blog post"), I expect a post is created for that user), those are in my opinion "integration" tests. In Rspec, these are "model" tests.
After you get some basics of your models in, write view tests. In order to implement the assertions in your view tests, you'll need to have Spork, Guard, and Capybara setup. And then you'll need to write your Haml… and then your controller code… In the end, you'll be writing the code to make the view test pass. The idea of having both controller and view tests is overkill. With Rspec + Capybara acceptance tests, you can wrap everything into the spec/acceptance directory. Saves you time and lots of thought. In the end you test your models thoroughly, and the requests/html thoroughly.
As your app gets larger, the tests will take much longer to run. It can easily take 10-20 minutes to run all tests! That'll quickly turn you off, especially if all you want is to just fix a typo before re-pushing. To avoid this, figure out clever ways to use seed data (data you don't need to recreate between each test), or clever ways to use mock data, and setup Spork. By not having to reload the Rails server between test runs, you cut out a TON of time. And with Guard + Spork, you don't need Autotest (Autotest is outdated).
If you want to go a step further, you can then test your javascript. This is still a very new area. There are two approaches right now, 1) using Capybara with a javascript-enabled driver (selenium is the only one that really works as of this post), or 2) using jasmine. I'd wait on this one, if your app is not a "purely javascript" app.
For Javascript tests, I'm thinking building some sort of node.js/websocket layer that allows you to run jasmine tests locally against your Rails + Spork test server, on your Mac and Windows (via Parallels or VMWare Fusion or whatever), is a much better way to do view + javascript testing, because you get the whole app as it really is in production.
That's all you'll need as of now to build a solid Rails app. Hope that helps, Lance.
First of all tests must be written before code.
I suggest cover you application by tests and then switch to Rails 3.1 in your case.
I prefer use rspec and cucumber together.
This is two different approach of testing TDD(rspec) and BDD(cucumber).

RoR: Tests for beginners

I have to preface all my posts about rails: I'm a novice.
Is it necessary to write tests for my app to work properly or is it strictly for finding breaks?
Testing your app is not necessary for it to work, but it is highly recommended and a very good practice. Testing your application will help you develop a better piece of software and a much more solid application. In the Rails world BDD(Behavior Driven Development) is very used as a testing and development technique.
I recommend you two diferent testing suites:
The first one is Rspec that will help you with all your controllers, and models unit testing
Cucumber is a testing suite that will test your application as a whole(integration test), this one is great for a more "real life" testing approach
I encourage you to check both Rspec and Cucumber, there are also other great testing suites like Test Unit.
Remember, testing your application will give you great benefits!
NOTE: Rspec and Cucumber are not mutually exclusive, actually they are recommended to use in conjunction
Writing tests is not necessary in the sense that your application won't operate without them, but they are not only for keeping bugs away. If you're a novice, writing the tests should also help you to understand how everything works.
There's no reason not to write tests. Just write good tests, and don't waste time testing things that don't need to be tested (like generated attr_accessors).
It's not necessary at all but its considered by almost every ruby developer I know to be standard procedure.
I did a couple "rails apps" without testing, but as soon as I needed some real backend logic in ruby, testing helped me to understand what I was doing.
No, writing tests is not required for your application to run. It is a good practice, though, so if you are not used to writing tests I'd recommend that you start learning. It's easy and it will save you a lot of headaches on whatever platform you are using.
Just to chime in with everyone else, I'd suggest you find yourself an article about BDD and test first development. And then read up on mocking and stubbing. Wrapping your head around the why and how of it will probably convince you it's worth the time and effort.
When I first dove into the XP & RoR world I live in now I was daunted by what felt to me like test-mania but it really pays off in spades.
The first time someone had me write the test first THEN write the code we were testing I was mind blown. But I've never gone back to my previous evil ways.

Practicing BDD with integration tests -- do I need unit tests too?

At present, my development process flows like this:
I describe the expected behaviour as an integration test using using WebRat
I write the Ruby on Rails code to provide that behaviour, so passing the test
I refactor, ensuring the tests still pass at the end of the process
I write the next integration test
It seems to me that by definition, my integration tests are testing every model, controller and view that I can create. In reality, am I missing anything by not writing unit tests too?
I'm actually pretty sympathetic to your point of view here. I love Cucumber and I love RSpec -- and I use them both, but not always on the same code. For instance, I rarely write RSpec examples for Rails controllers these days, and I almost never write view specs. Most of my controllers are very similar and don't deviate much from the "stock" controller pattern -- which is already well-tested by Rails's own unit tests. Verifying the same behavior again doesn't gain much for the time it takes and the hassle of mocking all the models. With Cucumber at an integration level I can skip that mocking and get the essential verification I'm looking for. View testing is handled much more transparently in Cucumber most of the time as well. (Then I should see "foo" and so forth.)
But that isn't to say I don't use RSpec extensively in Rails. I use it for the places where my logic lives: models, controller filters, and view helpers. I also have a couple of projects that are almost all business logic, e.g. libraries or API adapters against complex third-party interfaces. For those I usually find myself using RSpec exclusively and skipping Cucumber.
As a heuristic, I'd suggest that you should strongly consider writing a unit test any time any of the following questions can be answered "Yes":
Is the code I'm writing more than trivially complicated?
Does this code exist primarily to give answers to other code?
Is this existing code that I'm refactoring (that doesn't already have a unit test)?
Have I found a bug in this code? (If so, write a unit test before fixing it so it never sneaks in again.)
Do I have to think for more than ten seconds about the most elegant way to implement this code?
Is my Spidey Sense tingling?
If none of the above is true, then maybe you can get away with just doing integration testing. Again, there are a lot of cases where that's reasonable. But if you do run into problems later, be prepared to pay the price -- and that price should include writing unit tests at any moment if they seem called for.
Integration tests are useful to verify that different parts of code are well integrated. They may involve all layers and cover all code but... when an integration test fails, will it tell you where the bug is located? I may be wrong but I don't think so. This will just tell you that there is a problem somewhere. On the other hand, when a real unit tests (written in isolation using mocks or stubs) fails, you know exactly in which unit the problem is located (this is actually the purpose of unit testing, verifying that a unit implements the expected behavior). In other words, unit tests and integration tests are both useful but they have different purposes.
Do you have any rake tasks? Custom capistrano code? Cron methods? An API? Monkeypatches? How about flex or iPhone app integration? A job runner?
In a typical Rails application, there's lots of code that isn't exercised by the HTML UI. So no, unless your app is incredibly simple, webrat tests won't be sufficient.

Does cucumber do away with the need to write unit tests?

I am a little confused by the sheer number of testing frameworks available for Ruby/ROR.
I have recently watched the Cucumber Railscasts and found them very interesting. So I started having a play and then struggled to see conceptually where I would put various tests.
It would seem to be quite possible to do everything that can be done in unit tests within Cucumber, so do I need to write unit tests or should I just write my feature definitions and concentrate on providing as good a coverage as I can get using that.
Should I create my Unit tests using Rspec or Test:Unit? When I'm testing Ajax functionality should I use Selenium or Watir?
There seem to be so many options here I am struggling to see which tools to use and where the boundaries are.
What are other peoples experiences of Cucumber and where to draw the line between writing Cucumber Integration tests and Test:Unit and/or Rspec based unit and functional tests. Is anyone aware of a good write-up on this subject suggesting where to draw lines between testing methods and the strengths and weaknesses of the various tool.
I appreciate that some of this is subjective but common approaches on how to attack this issue would be welcomed.
Use Cucumber at a high level to describe what a user should be able to see and do. Use RSpec, Test:Unit, Shoulda, etc. to write unit tests. Straight from the horse's mouth:
When you decide you want to add a new feature or fix a bug, start by writing a new feature or scenario that describes how the feature should work. Don’t write any code (yet).
...
This is when you start writing code. Start by writing a couple of lines of code to address the failure you got from Cucumber. Run cucumber again. Repeat and rinse until you’re happy with your feature. When you get down to nitty gritty details, drop down one abstraction level and use RSpec, or any Ruby testing framework, to write some specs/tests for your classes.
Cucumber is made to test your whole stack, together, as opposed to 'units'.
You need to decide where to draw the line, but a lot of under the hood stuff probably wouldn't be covered in a cucumber test. Say when signing up, I fill out a form, with my name, email, phone number, etc. A unit test might check to see that a new User will also create a new TelephoneNumber. From the user's perspective, they don't really care that it creates a new TelephoneNumber, they care that once they've signed up, they have an account and can see their telephone number.
I don't have too much experience writing cucumber tests (not yet), but I hope this helps a bit.
When a unit test fails (I mean a real unit test that tests a method in isolation using mocks), it tells you what "unit" has a problem. When an acceptance test fails, it tells you what "feature" has a problem, not where the problem is located.
When you create a rails app you get functional, interation, and unit tests by default. Cucumber is an additional test it is a way to also test the experience that your user will have. When they click the button labeled "go" they should see "success" rendered rather than a 404. This will make sure that nothing you do accidentally messes up the user experience, and that from the top to bottom your app works for the most common use cases you can think of. The other tests are meant to insure that nothing goes wrong, and that you have inspected ever model and method with a microscope. It may be possible to replicate unit tests in their entirety with cucumber, but it would be painful (and crazy slow to execute, especially if you're using selenium). The best time to write tests is when you're developing code, and the quickiest and easiest way to do that, is by using in the built-in rails testing and maybe some additional help such as shoulda, rspec, also i'm a huge fan of factory-girl. If you haven't already checked it out www.railscasts.com has a great intro to cucumber, and rspec, and factory-girl, ... I know this question has already been answered (it's no) but this is my two cents. Good luck coding!!
I have thought/struggled with this question much, and here's where I've arrived.
Cucumber first and Cucumber last. Cucumber will provide the primary test coverage.
The core model methods that do the real business work of the application should also be developed/covered with rspec/unit tests.
Why the unit tests as well?
1) The unit tests will test run much faster.
2) This core business logic may (will probably) be used in several ways beyond the current views (which Cucumber tests through). These methods ought to be hammered with all types of possible inputs and outputs directly calling the method in the test.
Why not unit test the rest of the models, and the controllers and views?
1) Cucumber already has it covered once.
2) I find that the views-controller-some-model-methods all work together to get things done (think everything exercised to log in); so I like to test them together.
I've been practicing Cucumber/RSpec for the past half year or so doing BDD.
First of all BDD is not easy to get into, it will feel unnatural at the beginning.
But once you get into it, there's no other way to do programming.
To answer your question. To test Javascript you'll need a javascript driver that can be used by Capybara which is used by Cucumber.
capybara-webkit is what all the cool kids use now these days
There's one important thing to note.
Integration tests are slow.
And unit tests are fast, but can be slow, so it's important you use the right database cleaner and you write good tests that have good isolation.
My test setup which I'm extremely happy with:
Guard for loading spork
Spork for faster tests
Cucumber for integration testing
capybara-webkit for javascript testing
RSpec for unit testing
I don't do view tests and controller tests as these are redundant in my opinion as good knowledge of XPATH willl have you writing remarkable tests that even cover your page layout and structure.
Personally I don't think that you should stop writing unit tests. As an acceptance testing tool, Cucumber should replace your functional tests and, if you writing, view tests.
Cucumber features are supposed to be simple and coupled to the real user's value a given feature has.
From my experience, Cucumber and Rspec have different appeal. Rspec appeals to me from a developer perspective because its easy to write and provides very quick feedback when something breaks. Cucumber does not appeal to me as a developer because it does not run as quickly as Rspec. However, Cucumber does appeal to me as a business stakeholder since it provides full coverage of entire features.
Do yourself a favor and keep writing unit tests.

Resources