Does Cucumber Do Away with The Need to Write Unit Tests

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

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.

Why is cucumber considered an integration testing tool instead of a unit testing tool?

There is quite a lot of overhead in using cucumber for unit testing. Not only you have to write the features but then map them to the implementation using a separate bit of code.

Unit testing is meant to be very fast to write and very fast to execute. Naturally, cucumber focuses on end user experience, mainly due to the language used in writing a feature.

Just to refresh, a feature would contain the following:

As some stakeholder of a system

I would like to perform an activity

So that I can get some benefit out of it

Given a precondition
When I perform an action
Then something should happen

The opening paragraph, that is often ignored, is very important as it sets a context for the operation and explains why something happens. Because of the use of natural language, these things are easy to show to non-programmers in order to get some feedback.

Now, using these for unit tests would seem awkward at best. First of all, the end user focus suggests a more integration approach as the feature says nothing about mocks and UI/logic separation. I.e. a feature like the following just seems weird:

Given a that a database mock is configured with the following data
| ID | Username |
| 0 | igor |
When call FindAll on User Repository
Then I get the following user back
| ID | Username |
| 0 | igor |

Also, as your SUT gets smaller (i.e. a class), the context of operation is not as important. A User repository does not care about the context e.g. it doesn't care if the consumer of it is a normal user or a VIP user. A simple component (which it should be, following SRP), is completely deterministic based on its inputs.

So, the unit test is there to validate that what you wrote is correct, and the cucmber test is there to validate that what you wrote satisfies some higher purpose by putting a behavior of the system in a context.

BDD with Cucumber and rspec - when is this redundant?

Good question, one I've grappled with recently while working on a Rails app, also using Cucumber/RSpec. I try to test as much as possible at every level, however, I've also found that as the codebase grows, I sometimes feel I'm repeating myself needlessly.

Using "Outside-in" testing, my process usually goes something like: Cucumber Scenario -> Controller Spec -> Model Spec. More and more I find myself skipping over the controller specs as the cucumber scenarios cover much of their functionality. I usually go back and add the controller specs, but it can feel like a bit of a chore.

One step I take regularly is to run rcov on my cucumber features with rake cucumber:rcov and look for notable gaps in coverage. These are areas of the code I make sure to focus on so they have decent coverage, be it unit or integration tests.

I believe models/libs should be unit tested extensively, right off the bat, as it is the core business logic. It needs to work in isolation, outside of the normal web request/response process. For example, if I'm interacting with my app through the Rails console, I'm working directly with the business logic and I want the reassurance that methods I call on my models/classes are well tested.

At the end of the day, every app is different and I think it's down to the developer(s) to determine how much test coverage should be devoted to different parts of the codebase and find the right balance so that your test suite doesn't bog you down as your app grows.

Here's an interesting article I dug up from my bookmarks that is worth reading:
http://webmozarts.com/2010/03/15/why-not-to-want-100-code-coverage/

How to write features on cucumber tests without duplicating scenarios?

The problem here is that your scenarios are too generic and use too many technical terms, like "http status" and "rest service". None of the steps are phrased using the business language.

Either rephrase your steps to use the same language the business uses or don't use cucumber. Maybe these tests are better off as plain unit test-style tests written in the same language the REST services are written in.

If you want to practice behavior driven development you will need to learn the basics. I recommend reading BDD 101: Introducing BDD as a starting point.

Tool for integration testing to replace Cucumber

RSpec feature specs are fairly analogous to Cucumber integration tests. This requires the Capybara gem.

Moving your tests back to RSpec keep them more code-like, and you remove the extra step of needing to parse gherkin. This is a good approach if you don't really need to be sharing the specs with non-technical folks.

Thoughbot has a post that illustrates an interesting actor-based approach to feature specs: End-to-end testing with RSpec integration tests and Capybara.

The upcoming Rails 4 in Action book describes how to do feature specs in great detail. There is a GitHub repo for the code referenced in the book (the sample app is a project-tracking system) if you want to take a look.

Is there any advantage in doing unit testing along with acceptance testing?

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.



Related Topics



Leave a reply



Submit