Agile Zone is brought to you in partnership with:

Jerry is a DZone MVB and is not an employee of DZone and has posted 6 posts at DZone. You can read more from them at their website. View Full User Profile

Sucking Less: Checking In More Often

03.22.2010
| 6680 views |
  • submit to reddit

I'm fairly fearless when coding, which means that about once a week, I delete a huge chunk of something I should've kept, or change something into something unrecognizable, thereby inadvertently breaking a dozen unit tests. When I discover the problem, usually about 4 hours later, I no longer have any idea what I did that made the bad thing happen. Then I spend another 2 or 3 hours figuring out what I broke and fixing it.  Ugly.

On my personal projects, I check in code every time I get a unit test working. My checkins are something like 15-20 minutes apart.  On projects I get paid for, though, checking in means running the whole unit test suite, and that can take 10 minutes (on a good project) or 2 hours (on a bad one)--so I don't do it very often. That's when I get into trouble.  I've been meaning to solve that problem for some time, and Joel Spolsky's blog topic last Wednesday (Joel on Software) finally kicked me in the pants.  It took 15 minutes to solve the problem; here's how I did it.

The new breed of source code control systems, distributed systems like Git and Mercurial, have had my attention for awhile, as I usually work with a team that's spread out geographically.  I regularly need to share code that's not quite ready to be delivered with another developer, and that developer is very likely in a different city.  Typically we're reduced to emailing files to each other. A distributed SCC system would resolve this, as we could sync changes between our personal development repositories, but I assumed setting up and learning a new SCC would be painful, as it has been in the past, so I never got around to it.  Joel's article on Mercurial, however, got me to thinking about it seriously, and since I had a few hours on my hands, I figured I'd give it a try.  What I didn't expect was that I'd be up and functional in 10 minutes.

I downloaded Mercurial and installed it on my main dev box, which is a Windows laptop (I know, I suck). That took about 2 minutes, including googling for the Mercurial web site (http://mercurial.selenic.com/). Then I changed to the main development directory of my current project, and typed (per Joel's tutorial at http://hginit.com/):
hg init
hg add


The first impressive thing is these commands 'just worked'.  The second is that's all that's required to set up a local repository and add an entire project to it. Really. I'm so psyched!

The "add" command was naive, because it added everything, including build output and subversion control directories (**/.svn/**).  I spent the next 10 minutes reverting my add, ("hg revert --all"), then building an "ignore" file, then adding again, and finally committing.  To shorten your search (Mercurial has great documentation, by the way--it only took me a few minutes to figure this stuff out), here's what I ended up doing.

1. I created an .hhrc file in my home directory (C:\Documents and Settings\Jerry) with the following content:

[ui]
username=jerry

editor=C:/bin/vim/vim71/gvim


The "username" entry preempts a request by the "commit" command for a username, and I prefer vi to the default editor, which is notepad.

2. In the root of my project directory, I created a .hgignore file with the following content:

syntax: glob
.svn
*.class

*.log

.hgignore

antbuild/*

build.properties


This tells Mercurial to ignore all files or directories named .svn (which is where subversion stores its status), all .class and .log files, the .hgignore file itself, the build.properties file, and anything in the antbuild directory (or its subdirectories). Mercurial ignore files support at least 3 different syntaxes for specifying files; the documentation is available on the Mercurial wiki and it's quite complete.

Finally:

hg add
hg commit


Now I'm in a position to check in locally every few minutes, but when I have a small feature complete, I can deliver via svn to the project's repository.  That's right: I'm using Mercurial locally, and SVN for the project.

On my next project, I hope to have a chance to specify that the whole team uses Mercurial for the whole project; working with another programmer who's not physically nearby just got a whole lot easier; we can exchange our updates directly with Mercurial, then push them up to a central repository independently. Sweet!

References
Published at DZone with permission of Jerry Andrews, author and DZone MVB. (source)

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Comments

Ricky Clarkson replied on Mon, 2010/03/22 - 7:52am

Heard of branches?

Josh Marotti replied on Mon, 2010/03/22 - 11:55am

10 minutes -> 2 hours to run unit tests? Why is it taking so long? Sounds like you are running integration tests (hitting the db, going through multiple layers of code, need an app-server loaded, etc?).

 

I've had over 250 unit tests that ran under 10 seconds.


So if you are working on a piece of, say, the business layer, you should be able to just run the business layer unit tests, everything passes, and push the code in.  If it breaks anything else, there is a missing unit test for that layer that you will need to add.

 

The point of unit tests are quick feedback.  If it takes more than 20 seconds, it isn't something that will be run by developers quickly which will lead to problems like what you are seeing!

Jay Spring replied on Mon, 2010/03/22 - 2:32pm

  

Ricky Clarkson replied on Mon, 2010/03/22 - 11:53pm

Now I know why it's good that your post was copied to dzone.. you delete comments.

Konstantin Scheglov replied on Tue, 2010/03/23 - 2:52pm in response to: Josh Marotti

Problem is that your users don't care about your unit tests, they want to see that at their level all things work. So, you should run high level tests - call them as you want - integration or functional, I don't care about names.

So, while you can run unit tests to see if something is broken, you still have to run high level tests to have some  confidence that at user level things still work as before, plus new implemented features.

Allen Geer replied on Tue, 2010/03/23 - 10:02pm

I'd say ya'll could probably have a more efficient enterprise if you designed your unit tests a little more intelligently. The problem with unit testing is that many people do it in an overly complicated and neurotic fashion. They test things that can't possibly have "incorrect" results. Or they test function for neurotic, impossible inputs. Unit test your functional code. You dont need to test that java is indeed returning a string, when its typed for a string. Not saying thats what you are doing here, but a lot of project manager type have used the phrase unit testing to mean inflate the time it takes to implement something by testing tautologies.

County Line Nissan replied on Mon, 2011/08/01 - 11:08am

I had a similar experience with Git. It took just a few minutes to get going and now I use it as my main source control tool at office. -County Line Nissan

Nabeel Manara replied on Fri, 2012/01/27 - 9:06am

I had a similar experience with Git. It took just a few minutes to get going and now I use it as my main source control tool at home.

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.