@Roy is there an easy way differentiate between unit and integration tests, given a unit-of-work can span multiple classes and functions? Should we be using application layers as boundaries?
Two comments.
First, uou did not include "isolated" in the list of criteria. A mistake?, or do you share the view that unit tests need not be isolated (as long as the framework is aware of the dependencies, and thus still able to isolate defects).
Second, I would personally add "example" to the definition. A unit test is an example of correct system behavior and correct API usage. Often unit tests are the best documentation available. (And, if the framework allows return values, a unit test also produces an example of a correct runtime object state that might serve as the fixture of another next test, given the framework allows that also.)
Thats about the best I have heard so far! But I am not sure I like the
"can span multiple classes"
As that sounds more like an integration test.
I always feel that unit tests should be very focused, and any dependencies should be mocked or stubbed out.
So, what makes it different from some other (non-unit) test?
Thanks,
Alex
'In-memory' implies no hit to any external process/database.
So what will be the name for 'Unit tests' hitting the database and/or other process ?
Raghuraman, Alex et all:
I added the difference form integration test to the post itself.
So, if I use in-memory database and test half of my application (business facade, business component, data access classes) that is still unit-test ?
"A unit of work is any functional scenario in the system that contains logic" - I don't know ...it seems blurred to me.
I participated in a training class on testing in which the instructor used the term "microtesting" instead of unit testing. The term "unit testing" has been abused so much that it now has a nebulous meaning. Microtest does not suffer from that, and the "micro" helps imply small and focused in scope.
So if I call User.IsLovely and this call, in one scenario, uses in-memory data without touching a database, I have a unit test?
Okay, so what if, depending on the application configuration, this call may result in a call to a database? No longer a unit test, fine...
So what if the database is in-memory? What if the 'database' is just a key-value store? Does the 'database' have to speak SQL? Is accessing data via an ORM the same as using a database? If the ORM uses an in-memory store?
I can't see how it makes sense to say that if a database is somehow called then our test is no longer a unit test. Surely we build layers and abstractions in order to not have to consider what's beneath them?
If we are going to consider time to run, then fine, we have two different classes of tests: fast- and slow-running. But they're not necessarily testing different kinds of logic. The difference is purely in the implementation. We're not supposed to be considering the implementation: we're concerned with external appearance, aren't we?
I'm not happy with the (to me) arbitrary classification of tests into 'unit', 'integration', etc. Tests are tests. They isolate parts of the system, exercise them and determine whether they perform as expected.
If you want to split your tests up into fast- and slow-running in order to make it more likely that you'll bother running them often (by picking the fast-running set), that's fine. But I prefer to either:
* Find ways to ensure that slow-running tests don't run as slowly, e.g. when testing code which uses a database, wrap the test in a transaction which is rolled back during tear down.
... or ...
* Mock the slow stuff. If you need to simulate stuff running slowly, mock the clock.
*shrug*
So now I need to use a ram-disk for any unit test that happens to involve the filesystem even if it does so in a tightly controlled and reasonably isolated manner?
Most of the rest is fine but I don't think a unit test is necessarily in-memory. Instead of saying that a unit test is in-memory, perhaps you could say that it has a small and finite number of controlled variables and that it can make strong assumptions about the deterministic behaviors of all components that are exercised with the possible exception of the test subject.
I'm not really sure about the 'span multiple classes' bit. Seems to me that in a object oriented design what we're aiming for is each class being a coherent unit.
Having said that I don't think you necessarily need to mock out all the dependencies, but personally I think a test ought to focus on the behavior of just the one class
I like these definitions for the most part, but any form of threading precludes my test from being a unit test? That seems a bit harsh.
I'm not happy with the (to me) arbitrary classification of tests into 'unit', 'integration', etc. Tests are tests. They isolate parts of the system, exercise them and determine whether they perform as expected.
I guess that you doesn't mean 'unit test is more preferred to integration test' by this post.
Tomorrow I'll refer your definition at some meeting. It can be very helpful. Thanks in advance. :)