I am starting a new project for a client today.
I have done some rails projects before but never bothered writing tests for them.
I'd like to change that starting with this new project.
I am aware there are several testing tools, but am a bit confused as to which I should be using.
I heard of RSpec, Mocha, Webrat, and Cucumber.
Please keep in mind I never really wrote any regular tests, so my knowledge of testing in general is quite limited.
How would you suggest I get started?
Thanks!
Thank you for all the responses! I posted a related question that may interest those who view this question in the future. You can find it here.
I prefer using Rspec and Cucumber in conjunction. I also prefer Capybara over Webrat.
Rspec is wonderful for it's rails integration and structure. It's technically behavior testing, but in practice it ends up feeling like unit testing. It also allows you to group and define "specs", or rspec tests, in any structure you like with 'describe' blocks.
Cucumber is higher level. It is what you will translate your user stories into. For instance, you may decide that your users should be able to change their password, so you'll write something like this:
Scenario: Change password
Given I am logged in
And I am on the change password page
When I fill in "p4ssw0rd" for "old_password"
And I fill in "newp4ssw0rd$$" for "new_password"
Then my password should be "newp4ssw0rd$$"
If you are working with a QA dept, you can show your tests to them, and they'll instantly know the status of any given feature, and how the feature is supposed to work. Additionally, if you have enterprising testers, they can write tests themselves, even if they are not programmers in general.
They all serve different function and if you really care about the quality of your software, you would use them all.
RSpec is more for unit testing. Unit Testing is testing the smallest part, usually your models methods.
WebRat is more for functionality testing as end user would test it from a browser. You are actually testing the interaction and test whether it returns the correct view/data.
Cucumber is more like for behaviour driven testing or end-to-end testing. It is more to test the business logic according to many different scenarios or data.
Of course you could use all of them together in conjunction. For example, I can use Cucumber to do end-to-end testing and it would involve functional testing using WebRat and Rspec as well. Hopefully this will get the idea for you to start off.
You can have a look at the most popular testing frameworks here http://ruby-toolbox.com/
Cheers
Related
Suppose you are building an API in Rails. Is it enough if we write request specs alone without the model specs, controller specs and the view specs? Why do we need unit testing if we do acceptance and functional testing or feature testing for front end web projects. I insisted on doing unit testing as it allows you to write decoupled code but my colleague is against it. What are the best practices on this in the ruby on rails community?
If you only have time to do one type of testing, and you are writing an API, then it might make sense to only do feature testing by simply calling your API endpoints. After all, it's pretty important that those endpoints return the expected results.
However, when your feature tests start breaking, you will potentially have a terrible time figuring out the source of the problems without unit tests. Is there a core piece of your software that most of your endpoints are using? Good luck refactoring that without a robust set of unit tests.
But that really speaks to what you have to figure out -- is your core set pretty stable? Are you really just adding features or new endpoints? If so, you can probably get away with a heavy feature test approach.
Rails and testing go together like peas and carrots. Here is a great resource that highlights (better than I ever could) the importance of using tests (of all degrees) in your Rails projects. Hope this helps!
Not sure about "the community", but in my opinion it depends on the complexity of the project. If it's a very straightforward API project, doing only feature tests may be fine.
But if the project becomes larger, unit tests allow you to better pinpoint errors in case anything breaks. I.e. you don't see "there's a bug somewhere in feature X" but "this or that class does not work when invoking a particular method with specific arguments".
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.
I'm new to unit/func testing in Rails 3. So I'm starting now, better late than never.
I have a method in /lib/mailingjob.rb called find_reply(body)
Right now I'm using cucumber to test this but given that this is all backend, no web interface to this, should I not be using cucumber?
I'm finding when to use RPSEC vs cucumber confusing.
Thanks
In my opinion, you need to use both. Rspec is very good for unit testing, that is testing models, controllers, views. On the other hand, cucumber is a very nice tool to check full scenarios like a user logs in, clicks a link and he is supposed to view this.
I highly advise that you take a look at the cucumber railscast from railscasts.com. Also, make sure that you use webrat and maybe something to auto load your specs like watchr(which i prefer).
I'd advise you to never use Cucumber unless you are specifically employed as a business analyst. That makes your life much easier: all your tests will be in Rspec.
Cucumber takes a toll on your productivity, and your sanity. Running parallel test environments, adding layers of abstraction and breaking your editor with its odd syntax make for lost time. I've written about this extensively on my blog:
Why Bother With Cucumber Testing?
If I didn't already have a Stack Overflow account, I would have made one JUST to write this post. I urge you to re-read #Jack Kinsella's answer
I got in to BDD about 3 months ago, fell in love with it, and quickly started using Cucumber for everything. I forced it in to every project, no matter what
Recently, I've had to learn a yet another language, and my first step was to get the testing environment set up. I came across these 3 articles:
http://robots.thoughtbot.com/post/25650434584/writing-better-cucumber-scenarios-or-why-were
http://robots.thoughtbot.com/post/25653308407/describe-the-users-perspective-ddd-acceptance
http://37signals.com/svn/posts/3159-testing-like-the-tsa
Honestly, their content isn't that important; what's important is that they hinted at an overall idea. I began to suspect that I'd been using Cucumber wrong all along, and I went hunting for answers. This morning I found your SO question, and #Jack Kinsella's blog post
#Jack comes right out and says the idea I believe those articles were tentatively circling. He also gives me the language I was looking for. I now consider his article to be the final word on the subject :)
According to him, what we've ACTUALLY been using Cucumber for is "integration testing". I never understood what that meant before
Unit testing:
How the code works internally. Math.Add(1,1) should be 2, but the website user doesn't care. Just give me a web page!
-> Use RSpec or an equivalent
Integration testing:
How different branches of the code work together to make the website. I type my name and click Log In, and should be taken to the Home page
-> ALSO use RSpec!
(Inside of RSpec, add whatever you need to handle multiple-technologies-touching-eachother. For the code-to-webBrowsers example: Capybara, Watir, etc)
Acceptance testing:
Many of us don't need it. Someone signed a contract with you saying "I'm going to write 'I can add subpages to my micro-site.' in a text file". You write me code that makes it turn green
-> Use Cucumber. Only if you have to do this kind of testing. Which you almost certainly don't
What an elegant solution. No 2nd testing environment. No steps directory and swarm of extra files!
I had a moment of "But I love how Cucumber seperates English from the code". Regular bdd does that too. "rspec --format nested" or Jasmine test results
#Jack is right. Cucumber isn't adding anything; not the way we've been using it. And it's costing a lot. To quote him:
Why not admit to yourself that you don’t do acceptance testing and that you do not need it in your projects? Swap Cucumber for pure integration tests using Capybara, and you’ll be surprised by how much more productive you can be
To complete SpyrosP's answer, there is an awesome blog post from Sarah Mei which describes a scenario where you use both Rspec and Cucumber. It is called oustide-in Behavior Driven Development and you can find it here.
However, I think most of Jack's problem can be solved by a good cucumber editor. So the problem is not Cucumber. The problem is that there wasn't a capable editor when he wrote this two years ago. But today RubyMine has full cucumber editing capability. While it is not free, it can solve most of Jack's problem: Auto completing, pointing out errors, refactoring. So you probably want to go back and check the points he raised, and see if they are still valid today.
My take so this issue many years later is very simple: If you do not know what to use now, just start with RSpec, because it is the central stone for all your testing that you will always need.
With time you will discover that two big testing needs:
Is my code still working?
Can my users still perform the actions already implemented?
As a developer I tend to think that (1) is for every single code change and (2) when I finish a feature and/or deploy.
Having two test suites is nice because during a deployment, you can sit and run a very generic test suite: Are my user features still working? Can I finally deploy this?
Indeed, it should be so generic that if something breaks in (2) you need to do some heavy research (one row missing in your tables) while a fail in (1) should pin-point the exact class with the problem.
Normally I find myself in the situation where I want separate integration+acceptance testing without the Cucumber burden. First I use RSpec tags to filter out these tests. Whenever I need more I like going for Steak+Capybara since it enables Cucumber like objectives on top of something I already know quite well.
Definitely use both. Use cucumber for user experience tests(views), use rspec for testing internals(models, etc.). You may write controller rspec tests but I think they are not necessary(try to move the logic to models).
Whatever your system is, I strongly advise you to use Cucumber because scenarios will let you and your stakeholders know the functions of your system in a clear written fashion.
You will also have your documentation ready and you'll always know where you are and where you are heading. You'll also relate scenarios with support issues in the future.
Cuke them right by the way don't use variables in scenarios, they should be understandable.
And if you want them to run fast as rspecs use poltergeist(phantomjs).
I've been tempted not use cucumber because in many cases it's not simple as rspec. However every time I understood that I needed scenarios to take full control on the project.
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.
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.