News for hackers. Stuff that matters.
Re:How deep are your unit tests? by Negitivefrags on Monday December 10, 2012 @04:32AM (#4898257)
The thing I really dislike are unit testing styles that use mock objects a lot.

I see some people say that you should test each object in isolation, mocking out any dependencies. That seems wrong headed to me.

I prefer my unit tests to test everything all the way down.

The only thing I would mock is the file system, which is useful for testing file loading code.

Re:How deep are your unit tests? by azylman on Monday December 10, 2012 @04:43AM (#4898284)
I prefer my unit tests to test everything all the way down.

They already have that, that's called integration testing. Unit testing is trying to test as small of a unit of code as possible - this helps you identify exactly where the error is. If all of your tests are integration tests and something fails, you have no idea which part of your stack the problem is in.

Obviously different projects require different kinds and amounts of test cases, but I prefer a mixture of both unit tests and integration tests (unit tests for small, complex blocks of logic, integration tests for most of the other stuff).

Re:How deep are your unit tests? by Silhouette on Monday December 10, 2012 @08:53AM (#4898953)
If all of your tests are integration tests and something fails, you have no idea which part of your stack the problem is in.

Not necessarily, because if you have a lot of integration tests then probably multiple ones will fail given a bug in a certain module, and the pattern of the failures might be all you need to locate the source of the problem.

One of the most successful projects I ever worked on, in robustness/quality terms, didn't really have any unit tests at all, but it had a comprehensive suite of end-to-end test cases that could be run automatically. Many of those didn't (and couldn't) have an absolute true/false outcome, either, but looking at the results they generated and applying various heuristics developed from experience, they were remarkably useful for similar reasons to unit tests.

Re:How deep are your unit tests? by discreteevent on Monday December 10, 2012 @05:12AM (#4898358)
Here are qualities of good unit tests:

1) They run fast.

2) They help us localize problems.

In the industry, people often go back and forth about whether particular tests are unit tests. Is a test really a unit test if it uses another production class? I go back to the two qualities: Does the test run fast? Can it help us localize errors quickly? Naturally, there is a continuum. Some tests are larger, and they use several classes together. In fact, they may seem to be little integration tests. By themselves, they might seem to run fast, but what happens when you run them all together? When you have a test that exercises a class along with several of its collaborators, it tends to grow. If you haven't taken the time to make a class separately instantiable in a test harness, how easy will it be when you add more code? It never gets easier.

- From "Working Effectively With Legacy Code" by Michael Feathers. (A really good book that actually does a better job of teaching design than many a book because like all good teaching it starts with the examples and abstracts from there, not the other way around.)

Re:How deep are your unit tests? by kibibyte on Monday December 10, 2012 @04:45AM (#4898293)
That's what I thought until my first summer internship at a Rails shop. Our unit test suite could take a very long time to run (on my Macbook Air dev machine, it would take 15-20 minutes to run). The slowdown came from testing ActiveRecord models with many dependencies, and that we were creating sample models. As a result, our tests hit the test database multiple times, which made them slow down.

Our solution was to start mocking as many models as we could, which really did improve test runtime.

(Slight edit: after reading the other replies, now I really understand what integration tests are for.)

Re:How deep are your unit tests? by Firehed on Monday December 10, 2012 @04:49AM (#4898302)
How many issues do you think may be hidden by mocking out the database layer? It's easy to write bad data due to a subtle bug in a query builder for example and then write garbage into the database. Mocking would make that significantly harder to catch.
Re:How deep are your unit tests? by urbanautomaton on Monday December 10, 2012 @06:29AM (#4898557)
You're quite right, query builder statements are error-prone and difficult to stub; that's why you shouldn't sprinkle them throughout your app. Rather than write things like

  User.active.in_group(x).not_replied.each { ... }
all over the place, write scopes on your User model (e.g. User.awaiting_response_for_group(x)) that represent each use case, test them thoroughly against the database, and then stub them out when testing client code. That way you only have to test the queries in one place, and you don't couple the rest of your code to your query builder.
Re:How deep are your unit tests? by smackay on Monday December 10, 2012 @06:18AM (#4898531)
To avoid getting hung up on taxonomy I much prefer defining the scope of tests with the control theory terms of Observability and Controllability, http://en.wikipedia.org/wiki/Observability. That makes it way easier to categorize tests in terms of how effective they are and gives useful starting point to determine whether the granularity of the test really is able to adequately test the desired behaviour.
Re:How deep are your unit tests? by TeMPOraL on Monday December 10, 2012 @08:41AM (#4898903)
Control theory also tells us how feedback loops are related to those two terms; a lot of discussions about Agile, etc. would be much more productive if people understood that it is the feedback loop that matters (as opposed to particular methodology flavour) and why it does.
Re:How deep are your unit tests? by d0ugal on Monday December 10, 2012 @04:44AM (#4898289)
So, you prefer your unit tests to be integration tests?
Re:How deep are your unit tests? by dale-cooper on Monday December 10, 2012 @04:39AM (#4898279)
I think that's more towards some kind of integration testing. You're supposed to test one unit independently, and then write integration tests that actually tests that the whole system works. Not saying that's the best way but i think that's how people think.
Re:How deep are your unit tests? by jrogers65 on Monday December 10, 2012 @08:28AM (#4898862)
A unit test tests a unit of code. An integration or functional test tests the interaction between multiple units of code, usually from the point of view of "user needs functionality X, functional test Y ensures that X works". Unit testing is not supposed to catch bugs, it is primarily to ensure a solid design. Integration/functional tests are primarily there to ensure that the code works.

It only makes sense to unit test code which is in the domain of architecture. This ensures that your domain model is solid.

It only makes sense to functional test code which is a concrete implementation running on top of said architecture. This ensures that the end user sees what they need to see.

One of the often quoted benefits of unit testing is that they run fast. That fact is only incidental. Not to mention the insanity of unit testing as much as you can just because they're faster to run - they are also an order of magnitude slower to write than functional tests.

tl;dr - use the right tool for the right job. Unit testing is for design/architecture. Functional testing is for concrete functionality.

Re:How deep are your unit tests? by jakejake on Monday December 10, 2012 @05:09AM (#4898349)
Technically it is called integration testing but I agree with you on the idea.

Unless there's a reason to mock something up (like simulating a fail condition from a DB or network call, or simulating other code that isn't finished yet) I prefer to just test everything as close as possible to what is actually running. The level of granularity, like the OP said, changes depending on the complexity and the critical nature of each part of the code.

Some people argue that if I make an error in function A and that causes a unit test fail for function B - that can mislead a developer into thinking function B has an error. I argue that a) it rarely misleads anybody for very long and b) if I had function B tested in total isolation with mocks then that error in function A might have slipped through unnoticed. It's tricky to mock up some combination that you weren't expecting to happen.

Obviously in ideal circumstances you would be doing both unit and integration testing. But, you have to draw a line somewhere otherwise you just write tests all day and get no production code running.

Re:How deep are your unit tests? by meaty on Monday December 10, 2012 @06:48AM (#4898594)
If you need lots of mocks, it's a sign of coupling which means a bad fundamental design.

You need to test both the components individually (unit tests) and their interaction (integration tests).

We use Commons VFS for filesystem abstraction ( http://commons.apache.org/vfs/ ) and our own port of the API for .Net.

In fact we have our own systems API (more Google AppEngine style thank say the .Net Framework or Java libraries) on which we build our software.

Re:How deep are your unit tests? by jiggy2011 on Monday December 10, 2012 @08:30AM (#4898867)
That may be true, but sometimes it can also be a pain when you are talking to everything through a load of abstraction layers.

When something blows up it can be nice just to get a simple error rather than a 20 page stack trace.

Re:How deep are your unit tests? by Silhouette on Monday December 10, 2012 @09:03AM (#4898990)
That may be true, but sometimes it can also be a pain when you are talking to everything through a load of abstraction layers.

Exactly. Sometimes the benefit of a certain kind of test does not outweigh the cost of distorting a useful design so it will support the test code. That cost might be directly in terms of performance overhead, or it can be a more subtle overhead through (for example) weakening language-enforced modularity in your architecture so you can insert mock/stub placeholders where you want them for testing purposes, which can hurt everything from maintenance overheads to the effectiveness of code reviews.

Re:How deep are your unit tests? by jiggy2011 on Monday December 10, 2012 @09:12AM (#4899031)
I think dependency injection is designed to mostly solve that problem but with that you want to program in a very specific way (e.g calling the DI framework's factory methods rather than just using "new" and a constructor method).

This makes it more difficult to retrofit to code and is sort of awkward when you are integrating with different bits of code and libraries that don't use DI.

Thus the usefulness of mocking frameworks to "force" a particular class to be a certain implementation for the purposes of testing.

Re:How deep are your unit tests? by meaty on Monday December 10, 2012 @11:03AM (#4899611)
Hint: You never have to distort a design for testing, if it's not a crock. It's a great indicator of brokeness.
Re:How deep are your unit tests? by Silhouette on Monday December 10, 2012 @01:29PM (#4900682)
That's not a hint, it's a conceit, born in the kind of fantasy world that drinks whatever folks like Bob Martin are selling and loves names like SimpleBeanFactoryAwareAspectInstanceFactory and functions no more than five lines long.

In the real world, software architecture is the servant of many masters, often including multiple kinds of testing, and sometimes you can't do everything that each of them would like all at the same time. For a start, they can be objectively contradictory: every time you add a dedicated test hook or introduce inversion of control to support unit testing, for example, you have also created additional cases that need to be considered during a code review.

However, it's important to remember that all these testing methods and design techniques are merely means to an end. They are valuable precisely to the extent that they help us build software to do useful things, and no more. If they sometimes conflict, that's OK, as long as we favour the one that most helps us to get the job done. However, things tend to go wrong if we start nerfing one aspect just because dogma says we must not compromise on another.

Re:How deep are your unit tests? by meaty on Monday December 10, 2012 @10:49AM (#4899492)
A 20 page stack trace is the symptom of another problem, not a result of decoupling.
Re:How deep are your unit tests? by jiggy2011 on Monday December 10, 2012 @11:04AM (#4899619)
True, but the most popular method of decoupling seems to be via using an abstraction layer of some kind. At some point you need to talk to a concrete "thing".

It's also difficult to know ahead of time how much abstraction is the right amount ahead of time.

For example, you abstract disk access through an RDBMS but you might want to change DBMS so you abstract that through an ORM. But maybe you want to switch away from RDBMS altogether and go with a NoSQL solution or do everything with message queues or REST APIs? Should you abstract up another level also?

Re:How deep are your unit tests? by meaty on Monday December 10, 2012 @11:17AM (#4899697)
That's vertical decoupling.

Well the point of the abstraction is that you don't care about the contents, hence the term "black box abstraction".

It doesn't matter to the interface consumer what the implementation is, just that it does what the interface says it will do.

Our VFS layer has various backends which can be picked based on the client's requirements and this covers REST APIs, RDBMS and filesystems. There are various depths of stacks and abstractions hiding behind all that but to the consumer, it doesn't matter.

If it blows up anywhere in the stack, we can throw 80 levels of stack right down to the container thread if need be, but we only care about the abstraction at the point of failure.

Re:How deep are your unit tests? by jiggy2011 on Monday December 10, 2012 @11:26AM (#4899761)
True, if all of your classes can conform to the same interface.

When you integrate some third party black box with a different interface you're probably going to have to write at least one wrapper class.

Re:How deep are your unit tests? by meaty on Monday December 10, 2012 @11:41AM (#4899871)
True also. We wrap Amazon S3's client behind our VFS layer.