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

Re: [XP] Isolation and Mocks

Expand Messages
  • Elizabeth Keogh
    ... Some level of test isolation is inevitable if you re doing a top-down approach, and I believe that top-down is always valuable. Start with the UI and work
    Message 1 of 184 , Jun 1, 2007
    • 0 Attachment
      Matt wrote on 01/06/2007 02:33:33:

      > Dave wrote:

      > If someone on this list believes that true test isolation is always
      > valuable, could you do me a favor and post a logical proof?

      Some level of test isolation is inevitable if you're doing a top-down
      approach, and I believe that top-down is always valuable.

      Start with the UI and work down. Each level of code forms the customer of
      the level below, and because you haven't actually _got_ the level below
      yet, you have to use mocks or stubs in the test. When you come to code the
      next level, you know what the expected behaviour of that next unit is.
      Instead of coding for what you think you might need - as you would, say, a
      library - you're coding for what's really needed. This helps things stay
      simple, and the mock approach makes it easy to drive out responsibilities
      and role-based interfaces.

      Long example follows for anyone new to TDD / test isolation!

      --

      I have a sudoku solver. My UI should do two things:
      - listen for any changes in its Grid, and
      - apply the Strategies when the 'next' button is clicked.

      That gives me two things which it needs. I create both GridListener and
      Strategies interfaces. The UI is, or has, a GridListener, so I don't need
      to mock that, but the Strategies are used by the UI (the UI is the
      Strategies' customer). I make a mock of that.

      I describe two behaviours in my tests. One is: the UI should respond to
      the gridChanged(Cell[] cells) method by updating its display. Look,
      there's a new class - a Cell, which has both a position in the Grid and a
      number that should be displayed. I code that up. It's pretty simple, and I
      need a lot of them, so I'm not going to bother mocking it (that would be
      true test isolation, which I don't need for something so small). Now I
      write an example, something like:

      --
      // Given the UI is displayed
      sudokuUI.setVisible(true);

      // When the grid is changed
      sudokuUI.gridChanged(new Cell[] { ... some cells ... });

      // Then the UI should display the new cells
      ensureThat(sudokuUI, contains(... the cells ...)); // JUnit uses
      assertThat
      --

      The second behaviour is: when the Next button is clicked, I should tell
      the Strategies. Here's a test:

      --
      // Given the UI has some strategies
      strategies = mock(Strategies.class);
      sudokuUI = new SudokuUI((Strategies)strategies); // JMock would be
      ((Strategies)strategies.getProxy())

      // Then the UI should apply the Strategies again (mocks require
      expectations set up before hand)
      strategies.expects("apply");

      // When the next button is clicked
      sudokuUI.getNextButton().click(); // I normally do this with a special
      harness, but you get the picture

      // Check that it happened as expected
      strategies.verify();

      --

      Once these pass, I know that my UI behaves as I intended.

      I don't have any real Strategies, nor any real Grid for the Strategies to
      be applied to! But I know, now, what they do; how they interact with the
      other classes that need them.

      This helps me to avoid coding anything unnecessary when I create the
      implementations of the Strategies and the Grid. It's also helped me
      clarify my thinking over how the Strategies, the Grid and the UI behave;
      what their responsibilities are; what they need to provide to the code
      that uses them.

      (The example above won't work out exactly in practice - I've deliberately
      simplified things to get away from the problems of testing UIs - but
      hopefully it's easy to visualise what I'm talking about.)

      Cheers,
      Liz.

      --
      Elizabeth Keogh
      liz@...
      http://sirenian.livejournal.com
      http://jbehave.org


      [Non-text portions of this message have been removed]
    • Steve Freeman
      ... Now I m lost. I have a test that exercises a feature. Inside that test, some things are there for infrastructure and some things are there because they
      Message 184 of 184 , Jun 28, 2007
      • 0 Attachment
        On 25 Jun 2007, at 10:40, Paul Campbell wrote:
        > --- In extremeprogramming@yahoogroups.com, Steve Freeman
        > <smgfreeman@...> wrote:
        >>
        >> The issue for me is the intent I'm trying to express.
        >>
        >> I set expectations (a.k.a. mock) where I want to assert something
        >> about the behaviour. I stub where I just want the test to get through
        >> the code to the interesting stuff.
        >
        > I get that distinction and it seems a useful one BUT I still dont like
        > the terminology. It would make more sense to me to categorise the type
        > of test being done rather than the type of object being used as the
        > "double" or whatever.

        Now I'm lost. I have a test that exercises a feature. Inside that
        test, some things are there for infrastructure and some things are
        there because they show that the feature works. What would different
        types of test look like?

        S.

        Steve Freeman
        http://www.mockobjects.com

        Winner of the Agile Alliance Gordon Pask award 2006
      Your message has been successfully submitted and would be delivered to recipients shortly.