Loading ...
Sorry, an error occurred while loading the content.

413Re: [extremeperl] unit tester

Expand Messages
  • Rob Nagler
    Aug 29, 2005
      Adam Sroka writes:
      > I never declare the number of units. A "best practice" to someone is a
      > silly, waste of time to someone else. However, instead of writing my own
      > test framework:

      We have about 12,000 lines of unit tests. We have 1,500 lines
      (including lengthy pod) of test framework. I would estimate that
      we have 50% fewer lines of unit test code than if we had used an
      imperative framework. That's a total savings of about 4,000 lines.
      More importantly, when I look at a test, I see what it is testing.

      > use Test::More qw(no_plan);

      This actually is a very important part of the framework. You need to
      know what you are measuring before you know whether your test works or

      > Since we don't HAVE to do that, the question becomes, why would we
      > want to? I wouldn't. You'll have to explain why you would.

      The simplest explanation is that I know where to find things. One of
      the bad things about Perl is namespace pollution. We maintain a large
      number of complex applications. One day I'm working on a new
      advertising venture and the next I'm working on a tax collection
      package for surplus lines insurance. I can't be bothered to remember
      anything about what I have written a couple of months ago, let alone
      several years ago. We always qualify our code references with the
      name of the package so that we can find the object instantly. We only
      use single inheritance for the same reason.

      The other reason is that classes are an excellent mechanism for
      reuse, esp. in Perl where they are truly first-class. We use other
      mechanisms, such as closures, for other forms of sharing, but when it
      comes to managing a large collection of code, classes are simple and

      > I wouldn't because I think that the nature of testing is procedural,

      If you write procedural code, the nature of testing is procedure. The
      problem with procedural code is that it is stateful. The most
      difficult problems to debug are caused by impliciting coupling of
      shared state. If you look at the latest bOP release, you'll notice
      that I fixed several defects by changing implicit to explicit

      The way you couple your code is important. Back to the test example
      from my book (http://www.extremeperl.org/bk/test-driven-design):

      use strict;
      use Test::More tests => 9;
      use Test::Exception;
      BEGIN {
      ok(my $ema = EMA->new(4));
      is($ema->compute(5), 5);
      is($ema->compute(5), 5);
      is($ema->compute(10), 7);

      The use of $ema is implicit coupling. My book uses procedural code,
      because it is my weak attempt at "being popular" (see
      paulgraham.com). Here's how it is written in the version available in

      use strict;
      use Bivio::Test;
      4 => [
      compute => [
      5 => 5,
      5 => 5,
      10 => 7,

      Note the explicit relationship between the object created (with 4) and
      the method (compute) called repeatedly on that object. In both
      versions, the code must be executed imperatively. However, in the
      declarative version, you are shown the relationship through the
      explicit nesting of a perl data structure. You can't call the wrong
      method, becuse it is mentioned only once. You can't use the wrong
      object, because it is declared only once. In the first version, it's
      much easier to have a mistake like this.

      > needs to be an object, then I make one. That is the essence of XP - do
      > the simplest thing that could possibly work. Most unit tests in other
      > languages feel like procedures wrapped in classes anyway (e.g. TestCase
      > feels more like a collection of testThis() methods than a proper class.)

      You are correct, which is exactly the problem. When you find yourself
      typing testThis, testThat, and testTheOtherThing, you are repeating
      yourself. The rule of three says you need to get rid of the word
      "test", and there is probably a strong relationship between This,
      That, and TheOtherThing.

      > Your code is every bit as repetitive as the code you are replacing. The
      > difference is that you've dropped in a layer of abstraction
      > (unnecessarily, IMO) between your repetitive test code and the main
      > package. Test code is repetitive because testing is repetitive. You can
      > hide that, but you haven't changed it.

      There are two reasons I see for using classes: sharing and naming.
      When you name a concept, you abstract the meaning into a symbol. That
      symbol is a handle. When we use the word "chmod", we know what it
      means, even though, it is rather meaningless. The name helps us
      communicate quickly. If instead I had to speak about the abstraction
      (like an Ent) by telling a long story about its origin (as I'm doing
      now ;-), it makes if very difficult to work together. We continually
      reestablishing context, because we don't have a common vocabulary.

      It's why programming languages with positional parameters dominate the
      programming space. The shorter the name for common tasks (such as
      testing), the less the name interferes with the task itself. It's why
      drag-and-drop interfaces are popular, you don't need to remember the
      command name to invoke an operation. You simply do it. It's not
      always intuitive, but it's easy to learn. It's much harder to learn:

      mv foo bar

      than it is to "double click" on "foo" and type "bar".

      The other reason I use classes is for sharing, which to me means,
      fewer defects. Less is more. That's what OAOO means to me, anyway,
      and that's why we have our own unit test infrastructure.

    • Show all 33 messages in this topic