I tend to side with your colleagues, but only up to a point.
The issue with unit tests is that they're frequently and mindlessly written on trivial cases where cursory investigation of the code reveals that it'll work no matter what. For instance:
def add(x, y)
x + y
Along with a dozen tests to make sure that the addition will indeed work for arbitrarily chosen use-cases. Duh...
The general premise behind unit testing is: if your code contains no bugs, that's because you haven't tested enough. Now, when to write proper unit tests. Answers:
- When you're testing
- When you're debugging
- As you're developing really tricky things
Let's go through each one, supposing you're developing some kind fo web app.
You write some code to new functionality, and it should work reasonably well by now. You then reach out for your browser and verify that it works by testing more intensively, right? Bzzzt!... Wrong answer. You write a unit test. If you don't do so now, you probably never will. And this is one of the places where unit tests work very well: to test high level functionality.
You then discover a bug (who never misses any?). This brings us to point two. You dive back into the code and start following the steps. As you do, write the unit tests at key break points where having consistent and correct data is crucial.
Last point is the other way around. You're designing some hairy functionality that involves loads of meta-programming. It quickly spawns a decision tree with thousands of potential scenarios, and you need to make sure that each and every last one of them works. When writing such things, a simple looking change here or there can have unimaginable consequences further down the food chain. Say, you're designing an MPTT implementation using SQL triggers - so that it can work with multiple-row statements.
In this kind of thorny environment, you'll typically want to highly automate your tests. So you write scripts to automate the generation of test data, and run a boat load of unit tests on this test data. One crucial thing to not lose track of as you do this, is that you also need to write unit tests for your unit test generator.
Bottom line: unit tests, definitely yes. But spare yourself the ones on basic functionality - until you actually need them for debugging, or making sure some hairy functionality works properly (including, in the latter case, the tests themselves).