@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. :)