Re: Static Type Checks are not Tests
Posted: Jul 21, 2007 5:16 AM
> > The testing burden in dynamically typed languages is
> > greater than the testing burden of statically typed
> > languages, provided that you do functional testing for
> > your requirements. Actually, the testing burden is
> > in both cases.
> I've thought about it, and I've decided that static type
> checks are not tests. Tests are dependent on codepath.
> Each test excerises a different codepath (well,
> , more-or-less, some may validate that several different
> inputs have the same codepath). While static type
> checking is completely independent of codepath.
> More generally, tests are purely empirical, while static
> type checks are purely deductive.
> The point of my comments is that static type checking
> immediately detects a class of errors that I commonly see
> in my own code that are very difficult, or even
> impossible, to detect via testing except by chance.
> Unit tests are not enough, because often times the place
> where the error is introduced (e.g., a member variable is
> set to a tuple instead of an integer) is often distant,
> both within the code and within execution of the program,
> from where the error causes failure (when arithmetic
> operations are attempted on the tuple). Only integrated
> testing can detect these errors, and even then a huge set
> of tests is required. Unless, of course, you specify the
> types of the member variables on the object and validate
> them at runtime or check all of them in your tests. In
> which case you've lost both the time savings and
> flexibility gain of dynamic typing.
When I argue that type checks are tests I'm not saying that we should do away with types. I'm just pointing out that typing and traditional testing are connected far more than people think.
To me, an automated test is a machine verifiable boolean statement about a program or a piece of a program. So, when I can say, in a Java program, that an instance of Integer can never be referred to by an HttpServletRequest field because they aren't type conformant, I'm basically doing the same thing as I would be if I said that Math.abs(-1) is 1, or Foo.bar(12) is 13 if Foo.staticThing is 1.
All of these are statements about programs. Sure, the first one is more global in scope than the other two, but I think see them as a part of the same thing is valuable because it's possible to extend languages so that they blur what has been seen as a hard line between type systems and tests.