Cucumber Rocks - But it’s not a replacement for unit tests
I admit that cucumber is awesome. It apparently was the big thing at Rails Conf this year. I love that my BA can write the requirements, I can throw them into a feature file, and get feedback on my progress of the feature being done.
Cucumber is also an excellent choice for getting coverage on a legacy code base. Many of our clients have existing applications that were developed by cheap firms. They finally realize that they should have gone with a development company that writes automated tests, and works in a true agile manner. When initially looking at the code, we often get chills. There are usually zero tests. Most of the code sits in huge controller methods. We generally will use cucumber to start to get coverage for the features that the client wants changes to. We do write unit and functional tests, but we generally only assert the things we are changing. Over time, the unit and functional test coverage increases, and when we make changes we generally will refactor lots of the existing code base.
With that said, I have seen the use of cucumber on some of our projects change the way some developers code. They go from true TDD to crappy non-TDD. Many methods on the model don't have unit tests! How can we call this TDD?
I do admit that the functional tests can be a lot lighter, as you are getting coverage from the cucumber suite of tests. However, It doesn't mean that you can skip writing unit and functional tests.
This is how I incorporate cucumber into my development, while still maintaining 100% code coverage.
1. Write cucumber tests from the acceptance tests from the requirement
2. See all of the tests fail
3. Write unit tests, see them fail, write the code until the unit tests pass.
4. Write functional tests, see them fail, write code until the functional tests pass
5. Continue until I think the feature is fully implemented
6. Run the cucumber tests and see if anything still fails. - Add unit/functional tests to address failing cucumber tests. Once all tests pass, run the test coverage to ensure there are no holes (this generally doesn't happen, as I am practicing TDD).
Code Coverage - Why?
I recently got into a debate with a coworker about my requirement on an internal project that the code coverage cannot fall below 100%, or the build will break. He put up some very good points, but I'd like to spell out my thinking.
The project is an internal project we use for staffing, time entry and billing, so it is a production system, that is used for billing our clients, so I treat it as a very high priority. Unfortunately, it's an internal project, so I work on it when I can, and I get bench resources when they are free. This causes many developers to come on and off the project with no predictable pattern. I kept encountering this experience:
Fun with Math
Math is fun!
I never understand why people hate math so much. I guess I hated history & literature as much as fans of those subjects hate math. I remember always hearing that you would never use math in real life, which is just not true. I use it all the time, and this post is about one of those times.
A coworker of mine is creating an iPhone app, and whenever he encounters tricky math, pulls me in, as he realizes I have fun with it. His problem was:
given two points on a circle, find the shortest number of degrees between them
So given points at 4° and 20°, the result should be 16°. Seems easy enough, except a few fun scenarios. 356° and 4° results in 8°, and 360° and 0° are the same.
I thought through it, and my original approach was going to figure out what quadrant each angle was in, and then do some calculations to adjust the distance to keep the answer <= 180°. But then I realized that was going to be nasty, and then I remembered our good friend the radian.
Continue reading »
Get A Room! - Why Campfire Rocks
Campfire, a group chat program, allows teams to have chat rooms, and search the old chat content. I used campfire about a year ago, right before we were going live on a project. I hated it. Here's why:
- There were about 6 of us in the room, and we were all pairing on different activities. I kept on having to check back into the room on things I really didn't care about. I found that as soon as my pair and I finished a task, we had to scroll through pages of chat to get caught up on the details of the other pairs' activities.
- It was a web client, so I had to actively poll for updates.
- It seemed to detract time from my already busy schedule.
- We were all rushing to finish up things for go live, and it was a new program to the team. Perhaps if we had used it all along, it may have been more useful
We recently started using it on the current project that I'm managing. I now love it. Here's why:
Review of fixture_replacement2 plugin - Update
UPDATE:
So, after working on my project for months, and getting other developers involved, I need to change my mind. I still like fixture replacement, but most of my tests require such an elaborate data set, that my tests are PAINFULLY slow. What was I thinking back in November? I guess I wasn't focused due to the Obamathon that was running through the nation at the time.
My application is an internal tool we use for staffing our projects, and is going to manage time entries and invoicing. There are many other features in the pipeline, but I'm making sure that we keep our eye on the ball, and releasing the most important features first. The problems I run into, are that most of my model methods are doing complicated queries on a data set that has a lot of possible values. To test some of my reports, I need to test the cases where there are people on various projects, vacations, holidays, out of office, etc. To ensure that the method responds correctly with all of these possible values, my data set is complicated. I have a number of test helper methods that set up some or all of my data set depending on what I am testing. This has effectively replicated fixtures, and I have lost my speed.
What are my issues:
1. Fixtures are wicked fast. Fixture replacement is not when you have large data sets. Why? Fixtures essentially load the data in the tables, then start a transaction before each test and rolls it back after each test. Fixture replacement does not get this benefit, as all data is loaded after the transaction is started. So my tests take forever....
2. Because I need complicated data sets that are reusable, My test helpers set up the data in stages, and I only load what I need. One of the problems I had with fixtures, was I always had to go the fixture files to see what data was loaded. When using fixture replacement, my test data is normally defined in a setup context of at the beginning of each test, so i can see exactly what data is on the model I'm testing. Due to my test helper setup methods, I now am constantly referring to them instead of the fixture files.
My plan:
As my project takes a few minutes to run the tests, I need to fix this, as my application will begin to be used by the entire company for time tracking, and the features will need to roll out quickly. I can't have any developer waiting minutes before each check in. This will only lead to test mutiny (checking in without running rake). So, my plan is:
1. Create a new data set in fixtures that includes an updated view of my projects (the current one is stuck in July of last year). Use mocks to mock out Date.today. I was setting an effective date as a member variable in my tests, but I like the idea of mocking it out better. I will also create some sort of visual depiction of my data set, as I am constantly trying to figure out what the application should generate, as I created my data set months ago, and generally don't have any idea of what it looks like when I am adding new features.
2. Slowly convert my tests to use my new data set.
3. Kill my old fixture replacement setup helpers
4. Only use fixture replacement for small unit tests. Most of my simple model methods can use a very simple setup with fixture replacement. The model methods that are crazy complicated can use the fixtures and date mocks.
So - I still like fixture replacement, but It is not good for large data sets. I think fixtures are still useful and their speed only sweetens the deal.....
Original blog post:
We have been using fixture_replacement2 on some of our Ruby on Rails projects. I am writing an internal application and finally switched over from using fixtures. It took a bit of time to get the tests that I had written modified to stop using the fixture data, but now I am completely fixture free. The tests are a lot easier to write, and I created a few helper methods that setup common datasets. This way, I can call a setup method to configure my data, and then - it's all good. At first I called the method test_data_blah, and was wondering why I was getting an error running any test, so now it's called data_blah. Doh!
At first I didn't like the fact that I needed to explicitly create the data for what I was working on, but then I realized that (especially for unit tests) you don't need much dependent data; usually it's one or two records. For functional tests, I found that the data setup methods rocked, as I could quickly get the data set up that I needed.I could quickly assert the content of the response, based on the data in my setup. I missed fixtures at first, but now realize that over time, they are a pain.
Topics: fixture replacement, fixtures, plugin, plugins, Ruby on Rails, Testing
Visually Indicate Develpmont Vs. Production Environments
After my BA added "My Test Project" to production, I wanted to try to prevent this kind of behavior in the future. I added "Environment: Development" in the header of the layout. This was nice, but it was so subtle, I wouldn't think it would prevent you from making the same mistake. So, I had the visual designer create 3 separate background images for Development, Staging and Production (well this one was already there). I then conditionally modified the style in the application layout head section:
<head>
<style type="text/css">
<% if RAILS_ENV == 'development' %>
body { background-image: url(/images/bkgrnd_dev.gif); }
<% elsif RAILS_ENV == 'staging' %>
body { background-image: url(/images/bkgrnd_staging.gif); }
<% end %>
</style>
</head>
Now, whenever I am in development I can clearly tell. Staging also looks different. So now, it's really easy to tell that you are in production, right before you add some crappy test data.
Topics: Rails Environment Tests
Automated Deployments Rock
I have been a developer for many moons, and have taken many systems to production. I must say that production deployments were never on my list of things that make me warm and fuzzy. This was due to the fact that they weren't automated, or the automation was poor. On a recent java project, we had a series of simple sh scripts that did the work of deployment. We deployed war files to 12 application servers and to about 60 JBoss nodes. Before the automated scripts, a developer who typed wicked fast did all of the deployments. Without him, deployments would have been a nightmare.
I learned Ruby on Rails last year, and was delighted when I found Capistarno. I wanted to share the things I love and hate about capistrano.
Continue reading »
Topics: capistrano, deployment
Testing various roles in ruby on rails
On pretty much every project I've ever been on, there have always been various roles in the system that experience different behavior. Admins can generally do everything, end users get the least functionality, and there are always a few in between that vary based on requirements. Unfortunately, all too often all possible scenarios aren't tested, or they test only positive cases for each role.
In my current Ruby on Rails project, I am checking all roles and ensuring those who should be able to do certain things are able to, and those that shouldn't are unable to. What I have found, is that usually, the Admin and one other role can usually do a set of things, and every other role can't. So, I find that I set up my tests the following manner:
['root','hr'].each do |role_name| context "logged in as #{role_name}" do setup do login_as_user(role_name) end should 'index' do get :index assert_response :success # other assertions end end end
Topics: Ruby on Rails testing role, Testing
What makes a good requirement document for an agile project
As a developer, I start from requirements. I have worn project management and business analyst 'hats' on many projects (but I am a geek, as I really enjoy the developer hat the most). My coworker, Alice Toth, has come up with a pretty awesome template and style of writing requirements that seems to be perfect for the agile development methodology. Too often, I see struggling projects struggle, because their requirements suck. I look at their "requirements" and they are nothing more than a picture with a bunch of notes. The developers have so many questions, and in general, all people involved (client, developers, BAs, IAs and testers) don't have a good understanding of the system as a whole, and what are the various personas that use the system.
I have worked on projects that have used Use Cases and Functional Specifications, but these never seem to convey all the necessary information for all involved. They tend to be very verbose, and they are really not fun to write, read or manage. A good requirement should tell each audience member exactly what the expected functionality is, and never generate a myriad of questions from all involved. It's often difficult to solicit information from a client, but documenting for developers should never be that hard. Here is a recap of what a good requirement is:
Topics: agile, Requirements
A Java Programmer’s transition to Ruby on Rails
There is much out there on the topic of migrating to Ruby on Rails for an experienced Java programmer. I figured I'd add my two cents, as I have finally drunk the Kool-Aid. I switched to Ruby on Rails late last year, and developed a subscription and content management system in Ruby on Rails, went back to a Java project, and then back to Ruby on Rails. The switch back to Java gave me an interesting insight into the things I love and hate about both development platforms.
Topics: Java, Ruby on Rails, Training
About Pathfinder
Follow the Blog
-
Get a monthly update on best practices for delivering successful software.
Subscribe via email
Subscribe via RSS
Categories
Topics
Archives
- July 2009
- June 2009
- May 2009
- April 2009
- March 2009
- February 2009
- January 2009
- December 2008
- November 2008
- October 2008
- September 2008
- August 2008
- July 2008
- June 2008
- May 2008
- April 2008
- March 2008
- February 2008
- January 2008
- December 2007
- November 2007
- October 2007
- September 2007
- August 2007
- July 2007
- June 2007
- May 2007
- April 2007
- March 2007
- February 2007
- January 2007
- December 2006
- November 2006
- October 2006
- September 2006
- August 2006
- July 2006
- June 2006
- May 2006
- April 2006
- March 2006
Blogroll
Recent
- Elements of Testing Style
- Aesthetics and Web Design
- Asterisk-Java Testing with Groovy
- 3 Misuses of Code Comments
- Fluently NHibernate
- Digging a Hole and Covering it with Leaves — The Software Development Version
- The Importance of User Experience - Do You Understand It in Your Bones?
- Writing Your Own Protocol With NSURLProtocol
- What’s In Your Dock: iPhone edition
- Feature Fatigue


